From 93049e9d5226b28b2d60d66a44bb503386991ee4 Mon Sep 17 00:00:00 2001 From: eugenijm Date: Fri, 22 May 2020 00:49:02 +0300 Subject: [PATCH] WIP preserve scroll position during posting form resize, attachment upload, window resize, disable auto-focus for mobile --- src/App.js | 4 +- src/components/chat/chat.js | 53 ++++++++++++++++--- src/components/chat/chat.vue | 4 +- .../post_status_form/post_status_form.js | 7 +++ src/modules/interface.js | 9 +++- src/services/window_utils/window_utils.js | 5 ++ 6 files changed, 72 insertions(+), 10 deletions(-) diff --git a/src/App.js b/src/App.js index 6a8e74a6..aaebaa75 100644 --- a/src/App.js +++ b/src/App.js @@ -12,7 +12,7 @@ import MobilePostStatusButton from './components/mobile_post_status_button/mobil import MobileNav from './components/mobile_nav/mobile_nav.vue' import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue' import PostStatusModal from './components/post_status_modal/post_status_modal.vue' -import { windowWidth } from './services/window_utils/window_utils' +import { windowWidth, windowHeight } from './services/window_utils/window_utils' export default { name: 'app', @@ -120,10 +120,12 @@ export default { }, updateMobileState () { const mobileLayout = windowWidth() <= 800 + const layoutHeight = windowHeight() const changed = mobileLayout !== this.isMobileLayout if (changed) { this.$store.dispatch('setMobileLayout', mobileLayout) } + this.$store.dispatch('setLayoutHeight', layoutHeight) } }, watch: { diff --git a/src/components/chat/chat.js b/src/components/chat/chat.js index 43e5ff8e..a0598cd3 100644 --- a/src/components/chat/chat.js +++ b/src/components/chat/chat.js @@ -24,7 +24,8 @@ const Chat = { mobileLayout: this.$store.state.interface.mobileLayout, recipientId: this.$route.params.recipient_id, hoveredSequenceId: undefined, - newMessageCount: this.currentChatMessageService && this.currentChatMessageService.newMessageCount + newMessageCount: this.currentChatMessageService && this.currentChatMessageService.newMessageCount, + lastPosition: undefined } }, created () { @@ -38,6 +39,7 @@ const Chat = { window.addEventListener('scroll', this.handleScroll) } this.updateSize() + this.handleResize() }) if (this.isMobileLayout) { this.setMobileChatLayout() @@ -47,11 +49,19 @@ const Chat = { document.addEventListener('visibilitychange', this.handleVisibilityChange, false) this.$store.commit('setChatFocused', !document.hidden) } + let body = document.querySelector('body') + if (body) { + body.style.overscrollBehavior = 'none' + } }, destroyed () { window.removeEventListener('scroll', this.handleScroll) window.removeEventListener('resize', this.handleLayoutChange) this.unsetMobileChatLayout() + let body = document.querySelector('body') + if (body) { + body.style.overscrollBehavior = 'unset' + } if (typeof document.hidden !== 'undefined') document.removeEventListener('visibilitychange', this.handleVisibilityChange, false) this.$store.dispatch('clearCurrentChat') }, @@ -86,7 +96,8 @@ const Chat = { backendInteractor: state => state.api.backendInteractor, currentUser: state => state.users.currentUser, isMobileLayout: state => state.interface.mobileLayout, - openedChats: state => state.chats.openedChats + openedChats: state => state.chats.openedChats, + windowHeight: state => state.interface.layoutHeight }) }, watch: { @@ -102,6 +113,9 @@ const Chat = { '$route': function (prev, next) { this.recipientId = this.$route.params.recipient_id this.startFetching() + }, + windowHeight () { + this.handleResize({ expand: true }) } }, methods: { @@ -159,7 +173,6 @@ const Chat = { let body = document.querySelector('body') if (body) { body.style.height = '100%' - body.style.overscrollBehavior = 'none' } let app = document.getElementById('app') @@ -201,7 +214,6 @@ const Chat = { let body = document.querySelector('body') if (body) { body.style.height = 'unset' - body.style.overscrollBehavior = 'unset' } let app = document.getElementById('app') @@ -229,8 +241,37 @@ const Chat = { content.style.overflow = 'unset' } }, - handleResize (newHeight) { - this.updateSize(newHeight) + handleResize (opts) { + this.$nextTick(() => { + this.updateSize() + + let prevOffsetHeight + if (this.lastPosition) { + prevOffsetHeight = this.lastPosition.offsetHeight + } + + this.lastPosition = { + scrollTop: this.$refs.scrollable.scrollTop, + totalHeight: this.$refs.scrollable.scrollHeight, + offsetHeight: this.$refs.scrollable.offsetHeight + } + + if (this.lastPosition) { + const diff = this.lastPosition.offsetHeight - prevOffsetHeight + const bottomedOut = this.bottomedOut() + if (diff < 0 || (!bottomedOut && opts && opts.expand)) { + this.$nextTick(() => { + this.updateSize() + this.$nextTick(() => { + this.$refs.scrollable.scrollTo({ + top: this.$refs.scrollable.scrollTop - diff, + left: 0 + }) + }) + }) + } + } + }) }, updateSize (newHeight, _diff) { let h = this.$refs.header diff --git a/src/components/chat/chat.vue b/src/components/chat/chat.vue index 9ab16226..dd8be63b 100644 --- a/src/components/chat/chat.vue +++ b/src/components/chat/chat.vue @@ -66,9 +66,9 @@ :disable-notice="true" :disable-polls="true" :poster="poster" - :preserve-focus="true" + :preserve-focus="!isMobileLayout" :polls-available="false" - :auto-focus="true" + :auto-focus="!isMobileLayout" :placeholder="formPlaceholder" :file-limit="1" max-height="160" diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index e93d1733..739e36a7 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -238,12 +238,19 @@ const PostStatusForm = { }) }, addMediaFile (fileInfo) { + this.$emit('resize') this.newStatus.files.push(fileInfo) this.enableSubmit() + // TODO: use fixed dimensions instead so relying on timeout + setTimeout(() => { + this.$emit('resize') + }, 150) }, removeMediaFile (fileInfo) { + this.$emit('resize') let index = this.newStatus.files.indexOf(fileInfo) this.newStatus.files.splice(index, 1) + this.$emit('resize') }, uploadFailed (errString, templateArgs) { templateArgs = templateArgs || {} diff --git a/src/modules/interface.js b/src/modules/interface.js index 5b2762e5..26f70d10 100644 --- a/src/modules/interface.js +++ b/src/modules/interface.js @@ -12,7 +12,8 @@ const defaultState = { window.CSS.supports('-webkit-filter', 'drop-shadow(0 0)') ) }, - mobileLayout: false + mobileLayout: false, + layoutHeight: 0 } const interfaceMod = { @@ -35,6 +36,9 @@ const interfaceMod = { }, setMobileLayout (state, value) { state.mobileLayout = value + }, + setLayoutHeight (state, value) { + state.layoutHeight = value } }, actions: { @@ -49,6 +53,9 @@ const interfaceMod = { }, setMobileLayout ({ commit }, value) { commit('setMobileLayout', value) + }, + setLayoutHeight ({ commit }, value) { + commit('setLayoutHeight', value) } } } diff --git a/src/services/window_utils/window_utils.js b/src/services/window_utils/window_utils.js index faff6cb9..909088db 100644 --- a/src/services/window_utils/window_utils.js +++ b/src/services/window_utils/window_utils.js @@ -3,3 +3,8 @@ export const windowWidth = () => window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth + +export const windowHeight = () => + window.innerHeight || + document.documentElement.clientHeight || + document.body.clientHeight