Improve directs sort order (#5588)

Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
Kristina 2024-05-13 17:43:20 +04:00 committed by GitHub
parent f560afe0b9
commit adca777b33
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 109 additions and 13 deletions

View File

@ -21,10 +21,11 @@
import contact from '@hcengineering/contact'
import { getResource, translate } from '@hcengineering/platform'
import view from '@hcengineering/view'
import { personAccountByIdStore, statusByUserStore } from '@hcengineering/contact-resources'
import ChatNavItem from './ChatNavItem.svelte'
import chunter from '../../../plugin'
import { ChatNavItemModel } from '../types'
import { ChatNavItemModel, SortFnOptions } from '../types'
import { getObjectIcon, getChannelName } from '../../../utils'
import { navigatorStateStore, toggleSections } from '../utils'
@ -35,11 +36,12 @@
export let actions: Action[] = []
export let maxItems: number | undefined = undefined
export let objectId: Ref<Doc> | undefined
export let sortFn: (items: ChatNavItemModel[], contexts: DocNotifyContext[]) => ChatNavItemModel[]
export let sortFn: (items: ChatNavItemModel[], options: SortFnOptions) => ChatNavItemModel[]
const client = getClient()
const hierarchy = client.getHierarchy()
let sortedItems: ChatNavItemModel[] = []
let items: ChatNavItemModel[] = []
let visibleItems: ChatNavItemModel[] = []
@ -50,12 +52,17 @@
$: isCollapsed = $navigatorStateStore.collapsedSections.includes(id)
$: void getChatNavItems(objects).then((res) => {
items = sortFn(res, contexts)
items = res
})
$: sortedItems = sortFn(items, {
contexts,
userStatusByAccount: $statusByUserStore,
personAccountById: $personAccountByIdStore
})
$: canShowMore = !!maxItems && items.length > maxItems
$: visibleItems = getVisibleItems(canShowMore, isShownMore, maxItems, items, objectId)
$: visibleItems = getVisibleItems(canShowMore, isShownMore, maxItems, sortedItems, objectId)
async function getChatNavItems (objects: Doc[]): Promise<ChatNavItemModel[]> {
const items: ChatNavItemModel[] = []
@ -132,7 +139,7 @@
}
</script>
{#if items.length > 0 && contexts.length > 0}
{#if visibleItems.length > 0 && contexts.length > 0}
<NavGroup
title={header}
categoryName={id}
@ -161,7 +168,7 @@
</div>
{/if}
{:else if objectId}
{@const item = items.find(({ id }) => id === objectId)}
{@const item = visibleItems.find(({ id }) => id === objectId)}
{#if item}
{@const context = contexts.find(({ attachedTo }) => attachedTo === item.id)}
<ChatNavItem {context} isSelected {item} on:select />

View File

@ -13,17 +13,24 @@
// limitations under the License.
//
import { type Asset, type IntlString } from '@hcengineering/platform'
import { type Doc, type DocumentQuery, type Ref } from '@hcengineering/core'
import { type Account, type Doc, type DocumentQuery, type IdMap, type Ref, type UserStatus } from '@hcengineering/core'
import { type DocNotifyContext } from '@hcengineering/notification'
import { type AnySvelteComponent, type IconSize, type Action } from '@hcengineering/ui'
import { type PersonAccount } from '@hcengineering/contact'
export type ChatGroup = 'activity' | 'direct' | 'channels' | 'starred'
export interface SortFnOptions {
contexts: DocNotifyContext[]
userStatusByAccount: Map<Ref<Account>, UserStatus>
personAccountById: IdMap<PersonAccount>
}
export interface ChatNavGroupModel {
id: ChatGroup
label?: IntlString
query: DocumentQuery<DocNotifyContext>
sortFn: (items: ChatNavItemModel[], contexts: DocNotifyContext[]) => ChatNavItemModel[]
sortFn: (items: ChatNavItemModel[], options: SortFnOptions) => ChatNavItemModel[]
wrap: boolean
getActionsFn?: (contexts: DocNotifyContext[]) => Action[]
maxSectionItems?: number

View File

@ -22,7 +22,10 @@ import {
type WithLookup,
hasAccountRole,
getCurrentAccount,
AccountRole
AccountRole,
type IdMap,
type Account,
type UserStatus
} from '@hcengineering/core'
import { createQuery, getClient, MessageBox } from '@hcengineering/presentation'
import { get, writable } from 'svelte/store'
@ -32,9 +35,10 @@ import attachment, { type SavedAttachments } from '@hcengineering/attachment'
import activity, { type ActivityMessage } from '@hcengineering/activity'
import { InboxNotificationsClientImpl } from '@hcengineering/notification-resources'
import { type Action, showPopup } from '@hcengineering/ui'
import contact from '@hcengineering/contact'
import contact, { type PersonAccount } from '@hcengineering/contact'
import { type DirectMessage } from '@hcengineering/chunter'
import { type ChatNavGroupModel, type ChatNavItemModel } from './types'
import { type ChatNavGroupModel, type ChatNavItemModel, type SortFnOptions } from './types'
import chunter from '../../plugin'
const channelStorageKey = 'chunter.openedChannel'
@ -184,7 +188,7 @@ export const chatNavGroupModels: ChatNavGroupModel[] = [
},
{
id: 'direct',
sortFn: sortAlphabetically,
sortFn: sortDirects,
wrap: true,
getActionsFn: getDirectActions,
query: {
@ -212,7 +216,85 @@ function sortAlphabetically (items: ChatNavItemModel[]): ChatNavItemModel[] {
return items.sort((i1, i2) => i1.title.localeCompare(i2.title))
}
function sortActivityChannels (items: ChatNavItemModel[], contexts: DocNotifyContext[]): ChatNavItemModel[] {
function getDirectCompanion (
direct: DirectMessage,
me: PersonAccount,
personAccountById: IdMap<PersonAccount>
): Ref<Account> | undefined {
return direct.members.find((member) => personAccountById.get(member as Ref<PersonAccount>)?.person !== me.person)
}
function isOnline (account: Ref<Account> | undefined, userStatusByAccount: Map<Ref<Account>, UserStatus>): boolean {
if (account === undefined) {
return false
}
return userStatusByAccount.get(account)?.online ?? false
}
function isGroupChat (direct: DirectMessage, personAccountById: IdMap<PersonAccount>): boolean {
const persons = new Set(
direct.members
.map((member) => personAccountById.get(member as Ref<PersonAccount>)?.person)
.filter((it) => it !== undefined)
)
return persons.size > 2
}
function sortDirects (items: ChatNavItemModel[], option: SortFnOptions): ChatNavItemModel[] {
const { userStatusByAccount, personAccountById } = option
const me = getCurrentAccount() as PersonAccount
return items.sort((i1, i2) => {
const direct1 = i1.object as DirectMessage
const direct2 = i2.object as DirectMessage
const isGroupChat1 = isGroupChat(direct1, personAccountById)
const isGroupChat2 = isGroupChat(direct2, personAccountById)
if (isGroupChat1 && isGroupChat2) {
return i1.title.localeCompare(i2.title)
}
if (isGroupChat1 && !isGroupChat2) {
const isOnline2 = isOnline(getDirectCompanion(direct2, me, personAccountById), userStatusByAccount)
return isOnline2 ? 1 : -1
}
if (!isGroupChat1 && isGroupChat2) {
const isOnline1 = isOnline(getDirectCompanion(direct1, me, personAccountById), userStatusByAccount)
return isOnline1 ? -1 : 1
}
const account1 = getDirectCompanion(direct1, me, personAccountById)
const account2 = getDirectCompanion(direct2, me, personAccountById)
if (account1 === undefined) {
return 1
}
if (account2 === undefined) {
return -1
}
const isOnline1 = isOnline(account1, userStatusByAccount)
const isOnline2 = isOnline(account2, userStatusByAccount)
if (isOnline1 === isOnline2) {
return i1.title.localeCompare(i2.title)
}
if (isOnline1 && !isOnline2) {
return -1
}
return 1
})
}
function sortActivityChannels (items: ChatNavItemModel[], option: SortFnOptions): ChatNavItemModel[] {
const { contexts } = option
const contextByDoc = new Map(contexts.map((context) => [context.attachedTo, context]))
return items.sort((i1, i2) => {