Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
import NcModal from '@nextcloud/vue/dist/Components/NcModal.js'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'

import DialpadPanel from '../../UIShared/DialpadPanel.vue'
import LoadingComponent from '../../LoadingComponent.vue'
import SelectPhoneNumber from '../../SelectPhoneNumber.vue'
import DialpadPanel from '../../UIShared/DialpadPanel.vue'

import { CONVERSATION, PARTICIPANT } from '../../../constants.js'
import { callSIPDialOut } from '../../../services/callsService.js'
Expand Down
93 changes: 70 additions & 23 deletions src/components/LeftSidebar/LeftSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -182,28 +182,28 @@

<!-- Search results -->
<ul v-else class="h-100 scroller">
<!-- Search results: user's conversations -->
<NcAppNavigationCaption :name="t('spreed', 'Conversations')" />
<Conversation v-for="item of searchResultsConversationList"
:key="`conversation_${item.id}`"
:ref="`conversation-${item.token}`"
:item="item"
@click="abortSearch" />
<Hint v-if="searchResultsConversationList.length === 0" :hint="t('spreed', 'No matches found')" />

<!-- Create a new conversation -->
<NcListItem v-if="canStartConversations"
:name="t('spreed', 'Create a new conversation')"
:name="searchText"
data-nav-id="conversation_create_new"
@click="createConversation(searchText)">
<template #icon>
<ChatPlus :size="30" />
<ChatPlus :size="44" />
</template>
<template #subname>
{{ searchText }}
{{ t('spreed', 'New group conversation') }}
</template>
</NcListItem>

<!-- Search results: user's conversations -->
<NcAppNavigationCaption :name="t('spreed', 'Conversations')" />
<Conversation v-for="item of searchResultsConversationList"
:key="`conversation_${item.id}`"
:ref="`conversation-${item.token}`"
:item="item"
@click="abortSearch" />
<Hint v-if="searchResultsConversationList.length === 0" :hint="t('spreed', 'No matches found')" />

<!-- Search results: listed (open) conversations -->
<template v-if="!listedConversationsLoading && searchResultsListedConversations.length !== 0">
<NcAppNavigationCaption :name="t('spreed', 'Open conversations')" />
Expand All @@ -223,7 +223,10 @@
:name="item.label"
@click="createAndJoinConversation(item)">
<template #icon>
<ConversationIcon :item="iconData(item)" />
<AvatarWrapper v-bind="iconData(item)" />
</template>
<template #subname>
{{ t('spreed', 'New private conversation') }}
</template>
</NcListItem>
</template>
Expand All @@ -241,6 +244,9 @@
<template #icon>
<ConversationIcon :item="iconData(item)" />
</template>
<template #subname>
{{ t('spreed', 'New group conversation') }}
</template>
</NcListItem>
</template>

Expand All @@ -255,14 +261,36 @@
<template #icon>
<ConversationIcon :item="iconData(item)" />
</template>
<template #subname>
{{ t('spreed', 'New group conversation') }}
</template>
</NcListItem>
</template>

<!-- New conversations: Federated users -->
<template v-if="searchResultsFederated.length !== 0">
<NcAppNavigationCaption :name="t('spreed', 'Federated users')" />
<NcListItem v-for="item of searchResultsFederated"
:key="`federated_${item.id}`"
:data-nav-id="`federated_${item.id}`"
:name="item.label"
@click="createAndJoinConversation(item)">
<template #icon>
<AvatarWrapper v-bind="iconData(item)" />
</template>
<template #subname>
{{ t('spreed', 'New group conversation') }}
</template>
</NcListItem>
</template>
</template>

<!-- Search results: no results (yet) -->
<NcAppNavigationCaption v-if="sourcesWithoutResults" :name="sourcesWithoutResultsList" />
<Hint v-if="contactsLoading" :hint="t('spreed', 'Loading')" />
<Hint v-else :hint="t('spreed', 'No search results')" />
<template v-if="sourcesWithoutResults">
<NcAppNavigationCaption :name="sourcesWithoutResultsList" />
<Hint :hint="t('spreed', 'No search results')" />
</template>
<Hint v-else-if="contactsLoading" :hint="t('spreed', 'Loading')" />
</ul>
</li>
</template>
Expand Down Expand Up @@ -316,10 +344,11 @@ import Conversation from './ConversationsList/Conversation.vue'
import ConversationsListVirtual from './ConversationsList/ConversationsListVirtual.vue'
import InvitationHandler from './InvitationHandler.vue'
import OpenConversationsList from './OpenConversationsList/OpenConversationsList.vue'
import SearchBox from '../UIShared/SearchBox.vue'
import AvatarWrapper from '../AvatarWrapper/AvatarWrapper.vue'
import ConversationIcon from '../ConversationIcon.vue'
import Hint from '../UIShared/Hint.vue'
import NewConversationDialog from '../NewConversationDialog/NewConversationDialog.vue'
import Hint from '../UIShared/Hint.vue'
import SearchBox from '../UIShared/SearchBox.vue'
import TransitionWrapper from '../UIShared/TransitionWrapper.vue'

import { useArrowNavigation } from '../../composables/useArrowNavigation.js'
Expand Down Expand Up @@ -349,6 +378,7 @@ export default {
name: 'LeftSidebar',

components: {
AvatarWrapper,
CallPhoneDialog,
InvitationHandler,
NcAppNavigation,
Expand Down Expand Up @@ -389,7 +419,7 @@ export default {

const federationStore = useFederationStore()
const talkHashStore = useTalkHashStore()
const { initializeNavigation, resetNavigation } = useArrowNavigation(leftSidebar, searchBox, '.list-item')
const { initializeNavigation, resetNavigation } = useArrowNavigation(leftSidebar, searchBox)
const isMobile = useIsMobile()

return {
Expand All @@ -413,6 +443,7 @@ export default {
searchResultsUsers: [],
searchResultsGroups: [],
searchResultsCircles: [],
searchResultsFederated: [],
searchResultsListedConversations: [],
contactsLoading: false,
listedConversationsLoading: false,
Expand Down Expand Up @@ -703,6 +734,10 @@ export default {
})
this.searchResultsGroups = this.searchResults.filter((match) => match.source === ATTENDEE.ACTOR_TYPE.GROUPS)
this.searchResultsCircles = this.searchResults.filter((match) => match.source === ATTENDEE.ACTOR_TYPE.CIRCLES)
this.searchResultsFederated = this.searchResults.filter((match) => match.source === ATTENDEE.ACTOR_TYPE.REMOTES)
.map((item) => {
return { ...item, source: ATTENDEE.ACTOR_TYPE.FEDERATED_USERS }
})
this.contactsLoading = false
} catch (exception) {
if (CancelableRequest.isCancel(exception)) {
Expand Down Expand Up @@ -960,11 +995,15 @@ export default {
},

iconData(item) {
if (item.source === ATTENDEE.ACTOR_TYPE.USERS) {
if (item.source === ATTENDEE.ACTOR_TYPE.USERS
|| item.source === ATTENDEE.ACTOR_TYPE.FEDERATED_USERS) {
return {
type: CONVERSATION.TYPE.ONE_TO_ONE,
displayName: item.label,
name: item.id,
id: item.id,
name: item.label,
source: item.source,
disableMenu: true,
token: 'new',
showUserStatus: true,
}
}
return {
Expand Down Expand Up @@ -1074,6 +1113,14 @@ export default {
padding: 0 !important;
}

:deep(.app-navigation-caption):not(:first-child) {
margin-top: 12px !important;
}

:deep(.app-navigation-caption__name) {
margin: 0 !important;
}

:deep(.list-item) {
overflow: hidden;
outline-offset: -2px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ import { showError } from '@nextcloud/dialogs'

import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'

import ContactSelectionBubble from '../UIShared/ContactSelectionBubble.vue'
import DialpadPanel from '../UIShared/DialpadPanel.vue'
import ParticipantSearchResults from '../RightSidebar/Participants/ParticipantsSearchResults.vue'
import SelectPhoneNumber from '../SelectPhoneNumber.vue'
import ContactSelectionBubble from '../UIShared/ContactSelectionBubble.vue'
import DialpadPanel from '../UIShared/DialpadPanel.vue'
import TransitionWrapper from '../UIShared/TransitionWrapper.vue'

import { useArrowNavigation } from '../../composables/useArrowNavigation.js'
Expand Down Expand Up @@ -131,7 +131,7 @@ export default {
const wrapper = ref(null)
const setContacts = ref(null)

const { initializeNavigation, resetNavigation } = useArrowNavigation(wrapper, setContacts, '.participant-row')
const { initializeNavigation, resetNavigation } = useArrowNavigation(wrapper, setContacts)

return {
initializeNavigation,
Expand Down
2 changes: 1 addition & 1 deletion src/components/RightSidebar/Participants/Participant.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
'selected': isSelected }"
:aria-label="participantAriaLabel"
:role="isSearched ? 'listitem' : undefined"
:tabindex="isSearched ? 0 : undefined"
:tabindex="0"
v-on="isSearched ? { click: handleClick, 'keydown.enter': handleClick } : {}"
@keydown.enter="handleClick">
<!-- Participant's avatar -->
Expand Down
41 changes: 36 additions & 5 deletions src/components/RightSidebar/Participants/ParticipantsTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
-->

<template>
<div class="wrapper">
<div ref="wrapper" class="wrapper">
<div class="search-form">
<SearchBox v-if="canSearch"
ref="searchBox"
class="search-form__input"
:value.sync="searchText"
:is-focused.sync="isFocused"
Expand All @@ -46,15 +47,17 @@
:participants="participants"
:loading="!participantsInitialised" />

<div v-else class="scroller">
<div v-else class="scroller h-100">
<NcAppNavigationCaption v-if="canAdd" :name="t('spreed', 'Participants')" />

<ParticipantsList v-if="filteredParticipants.length"
class="known-results"
:items="filteredParticipants"
:loading="!participantsInitialised" />
<Hint v-else :hint="t('spreed', 'No search results')" />

<ParticipantsSearchResults v-if="canAdd"
class="search-results"
:search-results="searchResults"
:contacts-loading="contactsLoading"
:no-results="noResults"
Expand All @@ -66,7 +69,7 @@

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

import { getCapabilities } from '@nextcloud/capabilities'
import { showError } from '@nextcloud/dialogs'
Expand All @@ -77,11 +80,12 @@ import NcAppNavigationCaption from '@nextcloud/vue/dist/Components/NcAppNavigati
import ParticipantsList from './ParticipantsList.vue'
import ParticipantsListVirtual from './ParticipantsListVirtual.vue'
import ParticipantsSearchResults from './ParticipantsSearchResults.vue'
import SelectPhoneNumber from '../../SelectPhoneNumber.vue'
import DialpadPanel from '../../UIShared/DialpadPanel.vue'
import Hint from '../../UIShared/Hint.vue'
import SearchBox from '../../UIShared/SearchBox.vue'
import SelectPhoneNumber from '../../SelectPhoneNumber.vue'

import { useArrowNavigation } from '../../../composables/useArrowNavigation.js'
import { useGetParticipants } from '../../../composables/useGetParticipants.js'
import { useIsInCall } from '../../../composables/useIsInCall.js'
import { useSortParticipants } from '../../../composables/useSortParticipants.js'
Expand Down Expand Up @@ -125,12 +129,20 @@ export default {
},

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

const { initializeNavigation, resetNavigation } = useArrowNavigation(wrapper, searchBox)

return {
initializeNavigation,
resetNavigation,
wrapper,
searchBox,
sortParticipants,
isInCall,
cancelableGetParticipants,
Expand Down Expand Up @@ -253,7 +265,7 @@ export default {
if (!this.isSearching) {
return
}

this.resetNavigation()
try {
this.cancelSearchPossibleConversations('canceled')
const { request, cancel } = CancelableRequest(searchPossibleConversations)
Expand All @@ -266,6 +278,9 @@ export default {

this.searchResults = response?.data?.ocs?.data || []
this.contactsLoading = false
this.$nextTick(() => {
this.initializeNavigation()
})
} catch (exception) {
if (CancelableRequest.isCancel(exception)) {
return
Expand Down Expand Up @@ -356,6 +371,14 @@ export default {
overflow-y: auto;
}

.known-results {
padding: 0 2px;
}

.search-results {
margin-top: 12px; // compensate margin before first header inside
}

/** TODO: fix these in the nextcloud-vue library **/

:deep(.app-sidebar-header__menu) {
Expand All @@ -369,6 +392,14 @@ export default {
right: 6px !important;
}

:deep(.app-navigation-caption):not(:first-child) {
margin-top: 12px !important;
}

:deep(.app-navigation-caption__name) {
margin: 0 !important;
}

/*
* The field will fully overlap the top of the sidebar content so
* that elements will scroll behind it
Expand Down
Loading