Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: move page visibility check to composable #13302

Merged
merged 1 commit into from
Sep 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 20 additions & 24 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { useActiveSession } from './composables/useActiveSession.js'
import { useHashCheck } from './composables/useHashCheck.js'
import { useIsInCall } from './composables/useIsInCall.js'
import { useSessionIssueHandler } from './composables/useSessionIssueHandler.js'
import { useWindowVisibility } from './composables/useWindowVisibility.ts'
import { CONVERSATION, PARTICIPANT } from './constants.js'
import Router from './router/router.js'
import BrowserStorage from './services/BrowserStorage.js'
Expand Down Expand Up @@ -71,6 +72,7 @@ export default {
isLeavingAfterSessionIssue: useSessionIssueHandler(),
isMobile: useIsMobile(),
isNextcloudTalkHashDirty: useHashCheck(),
isWindowVisible: useWindowVisibility(),
supportSessionState: useActiveSession(),
federationStore: useFederationStore(),
}
Expand All @@ -88,9 +90,6 @@ export default {
},

computed: {
windowIsVisible() {
return this.$store.getters.windowIsVisible()
},
isFullscreen() {
return this.$store.getters.isFullscreen()
},
Expand Down Expand Up @@ -189,7 +188,7 @@ export default {

watch: {
atLeastOneLastMessageIdChanged() {
if (this.windowIsVisible) {
if (this.isWindowVisible) {
return
}

Expand Down Expand Up @@ -220,7 +219,23 @@ export default {
toggle?.removeAttribute('data-theme-dark')
}
}
}
},

isWindowVisible(value) {
if (value) {
// Remove the potential "*" marker for unread chat messages
let title = this.getConversationName(this.token)
if (window.document.title.indexOf(t('spreed', 'Duplicate session')) === 0) {
title = t('spreed', 'Duplicate session')
}
this.setPageTitle(title, false)
} else {
// Copy the last message map to the saved version,
// this will be our reference to check if any chat got a new
// message since the last visit
this.savedLastMessageMap = this.lastMessageMap
}
},
},

beforeCreate() {
Expand Down Expand Up @@ -249,7 +264,6 @@ export default {
if (!getCurrentUser()) {
EventBus.off('should-refresh-conversations', this.debounceRefreshCurrentConversation)
}
document.removeEventListener('visibilitychange', this.changeWindowVisibility)

unsubscribe('notifications:action:execute', this.interceptNotificationActions)

Expand All @@ -272,7 +286,6 @@ export default {
}

window.addEventListener('resize', this.onResize)
document.addEventListener('visibilitychange', this.changeWindowVisibility)

this.onResize()

Expand Down Expand Up @@ -625,23 +638,6 @@ export default {
this.fetchSingleConversation(this.token)
},

changeWindowVisibility() {
this.$store.dispatch('setWindowVisibility', !document.hidden)
if (this.windowIsVisible) {
// Remove the potential "*" marker for unread chat messages
let title = this.getConversationName(this.token)
if (window.document.title.indexOf(t('spreed', 'Duplicate session')) === 0) {
title = t('spreed', 'Duplicate session')
}
this.setPageTitle(title, false)
} else {
// Copy the last message map to the saved version,
// this will be our reference to check if any chat got a new
// message since the last visit
this.savedLastMessageMap = this.lastMessageMap
}
},

/**
* Set the page title to the conversation name
*
Expand Down
15 changes: 8 additions & 7 deletions src/components/MessagesList/MessagesList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
<script>
import debounce from 'debounce'
import uniqueId from 'lodash/uniqueId.js'
import { computed } from 'vue'

import Message from 'vue-material-design-icons/Message.vue'

Expand All @@ -76,6 +77,7 @@ import LoadingPlaceholder from '../UIShared/LoadingPlaceholder.vue'
import TransitionWrapper from '../UIShared/TransitionWrapper.vue'

import { useIsInCall } from '../../composables/useIsInCall.js'
import { useWindowVisibility } from '../../composables/useWindowVisibility.ts'
import { ATTENDEE, CHAT, CONVERSATION } from '../../constants.js'
import { EventBus } from '../../services/EventBus.js'
import { useChatExtrasStore } from '../../stores/chatExtras.js'
Expand Down Expand Up @@ -121,10 +123,13 @@ export default {

emits: ['update:is-chat-scrolled-to-bottom'],

setup() {
setup(props) {
const isWindowVisible = useWindowVisibility()
const isChatVisible = computed(() => isWindowVisible.value && props.isVisible)
Antreesy marked this conversation as resolved.
Show resolved Hide resolved
return {
isInCall: useIsInCall(),
chatExtrasStore: useChatExtrasStore(),
isChatVisible,
}
},

Expand Down Expand Up @@ -177,10 +182,6 @@ export default {
},

computed: {
isWindowVisible() {
return this.$store.getters.windowIsVisible() && this.isVisible
},

visualLastReadMessageId() {
return this.$store.getters.getVisualLastReadMessageId(this.token)
},
Expand Down Expand Up @@ -262,7 +263,7 @@ export default {
},

watch: {
isWindowVisible(visible) {
isChatVisible(visible) {
if (visible) {
this.onWindowFocus()
}
Expand Down Expand Up @@ -1107,7 +1108,7 @@ export default {
} else if (!this.isSticky) {
// Reading old messages
return
} else if (!this.isWindowVisible) {
} else if (!this.isChatVisible) {
const firstUnreadMessageHeight = this.$refs.scroller.scrollHeight - this.$refs.scroller.scrollTop - this.$refs.scroller.offsetHeight
const scrollBy = firstUnreadMessageHeight < 40 ? 10 : 40
// We jump half a message and stop autoscrolling, so the user can read up
Expand Down
9 changes: 8 additions & 1 deletion src/components/TopBar/CallTime.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
import NcPopover from '@nextcloud/vue/dist/Components/NcPopover.js'

import { useWindowVisibility } from '../../composables/useWindowVisibility.ts'
import { CALL } from '../../constants.js'
import { formattedTime } from '../../utils/formattedTime.ts'

Expand All @@ -93,6 +94,12 @@ export default {
},
},

setup() {
return {
isWindowVisible: useWindowVisibility(),
}
},

data() {
return {
callTime: undefined,
Expand Down Expand Up @@ -198,7 +205,7 @@ export default {
this.isCallDurationHintShown = true

// close the popover after 10 seconds
if (this.$store.getters.windowIsVisible()) {
if (this.isWindowVisible) {
setTimeout(() => {
this.showPopover = false
}, 10000)
Expand Down
5 changes: 3 additions & 2 deletions src/composables/useActiveSession.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { computed, onBeforeMount, onBeforeUnmount, ref, watch } from 'vue'

import { useIsInCall } from './useIsInCall.js'
import { useStore } from './useStore.js'
import { useWindowVisibility } from './useWindowVisibility.ts'
import { SESSION } from '../constants.js'
import { hasTalkFeature } from '../services/CapabilitiesManager.ts'
import { setSessionState } from '../services/participantsService.js'
Expand All @@ -31,7 +32,7 @@ export function useActiveSession() {
}

const isInCall = useIsInCall()
const windowIsVisible = computed(() => store.getters.windowIsVisible())
const isWindowVisible = useWindowVisibility()

const inactiveTimer = ref(null)
const currentState = ref(SESSION.STATE.ACTIVE)
Expand All @@ -41,7 +42,7 @@ export function useActiveSession() {
currentState.value = SESSION.STATE.ACTIVE
})

watch(windowIsVisible, (value) => {
watch(isWindowVisible, (value) => {
// Change state if tab is hidden or minimized
if (value) {
setSessionAsActive()
Expand Down
4 changes: 3 additions & 1 deletion src/composables/useGetParticipants.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { subscribe, unsubscribe } from '@nextcloud/event-bus'

import { useIsInCall } from './useIsInCall.js'
import { useStore } from './useStore.js'
import { useWindowVisibility } from './useWindowVisibility.ts'
import { CONVERSATION } from '../constants.js'
import { EventBus } from '../services/EventBus.js'

Expand All @@ -23,6 +24,7 @@ export function useGetParticipants(isActive = ref(true), isTopBar = true) {
const token = computed(() => store.getters.getToken())
const conversation = computed(() => store.getters.conversation(token.value))
const isInCall = useIsInCall()
const isWindowVisible = useWindowVisibility()
const isOneToOneConversation = computed(() => conversation.value?.type === CONVERSATION.TYPE.ONE_TO_ONE
|| conversation.value?.type === CONVERSATION.TYPE.ONE_TO_ONE_FORMER)
let fetchingParticipants = false
Expand Down Expand Up @@ -67,7 +69,7 @@ export function useGetParticipants(isActive = ref(true), isTopBar = true) {
return
}

if (store.getters.windowIsVisible() && (isInCall.value || !conversation.value?.hasCall)) {
if (isWindowVisible.value && (isInCall.value || !conversation.value?.hasCall)) {
debounceFastUpdateParticipants()
} else {
debounceSlowUpdateParticipants()
Expand Down
36 changes: 36 additions & 0 deletions src/composables/useWindowVisibility.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import { createSharedComposable } from '@vueuse/core'
import { readonly, ref, onBeforeMount, onBeforeUnmount } from 'vue'
import type { Ref, DeepReadonly } from 'vue'

/**
* Composable to check whether the page is visible.
* @return {DeepReadonly<Ref<boolean>>} - computed boolean whether the page is visible
*/
function useWindowVisibilityComposable() {
const isWindowVisible = ref<boolean>(!document.hidden)

const changeWindowVisibility = () => {
isWindowVisible.value = !document.hidden
}

onBeforeMount(() => {
document.addEventListener('visibilitychange', changeWindowVisibility)
})

onBeforeUnmount(() => {
document.removeEventListener('visibilitychange', changeWindowVisibility)
})

return readonly(isWindowVisible)
}

/**
* Shared composable to check whether the page is visible.
* @return {DeepReadonly<Ref<boolean>>} - computed boolean whether the page is visible
*/
export const useWindowVisibility = createSharedComposable(useWindowVisibilityComposable)
24 changes: 0 additions & 24 deletions src/store/windowVisibilityStore.js
Antreesy marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,16 @@
*/

const state = {
visible: true,
fullscreen: false,
}

const getters = {
windowIsVisible: (state) => () => {
return state.visible
},
isFullscreen: (state) => () => {
return state.fullscreen
},
}

const mutations = {
/**
* Sets the current visibility state
*
* @param {object} state current store state;
* @param {boolean} value the value;
*/
setVisibility(state, value) {
state.visible = value
},

/**
* Sets the fullscreen state
*
Expand All @@ -40,16 +26,6 @@ const mutations = {
}

const actions = {
/**
* Sets the current visibility state
*
* @param {object} context the context object;
* @param {boolean} value the value;
*/
setWindowVisibility(context, value) {
context.commit('setVisibility', value)
},

/**
* Sets the fullscreen state
*
Expand Down
Loading