Skip to content

Commit

Permalink
Merge pull request #11334 from nextcloud/ref/noid/migrate-get-partici…
Browse files Browse the repository at this point in the history
…pants-mixin

Refactor(Mixins): Change getParticipants mixin to composable
  • Loading branch information
DorraJaouad authored Jan 12, 2024
2 parents ecd8a36 + 2f497e4 commit 11f5314
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 165 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,8 @@ import MessageForwarder from './MessageForwarder.vue'
import { PARTICIPANT, CONVERSATION, ATTENDEE } from '../../../../../constants.js'
import { getMessageReminder, removeMessageReminder, setMessageReminder } from '../../../../../services/remindersService.js'
import { copyConversationLinkToClipboard } from '../../../../../services/urlService.js'
import { useReactionsStore } from '../../../../../stores/reactions.js'
import { useIntegrationsStore } from '../../../../../stores/integrations.js'
import { useReactionsStore } from '../../../../../stores/reactions.js'

const EmojiIndex = new EmojiIndexFactory(data)
const supportReminders = getCapabilities()?.spreed?.features?.includes('remind-me-later')
Expand Down
31 changes: 15 additions & 16 deletions src/components/RightSidebar/Participants/ParticipantsTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@

<script>
import debounce from 'debounce'
import { toRefs } from 'vue'

import { getCapabilities } from '@nextcloud/capabilities'
import { showError } from '@nextcloud/dialogs'
Expand All @@ -82,9 +83,9 @@ import Hint from '../../Hint.vue'
import SearchBox from '../../LeftSidebar/SearchBox/SearchBox.vue'
import SelectPhoneNumber from '../../SelectPhoneNumber.vue'

import { useGetParticipants } from '../../../composables/useGetParticipants.js'
import { useIsInCall } from '../../../composables/useIsInCall.js'
import { useSortParticipants } from '../../../composables/useSortParticipants.js'
import getParticipants from '../../../mixins/getParticipants.js'
import { searchPossibleConversations } from '../../../services/conversationsService.js'
import { EventBus } from '../../../services/EventBus.js'
import { addParticipant } from '../../../services/participantsService.js'
Expand All @@ -108,9 +109,11 @@ export default {
SelectPhoneNumber,
},

mixins: [getParticipants],

props: {
isActive: {
type: Boolean,
required: true,
},
canSearch: {
type: Boolean,
required: true,
Expand All @@ -121,13 +124,16 @@ export default {
},
},

setup() {
setup(props) {
const { isActive } = toRefs(props)
const { sortParticipants } = useSortParticipants()
const isInCall = useIsInCall()
const { cancelableGetParticipants } = useGetParticipants(isActive, false)

return {
sortParticipants,
isInCall,
cancelableGetParticipants,
}
},

Expand All @@ -144,6 +150,10 @@ export default {
},

computed: {
participantsInitialised() {
return this.$store.getters.participantsInitialised(this.token)
},

participants() {
return this.$store.getters.participantsList(this.token).slice().sort(this.sortParticipants)
},
Expand Down Expand Up @@ -181,28 +191,19 @@ export default {
return this.searchText !== ''
},
noResults() {
return this.searchResults === []
return this.searchResults.length === 0
},
},

watch: {
searchText(value) {
this.isFocused = !!value
},

isActive(value) {
if (value && this.pendingChanges) {
this.debounceUpdateParticipants()
}
}
},

beforeMount() {
EventBus.$on('route-change', this.abortSearch)
subscribe('user_status:status.updated', this.updateUserStatus)

// Initialises the get participants mixin
this.initialiseGetParticipantsMixin()
},

beforeDestroy() {
Expand All @@ -211,8 +212,6 @@ export default {

this.cancelSearchPossibleConversations()
this.cancelSearchPossibleConversations = null

this.stopGetParticipantsMixin()
},

methods: {
Expand Down
23 changes: 6 additions & 17 deletions src/components/TopBar/TopBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ import TopBarMenu from './TopBarMenu.vue'
import BreakoutRoomsEditor from '../BreakoutRoomsEditor/BreakoutRoomsEditor.vue'
import ConversationIcon from '../ConversationIcon.vue'

import { useGetParticipants } from '../../composables/useGetParticipants.js'
import { CONVERSATION } from '../../constants.js'
import getParticipants from '../../mixins/getParticipants.js'
import BrowserStorage from '../../services/BrowserStorage.js'
import { getStatusMessage } from '../../utils/userStatus.js'
import { localCallParticipantModel, localMediaModel } from '../../utils/webrtc/index.js'
Expand Down Expand Up @@ -194,10 +194,7 @@ export default {
MessageText,
},

mixins: [
richEditor,
getParticipants,
],
mixins: [richEditor],

props: {
isInCall: {
Expand All @@ -214,6 +211,10 @@ export default {
},
},

setup() {
useGetParticipants()
},

data: () => {
return {
unreadNotificationHandle: null,
Expand Down Expand Up @@ -348,18 +349,6 @@ export default {
this.notifyUnreadMessages(null)
}
},

isOneToOneConversation: {
immediate: true,
// Group conversations have mixin in RightSidebar, so should work only for one-to-one
handler(newValue) {
if (newValue) {
this.initialiseGetParticipantsMixin()
} else {
this.stopGetParticipantsMixin()
}
},
},
},

mounted() {
Expand Down
136 changes: 136 additions & 0 deletions src/composables/useGetParticipants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/**
* @copyright Copyright (c) 2024 Dorra Jaouad <[email protected]>
*
* @author Dorra Jaouad <[email protected]>
* @author Marco Ambrosini <[email protected]>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import debounce from 'debounce'
import { ref, nextTick, computed, watch, onBeforeUnmount, onMounted } from 'vue'

import { subscribe, unsubscribe } from '@nextcloud/event-bus'

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

/**
* @param {import('vue').Ref} isActive whether the participants tab is active
* @param {boolean} isTopBar whether the component is the top bar
*/
export function useGetParticipants(isActive = ref(true), isTopBar = true) {

// Encapsulation
const store = useStore()
const token = computed(() => store.getters.getToken())
const conversation = computed(() => store.getters.conversation(token.value))
const isInCall = useIsInCall()
const isOneToOneConversation = computed(() => conversation.value?.type === CONVERSATION.TYPE.ONE_TO_ONE)
let fetchingParticipants = false
let pendingChanges = true

/**
* Initialise the get participants listeners
*
*/
function initialiseGetParticipants() {
EventBus.$on('joined-conversation', onJoinedConversation)

// FIXME this works only temporary until signaling is fixed to be only on the calls
// Then we have to search for another solution. Maybe the room list which we update
// periodically gets a hash of all online sessions?
EventBus.$on('signaling-participant-list-changed', debounceUpdateParticipants)
subscribe('guest-promoted', onJoinedConversation)
}

/**
* Stop the get participants listeners
*
*/
function stopGetParticipants() {
EventBus.$off('joined-conversation', onJoinedConversation)
EventBus.$off('signaling-participant-list-changed', debounceUpdateParticipants)
unsubscribe('guest-promoted', onJoinedConversation)
}

const onJoinedConversation = () => {
if (isOneToOneConversation.value) {
cancelableGetParticipants()
} else {
nextTick(() => debounceUpdateParticipants())
}
}

const debounceUpdateParticipants = () => {
if (!isActive.value && !isInCall.value) {
// Update is ignored but there is a flag to force the participants update
pendingChanges = true
return
}

if (store.getters.windowIsVisible() && (isInCall.value || !conversation.value?.hasCall)) {
debounceFastUpdateParticipants()
} else {
debounceSlowUpdateParticipants()
}
pendingChanges = false
}

const cancelableGetParticipants = async () => {
const isInLobby = store.getters.isInLobby
const isModeratorOrUser = store.getters.isModeratorOrUser
if (fetchingParticipants || token.value === '' || isInLobby || !isModeratorOrUser) {
return
}

fetchingParticipants = true
debounceFastUpdateParticipants.clear()
debounceSlowUpdateParticipants.clear()

await store.dispatch('fetchParticipants', { token: token.value })
fetchingParticipants = false
}

const debounceFastUpdateParticipants = debounce(
cancelableGetParticipants, 3000)
const debounceSlowUpdateParticipants = debounce(
cancelableGetParticipants, 15000)

onMounted(() => {
if (isTopBar) {
initialiseGetParticipants()
}
})

watch(isActive, (newValue) => {
if (newValue && pendingChanges) {
debounceUpdateParticipants()
}
})

onBeforeUnmount(() => {
if (isTopBar) {
stopGetParticipants()
}
})

return {
cancelableGetParticipants,
}
}
Loading

0 comments on commit 11f5314

Please sign in to comment.