forked from AkkomaGang/akkoma-fe
WIP Chat refactoring
This commit is contained in:
parent
93049e9d52
commit
c82436cd8a
2 changed files with 120 additions and 116 deletions
|
@ -5,6 +5,7 @@ import ChatAvatar from '../chat_avatar/chat_avatar.vue'
|
||||||
import PostStatusForm from '../post_status_form/post_status_form.vue'
|
import PostStatusForm from '../post_status_form/post_status_form.vue'
|
||||||
import ChatTitle from '../chat_title/chat_title.vue'
|
import ChatTitle from '../chat_title/chat_title.vue'
|
||||||
import chatService from '../../services/chat_service/chat_service.js'
|
import chatService from '../../services/chat_service/chat_service.js'
|
||||||
|
import ChatLayout from './chat_layout.js'
|
||||||
|
|
||||||
const Chat = {
|
const Chat = {
|
||||||
components: {
|
components: {
|
||||||
|
@ -13,6 +14,7 @@ const Chat = {
|
||||||
ChatAvatar,
|
ChatAvatar,
|
||||||
PostStatusForm
|
PostStatusForm
|
||||||
},
|
},
|
||||||
|
mixins: [ChatLayout],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
loadingOlderMessages: false,
|
loadingOlderMessages: false,
|
||||||
|
@ -24,7 +26,6 @@ const Chat = {
|
||||||
mobileLayout: this.$store.state.interface.mobileLayout,
|
mobileLayout: this.$store.state.interface.mobileLayout,
|
||||||
recipientId: this.$route.params.recipient_id,
|
recipientId: this.$route.params.recipient_id,
|
||||||
hoveredSequenceId: undefined,
|
hoveredSequenceId: undefined,
|
||||||
newMessageCount: this.currentChatMessageService && this.currentChatMessageService.newMessageCount,
|
|
||||||
lastPosition: undefined
|
lastPosition: undefined
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -41,27 +42,17 @@ const Chat = {
|
||||||
this.updateSize()
|
this.updateSize()
|
||||||
this.handleResize()
|
this.handleResize()
|
||||||
})
|
})
|
||||||
if (this.isMobileLayout) {
|
this.setChatLayout()
|
||||||
this.setMobileChatLayout()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof document.hidden !== 'undefined') {
|
if (typeof document.hidden !== 'undefined') {
|
||||||
document.addEventListener('visibilitychange', this.handleVisibilityChange, false)
|
document.addEventListener('visibilitychange', this.handleVisibilityChange, false)
|
||||||
this.$store.commit('setChatFocused', !document.hidden)
|
this.$store.commit('setChatFocused', !document.hidden)
|
||||||
}
|
}
|
||||||
let body = document.querySelector('body')
|
|
||||||
if (body) {
|
|
||||||
body.style.overscrollBehavior = 'none'
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
destroyed () {
|
destroyed () {
|
||||||
window.removeEventListener('scroll', this.handleScroll)
|
window.removeEventListener('scroll', this.handleScroll)
|
||||||
window.removeEventListener('resize', this.handleLayoutChange)
|
window.removeEventListener('resize', this.handleLayoutChange)
|
||||||
this.unsetMobileChatLayout()
|
this.unsetChatLayout()
|
||||||
let body = document.querySelector('body')
|
|
||||||
if (body) {
|
|
||||||
body.style.overscrollBehavior = 'unset'
|
|
||||||
}
|
|
||||||
if (typeof document.hidden !== 'undefined') document.removeEventListener('visibilitychange', this.handleVisibilityChange, false)
|
if (typeof document.hidden !== 'undefined') document.removeEventListener('visibilitychange', this.handleVisibilityChange, false)
|
||||||
this.$store.dispatch('clearCurrentChat')
|
this.$store.dispatch('clearCurrentChat')
|
||||||
},
|
},
|
||||||
|
@ -91,6 +82,9 @@ const Chat = {
|
||||||
chatViewItems () {
|
chatViewItems () {
|
||||||
return chatService.getView(this.currentChatMessageService)
|
return chatService.getView(this.currentChatMessageService)
|
||||||
},
|
},
|
||||||
|
newMessageCount () {
|
||||||
|
return this.currentChatMessageService && this.currentChatMessageService.newMessageCount
|
||||||
|
},
|
||||||
...mapGetters(['currentChat', 'currentChatMessageService', 'findUser', 'findOpenedChatByRecipientId']),
|
...mapGetters(['currentChat', 'currentChatMessageService', 'findUser', 'findOpenedChatByRecipientId']),
|
||||||
...mapState({
|
...mapState({
|
||||||
backendInteractor: state => state.api.backendInteractor,
|
backendInteractor: state => state.api.backendInteractor,
|
||||||
|
@ -105,7 +99,6 @@ const Chat = {
|
||||||
let bottomedOut = this.bottomedOut(10)
|
let bottomedOut = this.bottomedOut(10)
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
if (bottomedOut && prev.length !== next.length) {
|
if (bottomedOut && prev.length !== next.length) {
|
||||||
this.newMessageCount = this.currentChatMessageService.newMessageCount
|
|
||||||
this.scrollDown({ forceRead: true })
|
this.scrollDown({ forceRead: true })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -155,92 +148,6 @@ const Chat = {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setMobileChatLayout () {
|
|
||||||
// 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.style.overflow = 'hidden'
|
|
||||||
html.style.height = '100%'
|
|
||||||
}
|
|
||||||
|
|
||||||
let body = document.querySelector('body')
|
|
||||||
if (body) {
|
|
||||||
body.style.height = '100%'
|
|
||||||
}
|
|
||||||
|
|
||||||
let app = document.getElementById('app')
|
|
||||||
if (app) {
|
|
||||||
app.style.height = '100%'
|
|
||||||
app.style.overflow = 'hidden'
|
|
||||||
app.style.minHeight = 'auto'
|
|
||||||
}
|
|
||||||
|
|
||||||
let appBgWrapper = window.document.getElementById('app_bg_wrapper')
|
|
||||||
if (appBgWrapper) {
|
|
||||||
appBgWrapper.style.overflow = 'hidden'
|
|
||||||
}
|
|
||||||
|
|
||||||
let main = document.getElementsByClassName('main')[0]
|
|
||||||
if (main) {
|
|
||||||
main.style.overflow = 'hidden'
|
|
||||||
main.style.height = '100%'
|
|
||||||
}
|
|
||||||
|
|
||||||
let content = document.getElementById('content')
|
|
||||||
if (content) {
|
|
||||||
content.style.paddingTop = '0'
|
|
||||||
content.style.height = '100%'
|
|
||||||
content.style.overflow = 'visible'
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.updateSize()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
unsetMobileChatLayout () {
|
|
||||||
let html = document.querySelector('html')
|
|
||||||
if (html) {
|
|
||||||
html.style.overflow = 'visible'
|
|
||||||
html.style.height = 'unset'
|
|
||||||
}
|
|
||||||
|
|
||||||
let body = document.querySelector('body')
|
|
||||||
if (body) {
|
|
||||||
body.style.height = 'unset'
|
|
||||||
}
|
|
||||||
|
|
||||||
let app = document.getElementById('app')
|
|
||||||
if (app) {
|
|
||||||
app.style.height = '100%'
|
|
||||||
app.style.overflow = 'visible'
|
|
||||||
app.style.minHeight = '100vh'
|
|
||||||
}
|
|
||||||
|
|
||||||
let appBgWrapper = document.getElementById('app_bg_wrapper')
|
|
||||||
if (appBgWrapper) {
|
|
||||||
appBgWrapper.style.overflow = 'visible'
|
|
||||||
}
|
|
||||||
|
|
||||||
let main = document.getElementsByClassName('main')[0]
|
|
||||||
if (main) {
|
|
||||||
main.style.overflow = 'visible'
|
|
||||||
main.style.height = 'unset'
|
|
||||||
}
|
|
||||||
|
|
||||||
let content = document.getElementById('content')
|
|
||||||
if (content) {
|
|
||||||
content.style.paddingTop = '60px'
|
|
||||||
content.style.height = 'unset'
|
|
||||||
content.style.overflow = 'unset'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleResize (opts) {
|
handleResize (opts) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.updateSize()
|
this.updateSize()
|
||||||
|
@ -321,29 +228,20 @@ const Chat = {
|
||||||
let totalHeight = this.$refs.scrollable.scrollHeight - this.$refs.scrollable.offsetHeight
|
let totalHeight = this.$refs.scrollable.scrollHeight - this.$refs.scrollable.offsetHeight
|
||||||
return { scrollHeight, totalHeight }
|
return { scrollHeight, totalHeight }
|
||||||
},
|
},
|
||||||
reachedTop (offset) {
|
reachedTop () {
|
||||||
let res = false
|
const scrollable = this.$refs.scrollable
|
||||||
|
return scrollable && scrollable.scrollTop <= 0
|
||||||
if (this.$refs.scrollable) {
|
|
||||||
let scrollHeight = this.$refs.scrollable.scrollTop + (offset || 0)
|
|
||||||
if (scrollHeight <= offset) {
|
|
||||||
res = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res
|
|
||||||
},
|
},
|
||||||
handleScroll: _.throttle(function () {
|
handleScroll: _.throttle(function () {
|
||||||
if (!this.currentChat) { return }
|
if (!this.currentChat) { return }
|
||||||
|
|
||||||
if (this.reachedTop(0)) {
|
if (this.reachedTop()) {
|
||||||
this.fetchChat(false, this.currentChat.id, {
|
this.fetchChat(false, this.currentChat.id, {
|
||||||
maxId: this.currentChatMessageService.minId
|
maxId: this.currentChatMessageService.minId
|
||||||
})
|
})
|
||||||
} else if (this.bottomedOut(150)) {
|
} else if (this.bottomedOut(150)) {
|
||||||
this.jumpToBottomButtonVisible = false
|
this.jumpToBottomButtonVisible = false
|
||||||
let newMessageCount = this.newMessageCount
|
if (this.newMessageCount > 0) {
|
||||||
if (newMessageCount > 0) {
|
|
||||||
this.readChat()
|
this.readChat()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -381,7 +279,6 @@ const Chat = {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
this.newMessageCount = this.currentChatMessageService.newMessageCount
|
|
||||||
if (isFirstFetch) {
|
if (isFirstFetch) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.updateSize()
|
this.updateSize()
|
||||||
|
@ -398,7 +295,6 @@ const Chat = {
|
||||||
readChat () {
|
readChat () {
|
||||||
if (!(this.currentChat && this.currentChat.id)) { return }
|
if (!(this.currentChat && this.currentChat.id)) { return }
|
||||||
this.$store.dispatch('readChat', { id: this.currentChat.id })
|
this.$store.dispatch('readChat', { id: this.currentChat.id })
|
||||||
this.newMessageCount = this.currentChatMessageService.newMessageCount
|
|
||||||
},
|
},
|
||||||
async startFetching () {
|
async startFetching () {
|
||||||
let chat = this.findOpenedChatByRecipientId(this.recipientId)
|
let chat = this.findOpenedChatByRecipientId(this.recipientId)
|
||||||
|
|
108
src/components/chat/chat_layout.js
Normal file
108
src/components/chat/chat_layout.js
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
const ChatLayout = {
|
||||||
|
methods: {
|
||||||
|
setChatLayout () {
|
||||||
|
let body = document.querySelector('body')
|
||||||
|
if (body) {
|
||||||
|
body.style.overscrollBehavior = 'none'
|
||||||
|
}
|
||||||
|
if (this.isMobileLayout) {
|
||||||
|
this.setMobileChatLayout()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
unsetChatLayout () {
|
||||||
|
this.unsetMobileChatLayout()
|
||||||
|
let body = document.querySelector('body')
|
||||||
|
if (body) {
|
||||||
|
body.style.overscrollBehavior = 'unset'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setMobileChatLayout () {
|
||||||
|
// 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.style.overflow = 'hidden'
|
||||||
|
html.style.height = '100%'
|
||||||
|
}
|
||||||
|
|
||||||
|
let body = document.querySelector('body')
|
||||||
|
if (body) {
|
||||||
|
body.style.height = '100%'
|
||||||
|
}
|
||||||
|
|
||||||
|
let app = document.getElementById('app')
|
||||||
|
if (app) {
|
||||||
|
app.style.height = '100%'
|
||||||
|
app.style.overflow = 'hidden'
|
||||||
|
app.style.minHeight = 'auto'
|
||||||
|
}
|
||||||
|
|
||||||
|
let appBgWrapper = window.document.getElementById('app_bg_wrapper')
|
||||||
|
if (appBgWrapper) {
|
||||||
|
appBgWrapper.style.overflow = 'hidden'
|
||||||
|
}
|
||||||
|
|
||||||
|
let main = document.getElementsByClassName('main')[0]
|
||||||
|
if (main) {
|
||||||
|
main.style.overflow = 'hidden'
|
||||||
|
main.style.height = '100%'
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = document.getElementById('content')
|
||||||
|
if (content) {
|
||||||
|
content.style.paddingTop = '0'
|
||||||
|
content.style.height = '100%'
|
||||||
|
content.style.overflow = 'visible'
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.updateSize()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
unsetMobileChatLayout () {
|
||||||
|
let html = document.querySelector('html')
|
||||||
|
if (html) {
|
||||||
|
html.style.overflow = 'visible'
|
||||||
|
html.style.height = 'unset'
|
||||||
|
}
|
||||||
|
|
||||||
|
let body = document.querySelector('body')
|
||||||
|
if (body) {
|
||||||
|
body.style.height = 'unset'
|
||||||
|
}
|
||||||
|
|
||||||
|
let app = document.getElementById('app')
|
||||||
|
if (app) {
|
||||||
|
app.style.height = '100%'
|
||||||
|
app.style.overflow = 'visible'
|
||||||
|
app.style.minHeight = '100vh'
|
||||||
|
}
|
||||||
|
|
||||||
|
let appBgWrapper = document.getElementById('app_bg_wrapper')
|
||||||
|
if (appBgWrapper) {
|
||||||
|
appBgWrapper.style.overflow = 'visible'
|
||||||
|
}
|
||||||
|
|
||||||
|
let main = document.getElementsByClassName('main')[0]
|
||||||
|
if (main) {
|
||||||
|
main.style.overflow = 'visible'
|
||||||
|
main.style.height = 'unset'
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = document.getElementById('content')
|
||||||
|
if (content) {
|
||||||
|
content.style.paddingTop = '60px'
|
||||||
|
content.style.height = 'unset'
|
||||||
|
content.style.overflow = 'unset'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ChatLayout
|
Loading…
Reference in a new issue