From 2c441c79225e1f4412eee4300820f57c4ef5f4fc Mon Sep 17 00:00:00 2001 From: Shpuld Shpuldson Date: Tue, 27 Oct 2020 10:03:04 +0200 Subject: [PATCH 01/41] fix back button size, fix missing chat notifications being marked as read too eagerly, fix promiseinterval erroring when not getting a promise --- src/components/chat/chat.js | 14 ++++++++++---- src/components/chat/chat.scss | 11 ++++++----- src/services/chat_utils/chat_utils.js | 2 +- src/services/promise_interval/promise_interval.js | 9 ++++++++- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/components/chat/chat.js b/src/components/chat/chat.js index 34e723d0..681ba08f 100644 --- a/src/components/chat/chat.js +++ b/src/components/chat/chat.js @@ -11,6 +11,7 @@ import { getScrollPosition, getNewTopPosition, isBottomedOut, scrollableContaine const BOTTOMED_OUT_OFFSET = 10 const JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET = 150 const SAFE_RESIZE_TIME_OFFSET = 100 +const MARK_AS_READ_DELAY = 1500 const Chat = { components: { @@ -94,7 +95,7 @@ const Chat = { const bottomedOutBeforeUpdate = this.bottomedOut(BOTTOMED_OUT_OFFSET) this.$nextTick(() => { if (bottomedOutBeforeUpdate) { - this.scrollDown({ forceRead: !document.hidden }) + this.scrollDown() } }) }, @@ -200,7 +201,7 @@ const Chat = { this.$nextTick(() => { scrollable.scrollTo({ top: scrollable.scrollHeight, left: 0, behavior }) }) - if (forceRead || this.newMessageCount > 0) { + if (forceRead) { this.readChat() } }, @@ -225,12 +226,17 @@ const Chat = { } else if (this.bottomedOut(JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET)) { this.jumpToBottomButtonVisible = false if (this.newMessageCount > 0) { - this.readChat() + // Use a delay before marking as read to prevent situation where new messages + // arrive just as you're leaving the view and messages that you didn't actually + // get to see get marked as read. + window.setTimeout(() => { + if (this.$el) this.readChat() + }, MARK_AS_READ_DELAY) } } else { this.jumpToBottomButtonVisible = true } - }, 100), + }, 200), handleScrollUp (positionBeforeLoading) { const positionAfterLoading = getScrollPosition(this.$refs.scrollable) this.$refs.scrollable.scrollTo({ diff --git a/src/components/chat/chat.scss b/src/components/chat/chat.scss index 012a1b1d..f91de618 100644 --- a/src/components/chat/chat.scss +++ b/src/components/chat/chat.scss @@ -25,7 +25,7 @@ min-height: 100%; margin: 0 0 0 0; border-radius: 10px 10px 0 0; - border-radius: var(--panelRadius, 10px) var(--panelRadius, 10px) 0 0 ; + border-radius: var(--panelRadius, 10px) var(--panelRadius, 10px) 0 0; &::after { border-radius: 0; @@ -58,11 +58,12 @@ .go-back-button { cursor: pointer; - margin-right: 1.4em; + padding: 0.6em; + margin: -0.6em 0.8em -0.6em -0.6em; + height: 100%; i { - display: flex; - align-items: center; + vertical-align: middle; } } @@ -78,7 +79,7 @@ display: flex; justify-content: center; align-items: center; - box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), 0px 2px 4px rgba(0, 0, 0, 0.3); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3), 0 2px 4px rgba(0, 0, 0, 0.3); z-index: 10; transition: 0.35s all; transition-timing-function: cubic-bezier(0, 1, 0.5, 1); diff --git a/src/services/chat_utils/chat_utils.js b/src/services/chat_utils/chat_utils.js index 583438f7..86fe1af9 100644 --- a/src/services/chat_utils/chat_utils.js +++ b/src/services/chat_utils/chat_utils.js @@ -3,7 +3,7 @@ import { showDesktopNotification } from '../desktop_notification_utils/desktop_n export const maybeShowChatNotification = (store, chat) => { if (!chat.lastMessage) return if (store.rootState.chats.currentChatId === chat.id && !document.hidden) return - if (store.rootState.users.currentUser.id === chat.lastMessage.account.id) return + if (store.rootState.users.currentUser.id === chat.lastMessage.account_id) return const opts = { tag: chat.lastMessage.id, diff --git a/src/services/promise_interval/promise_interval.js b/src/services/promise_interval/promise_interval.js index cf17970d..0c0a66a0 100644 --- a/src/services/promise_interval/promise_interval.js +++ b/src/services/promise_interval/promise_interval.js @@ -10,7 +10,14 @@ export const promiseInterval = (promiseCall, interval) => { let timeout = null const func = () => { - promiseCall().finally(() => { + const promise = promiseCall() + // something unexpected happened and promiseCall did not + // return a promise, abort the loop. + if (!(promise && promise.finally)) { + console.warn('promiseInterval: promise call did not return a promise, stopping interval.') + return + } + promise.finally(() => { if (stopped) return timeout = window.setTimeout(func, interval) }) From 1403f20f9feda44206b35f5b303652facd5e2011 Mon Sep 17 00:00:00 2001 From: Shpuld Shpuldson Date: Tue, 27 Oct 2020 12:59:50 +0200 Subject: [PATCH 02/41] block clicks for a second when timeline moves --- src/components/timeline/timeline.js | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index 17680542..25fa3e41 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -2,7 +2,7 @@ import Status from '../status/status.vue' import timelineFetcher from '../../services/timeline_fetcher/timeline_fetcher.service.js' import Conversation from '../conversation/conversation.vue' import TimelineMenu from '../timeline_menu/timeline_menu.vue' -import { throttle, keyBy } from 'lodash' +import { debounce, throttle, keyBy } from 'lodash' export const getExcludedStatusIdsByPinning = (statuses, pinnedStatusIds) => { const ids = [] @@ -34,7 +34,8 @@ const Timeline = { paused: false, unfocused: false, bottomedOut: false, - virtualScrollIndex: 0 + virtualScrollIndex: 0, + blockingClicks: false } }, components: { @@ -124,6 +125,21 @@ const Timeline = { this.$store.commit('setLoading', { timeline: this.timelineName, value: false }) }, methods: { + blockClickEvent (e) { + e.stopPropagation() + e.preventDefault() + }, + stopBlockingClicks: debounce(function () { + this.blockingClicks = false + this.$el && this.$el.removeEventListener('click', this.blockClickEvent, true) + }, 1000), + blockClicksTemporarily () { + if (!this.blockingClicks) { + this.$el.addEventListener('click', this.blockClickEvent, true) + this.blockingClicks = true + } + this.stopBlockingClicks() + }, handleShortKey (e) { // Ignore when input fields are focused if (['textarea', 'input'].includes(e.target.tagName.toLowerCase())) return @@ -135,6 +151,7 @@ const Timeline = { this.$store.commit('queueFlush', { timeline: this.timelineName, id: 0 }) this.fetchOlderStatuses() } else { + this.blockClicksTemporarily() this.$store.commit('showNewStatuses', { timeline: this.timelineName }) this.paused = false } From 85dc4002a1c96bbaf3c2fc3614c55cb57c574072 Mon Sep 17 00:00:00 2001 From: Shpuld Shpuldson Date: Tue, 27 Oct 2020 13:17:49 +0200 Subject: [PATCH 03/41] update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99f601a5..1a7cf9a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Fixed chat messages sometimes getting lost when you receive a message at the same time - Fixed clicking NSFW hider through status popover +### Changed +- Clicking immediately when timeline shifts is now blocked to prevent misclicks + ### Added - Import/export a muted users - Proper handling of deletes when using websocket streaming From 24d85ce6dc77c2e18759bdb67c8005fcd697a0c5 Mon Sep 17 00:00:00 2001 From: Shpuld Shpuldson Date: Tue, 27 Oct 2020 13:24:05 +0200 Subject: [PATCH 04/41] update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99f601a5..b7846c5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Fixed chats list not updating its order when new messages come in - Fixed chat messages sometimes getting lost when you receive a message at the same time - Fixed clicking NSFW hider through status popover +- Fixed chat-view back button being hard to click +- Fixed fresh chat notifications being cleared immediately while leaving the chat view and not having time to actually see the messages ### Added - Import/export a muted users From 7007659e05842dc06eb2c13eddaba6ab657df5ea Mon Sep 17 00:00:00 2001 From: Shpuld Shpuldson Date: Wed, 28 Oct 2020 08:53:23 +0200 Subject: [PATCH 05/41] change input blocking to use css --- src/components/timeline/timeline.js | 10 +++------- src/components/timeline/timeline.vue | 9 +++++++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index 25fa3e41..ea290fde 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -65,8 +65,10 @@ const Timeline = { } }, classes () { + let rootClasses = !this.embedded ? ['panel', 'panel-default'] : [] + if (this.blockingClicks) rootClasses = rootClasses.concat(['-blocked']) return { - root: ['timeline'].concat(!this.embedded ? ['panel', 'panel-default'] : []), + root: rootClasses, header: ['timeline-heading'].concat(!this.embedded ? ['panel-heading'] : []), body: ['timeline-body'].concat(!this.embedded ? ['panel-body'] : []), footer: ['timeline-footer'].concat(!this.embedded ? ['panel-footer'] : []) @@ -125,17 +127,11 @@ const Timeline = { this.$store.commit('setLoading', { timeline: this.timelineName, value: false }) }, methods: { - blockClickEvent (e) { - e.stopPropagation() - e.preventDefault() - }, stopBlockingClicks: debounce(function () { this.blockingClicks = false - this.$el && this.$el.removeEventListener('click', this.blockClickEvent, true) }, 1000), blockClicksTemporarily () { if (!this.blockingClicks) { - this.$el.addEventListener('click', this.blockClickEvent, true) this.blockingClicks = true } this.stopBlockingClicks() diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue index c1e2f44b..234ca2d2 100644 --- a/src/components/timeline/timeline.vue +++ b/src/components/timeline/timeline.vue @@ -1,5 +1,5 @@