diff --git a/src/components/chat/chat.js b/src/components/chat/chat.js
index 5d2c1d095..9a0ae1072 100644
--- a/src/components/chat/chat.js
+++ b/src/components/chat/chat.js
@@ -19,8 +19,6 @@ library.add(
faChevronLeft
)
-const scroller = () => document.getElementById('content')
-
const BOTTOMED_OUT_OFFSET = 10
const JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET = 10
const SAFE_RESIZE_TIME_OFFSET = 100
@@ -45,10 +43,9 @@ const Chat = {
},
created () {
this.startFetching()
- window.addEventListener('resize', this.handleLayoutChange)
},
mounted () {
- scroller().addEventListener('scroll', this.handleScroll)
+ window.addEventListener('scroll', this.handleScroll)
if (typeof document.hidden !== 'undefined') {
document.addEventListener('visibilitychange', this.handleVisibilityChange, false)
}
@@ -56,12 +53,9 @@ const Chat = {
this.$nextTick(() => {
this.handleResize()
})
- this.setChatLayout()
},
unmounted () {
- scroller().removeEventListener('scroll', this.handleScroll)
- window.removeEventListener('resize', this.handleLayoutChange)
- this.unsetChatLayout()
+ window.removeEventListener('scroll', this.handleScroll)
if (typeof document.hidden !== 'undefined') document.removeEventListener('visibilitychange', this.handleVisibilityChange, false)
this.$store.dispatch('clearCurrentChat')
},
@@ -97,8 +91,7 @@ const Chat = {
...mapState({
backendInteractor: state => state.api.backendInteractor,
mastoUserSocketStatus: state => state.api.mastoUserSocketStatus,
- mobileLayout: state => state.interface.mobileLayout,
- layoutHeight: state => state.interface.layoutHeight,
+ mobileLayout: state => state.interface.layoutType === 'mobile',
currentUser: state => state.users.currentUser
})
},
@@ -116,9 +109,6 @@ const Chat = {
'$route': function () {
this.startFetching()
},
- layoutHeight () {
- this.handleResize({ expand: true })
- },
mastoUserSocketStatus (newValue) {
if (newValue === WSConnectionStatus.JOINED) {
this.fetchChat({ isFirstFetch: true })
@@ -142,30 +132,6 @@ const Chat = {
}
})
},
- setChatLayout () {
- // This is a hacky way to adjust the global layout to the mobile chat (without modifying the rest of the app).
- // This layout prevents empty spaces from being visible at the bottom
- // of the chat on iOS Safari (`safe-area-inset`) when
- // - the on-screen keyboard appears and the user starts typing
- // - the user selects the text inside the input area
- // - the user selects and deletes the text that is multiple lines long
- // TODO: unify the chat layout with the global layout.
- let html = document.querySelector('html')
- if (html) {
- html.classList.add('chat-layout')
- }
- },
- unsetChatLayout () {
- let html = document.querySelector('html')
- if (html) {
- html.classList.remove('chat-layout')
- }
- },
- handleLayoutChange () {
- this.$nextTick(() => {
- this.scrollDown()
- })
- },
// Preserves the scroll position when OSK appears or the posting form changes its height.
handleResize (opts = {}) {
const { expand = false, delayed = false } = opts
@@ -179,25 +145,20 @@ const Chat = {
this.$nextTick(() => {
const { offsetHeight = undefined } = this.lastScrollPosition
- this.lastScrollPosition = getScrollPosition(scroller())
+ this.lastScrollPosition = getScrollPosition()
const diff = this.lastScrollPosition.offsetHeight - offsetHeight
if (diff < 0 || (!this.bottomedOut() && expand)) {
this.$nextTick(() => {
- scroller().scrollTo({
- top: scroller().scrollTop - diff,
- left: 0
- })
+ window.scrollTo({ top: window.scrollY - diff })
})
}
})
},
scrollDown (options = {}) {
const { behavior = 'auto', forceRead = false } = options
- const scrollable = scroller()
- if (!scrollable) { return }
this.$nextTick(() => {
- scrollable.scrollTo({ top: scrollable.scrollHeight, left: 0, behavior })
+ window.scrollTo({ top: document.documentElement.scrollHeight, behavior })
})
if (forceRead) {
this.readChat()
@@ -213,11 +174,10 @@ const Chat = {
})
},
bottomedOut (offset) {
- return isBottomedOut(scroller(), offset)
+ return isBottomedOut(offset)
},
reachedTop () {
- const scrollable = scroller()
- return scrollable && scrollable.scrollTop <= 0
+ return window.scrollY <= 0
},
cullOlderCheck () {
window.setTimeout(() => {
@@ -248,10 +208,9 @@ const Chat = {
}
}, 200),
handleScrollUp (positionBeforeLoading) {
- const positionAfterLoading = getScrollPosition(scroller())
- scroller().scrollTo({
- top: getNewTopPosition(positionBeforeLoading, positionAfterLoading),
- left: 0
+ const positionAfterLoading = getScrollPosition()
+ window.scrollTo({
+ top: getNewTopPosition(positionBeforeLoading, positionAfterLoading)
})
},
fetchChat ({ isFirstFetch = false, fetchLatest = false, maxId }) {
@@ -270,7 +229,7 @@ const Chat = {
chatService.clear(chatMessageService)
}
- const positionBeforeUpdate = getScrollPosition(scroller())
+ const positionBeforeUpdate = getScrollPosition()
this.$store.dispatch('addChatMessages', { chatId, messages }).then(() => {
this.$nextTick(() => {
if (fetchOlderMessages) {
@@ -281,7 +240,7 @@ const Chat = {
// full height of the scrollable container.
// If this is the case, we want to fetch the messages until the scrollable container
// is fully populated so that the user has the ability to scroll up and load the history.
- if (!isScrollable(scroller()) && messages.length > 0) {
+ if (!isScrollable() && messages.length > 0) {
this.fetchChat({ maxId: this.currentChatMessageService.minId })
}
})
diff --git a/src/components/chat/chat.scss b/src/components/chat/chat.scss
index 34a335fe3..1bad51b93 100644
--- a/src/components/chat/chat.scss
+++ b/src/components/chat/chat.scss
@@ -1,6 +1,9 @@
.chat-view {
display: flex;
height: 100%;
+ // Stick the form to the top/bottom of screen
+ margin-bottom: calc(var(--___columnMargin) / -2);
+ margin-top: calc(var(--___columnMargin) / -2);
.chat-view-inner {
height: auto;
diff --git a/src/components/chat/chat.vue b/src/components/chat/chat.vue
index 3b0129fa4..d909bed93 100644
--- a/src/components/chat/chat.vue
+++ b/src/components/chat/chat.vue
@@ -2,7 +2,6 @@
diff --git a/src/components/chat/chat_layout_utils.js b/src/components/chat/chat_layout_utils.js
index 50a933ac7..c187892d9 100644
--- a/src/components/chat/chat_layout_utils.js
+++ b/src/components/chat/chat_layout_utils.js
@@ -1,9 +1,9 @@
// Captures a scroll position
-export const getScrollPosition = (el) => {
+export const getScrollPosition = () => {
return {
- scrollTop: el.scrollTop,
- scrollHeight: el.scrollHeight,
- offsetHeight: el.offsetHeight
+ scrollTop: window.scrollY,
+ scrollHeight: document.documentElement.scrollHeight,
+ offsetHeight: window.innerHeight
}
}
@@ -13,21 +13,12 @@ export const getNewTopPosition = (previousPosition, newPosition) => {
return previousPosition.scrollTop + (newPosition.scrollHeight - previousPosition.scrollHeight)
}
-export const isBottomedOut = (el, offset = 0) => {
- if (!el) { return }
- const scrollHeight = el.scrollTop + offset
- const totalHeight = el.scrollHeight - el.offsetHeight
+export const isBottomedOut = (offset = 0) => {
+ const scrollHeight = window.scrollY + offset
+ const totalHeight = document.documentElement.scrollHeight - window.innerHeight
return totalHeight <= scrollHeight
}
-
-// Height of the scrollable container. The dynamic height is needed to ensure the mobile browser panel doesn't overlap or hide the posting form.
-export const scrollableContainerHeight = (inner, header, footer) => {
- return inner.offsetHeight - header.clientHeight - footer.clientHeight
-}
-
// Returns whether or not the scrollbar is visible.
-export const isScrollable = (el) => {
- if (!el) return
-
- return el.scrollHeight > el.clientHeight
+export const isScrollable = () => {
+ return document.documentElement.scrollHeight > window.innerHeight
}
diff --git a/src/components/chat_new/chat_new.vue b/src/components/chat_new/chat_new.vue
index f3894a3a9..0790bb372 100644
--- a/src/components/chat_new/chat_new.vue
+++ b/src/components/chat_new/chat_new.vue
@@ -1,6 +1,5 @@
document.getElementById('content')
-
const Timeline = {
props: [
'timeline',
@@ -91,7 +89,7 @@ const Timeline = {
const credentials = store.state.users.currentUser.credentials
const showImmediately = this.timeline.visibleStatuses.length === 0
- scroller() && scroller().addEventListener('scroll', this.handleScroll)
+ window.addEventListener('scroll', this.handleScroll)
if (store.state.api.fetchers[this.timelineName]) { return false }
@@ -113,7 +111,7 @@ const Timeline = {
setTimeout(this.determineVisibleStatuses, 250)
},
unmounted () {
- scroller().removeEventListener('scroll', this.handleScroll)
+ window.removeEventListener('scroll', this.handleScroll)
window.removeEventListener('keydown', this.handleShortKey)
if (typeof document.hidden !== 'undefined') document.removeEventListener('visibilitychange', this.handleVisibilityChange, false)
this.$store.commit('setLoading', { timeline: this.timelineName, value: false })
@@ -143,7 +141,7 @@ const Timeline = {
this.$store.commit('showNewStatuses', { timeline: this.timelineName })
this.paused = false
}
- scroller().scrollTop = 0
+ window.scrollTo({ top: 0 })
},
fetchOlderStatuses: throttle(function () {
const store = this.$store
@@ -231,8 +229,8 @@ const Timeline = {
}
if (count > 0) {
// only 'stream' them when you're scrolled to the top
- const doc = document.getElementById('content')
- const top = (doc.scrollTop) - (doc.clientTop || 0)
+ const doc = document.documentElement
+ const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)
if (top < 15 &&
!this.paused &&
!(this.unfocused && this.$store.getters.mergedConfig.pauseOnUnfocused)
diff --git a/src/panel.scss b/src/panel.scss
index bd56858ff..049144ba1 100644
--- a/src/panel.scss
+++ b/src/panel.scss
@@ -63,7 +63,7 @@
&.-sticky {
position: sticky;
- top: 0;
+ top: var(--navbar-height);
z-index: 2;
}