mirror of
https://github.com/hcengineering/platform.git
synced 2025-01-03 00:43:59 +03:00
UBERF-6676: Chat local state (#5461)
Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
parent
608ea96cc8
commit
b282edfc65
@ -28,10 +28,12 @@
|
||||
import { NavigatorModel, SpecialNavModel } from '@hcengineering/workbench'
|
||||
import { InboxNotificationsClientImpl } from '@hcengineering/notification-resources'
|
||||
import { onMount } from 'svelte'
|
||||
import { chunterId } from '@hcengineering/chunter'
|
||||
import { ActivityMessage } from '@hcengineering/activity'
|
||||
|
||||
import ChatNavigator from './navigator/ChatNavigator.svelte'
|
||||
import ChannelView from '../ChannelView.svelte'
|
||||
import { chatSpecials, loadSavedAttachments } from './utils'
|
||||
import { chatSpecials, loadSavedAttachments, storeChannel, openedChannelStore, clearChannel } from './utils'
|
||||
import { SelectChannelEvent } from './types'
|
||||
import { decodeChannelURI, openChannel } from '../../navigation'
|
||||
|
||||
@ -58,6 +60,13 @@
|
||||
syncLocation(loc)
|
||||
})
|
||||
|
||||
openedChannelStore.subscribe((data) => {
|
||||
if (data && selectedData?._id !== data._id) {
|
||||
selectedData = data
|
||||
openChannel(data._id, data._class, data.thread)
|
||||
}
|
||||
})
|
||||
|
||||
$: void loadObject(selectedData?._id, selectedData?._class)
|
||||
|
||||
async function loadObject (_id?: Ref<Doc>, _class?: Ref<Class<Doc>>): Promise<void> {
|
||||
@ -77,17 +86,25 @@
|
||||
)
|
||||
}
|
||||
|
||||
function syncLocation (loc: Location) {
|
||||
const specialId = loc.path[3]
|
||||
function syncLocation (loc: Location): void {
|
||||
if (loc.path[2] !== chunterId) {
|
||||
return
|
||||
}
|
||||
|
||||
currentSpecial = navigatorModel?.specials?.find((special) => special.id === specialId)
|
||||
const id = loc.path[3]
|
||||
|
||||
if (!id) {
|
||||
return
|
||||
}
|
||||
|
||||
currentSpecial = navigatorModel?.specials?.find((special) => special.id === id)
|
||||
|
||||
if (currentSpecial !== undefined) {
|
||||
selectedData = undefined
|
||||
clearChannel()
|
||||
} else {
|
||||
const [_id, _class] = decodeChannelURI(loc.path[3])
|
||||
|
||||
selectedData = { _id, _class }
|
||||
storeChannel(_id, _class, loc.path[4] as Ref<ActivityMessage>)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,6 +188,7 @@
|
||||
|
||||
{#each sections as section (section.id)}
|
||||
<ChatNavSection
|
||||
id={section.id}
|
||||
objects={section.objects}
|
||||
{contexts}
|
||||
{objectId}
|
||||
|
@ -27,7 +27,9 @@
|
||||
import { ChatNavItemModel } from '../types'
|
||||
import { getObjectIcon, getChannelName } from '../../../utils'
|
||||
import ChatSectionHeader from './ChatSectionHeader.svelte'
|
||||
import { navigatorStateStore, toggleSections } from '../utils'
|
||||
|
||||
export let id: string
|
||||
export let header: string
|
||||
export let objects: Doc[]
|
||||
export let contexts: DocNotifyContext[]
|
||||
@ -46,6 +48,8 @@
|
||||
let canShowMore = false
|
||||
let isShownMore = false
|
||||
|
||||
$: isCollapsed = $navigatorStateStore.collapsedSections.includes(id)
|
||||
|
||||
$: void getChatNavItems(objects).then((res) => {
|
||||
items = sortFn(res, contexts)
|
||||
})
|
||||
@ -136,7 +140,7 @@
|
||||
{actions}
|
||||
{isCollapsed}
|
||||
on:collapse={() => {
|
||||
isCollapsed = !isCollapsed
|
||||
toggleSections(id)
|
||||
}}
|
||||
/>
|
||||
{#if !isCollapsed}
|
||||
@ -155,6 +159,12 @@
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{:else if objectId}
|
||||
{@const item = items.find(({ id }) => id === objectId)}
|
||||
{#if item}
|
||||
{@const context = contexts.find(({ attachedTo }) => attachedTo === item.id)}
|
||||
<ChatNavItem {context} isSelected {item} on:select />
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -13,13 +13,13 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
import notification, { type DocNotifyContext } from '@hcengineering/notification'
|
||||
import { generateId, SortingOrder, type WithLookup } from '@hcengineering/core'
|
||||
import { type Class, type Doc, generateId, type Ref, SortingOrder, type WithLookup } from '@hcengineering/core'
|
||||
import { createQuery, getClient, MessageBox } from '@hcengineering/presentation'
|
||||
import { get, writable } from 'svelte/store'
|
||||
import view from '@hcengineering/view'
|
||||
import { type SpecialNavModel } from '@hcengineering/workbench'
|
||||
import attachment, { type SavedAttachments } from '@hcengineering/attachment'
|
||||
import activity from '@hcengineering/activity'
|
||||
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'
|
||||
@ -27,7 +27,69 @@ import contact from '@hcengineering/contact'
|
||||
import { type ChatNavGroupModel, type ChatNavItemModel } from './types'
|
||||
import chunter from '../../plugin'
|
||||
|
||||
const channelStorageKey = 'chunter.openedChannel'
|
||||
const navigatorStateStorageKey = 'chunter.navigatorState'
|
||||
|
||||
interface ChannelMetadata {
|
||||
_id: Ref<Doc>
|
||||
_class: Ref<Class<Doc>>
|
||||
thread?: Ref<ActivityMessage>
|
||||
}
|
||||
interface NavigatorState {
|
||||
collapsedSections: string[]
|
||||
}
|
||||
|
||||
export const savedAttachmentsStore = writable<Array<WithLookup<SavedAttachments>>>([])
|
||||
export const openedChannelStore = writable<ChannelMetadata | undefined>(restoreChannel())
|
||||
export const navigatorStateStore = writable<NavigatorState>(restoreNavigatorState())
|
||||
|
||||
function restoreChannel (): ChannelMetadata | undefined {
|
||||
const raw = localStorage.getItem(channelStorageKey)
|
||||
|
||||
if (raw == null) return undefined
|
||||
|
||||
try {
|
||||
return JSON.parse(raw) as ChannelMetadata
|
||||
} catch (e) {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
function restoreNavigatorState (): NavigatorState {
|
||||
const raw = localStorage.getItem(navigatorStateStorageKey)
|
||||
|
||||
if (raw == null) return { collapsedSections: [] }
|
||||
|
||||
try {
|
||||
return JSON.parse(raw) as NavigatorState
|
||||
} catch (e) {
|
||||
return { collapsedSections: [] }
|
||||
}
|
||||
}
|
||||
|
||||
export function toggleSections (_id: string): void {
|
||||
const navState = get(navigatorStateStore)
|
||||
const result: NavigatorState = navState.collapsedSections.includes(_id)
|
||||
? {
|
||||
collapsedSections: navState.collapsedSections.filter((id) => id !== _id)
|
||||
}
|
||||
: { collapsedSections: [...navState.collapsedSections, _id] }
|
||||
|
||||
localStorage.setItem(navigatorStateStorageKey, JSON.stringify(result))
|
||||
navigatorStateStore.set(result)
|
||||
}
|
||||
|
||||
export function clearChannel (): void {
|
||||
localStorage.removeItem(channelStorageKey)
|
||||
openedChannelStore.set(undefined)
|
||||
}
|
||||
|
||||
export function storeChannel (_id: Ref<Doc>, _class: Ref<Class<Doc>>, thread?: Ref<ActivityMessage>): void {
|
||||
const data: ChannelMetadata = { _id, _class, thread }
|
||||
|
||||
localStorage.setItem(channelStorageKey, JSON.stringify(data))
|
||||
openedChannelStore.set(data)
|
||||
}
|
||||
|
||||
export const chatSpecials: SpecialNavModel[] = [
|
||||
{
|
||||
|
@ -16,7 +16,7 @@ function encodeChannelURI (_id: Ref<Doc>, _class: Ref<Class<Doc>>): string {
|
||||
return [_id, _class].join('|')
|
||||
}
|
||||
|
||||
export function openChannel (_id: Ref<Doc>, _class: Ref<Class<Doc>>): void {
|
||||
export function openChannel (_id: Ref<Doc>, _class: Ref<Class<Doc>>, thread?: Ref<ActivityMessage>): void {
|
||||
const loc = getCurrentLocation()
|
||||
|
||||
const id = encodeChannelURI(_id, _class)
|
||||
@ -26,9 +26,15 @@ export function openChannel (_id: Ref<Doc>, _class: Ref<Class<Doc>>): void {
|
||||
}
|
||||
|
||||
loc.path[3] = id
|
||||
loc.path[4] = ''
|
||||
loc.query = { ...loc.query, message: null }
|
||||
|
||||
if (thread !== undefined) {
|
||||
loc.path[4] = thread
|
||||
loc.path.length = 5
|
||||
} else {
|
||||
loc.path[4] = ''
|
||||
loc.path.length = 4
|
||||
}
|
||||
|
||||
navigate(loc)
|
||||
}
|
||||
|
@ -74,6 +74,7 @@ export async function buildDmName (client: Client, employeeAccounts: PersonAccou
|
||||
})
|
||||
})
|
||||
|
||||
const me = getCurrentAccount() as PersonAccount
|
||||
const map = await promise
|
||||
|
||||
unsub?.()
|
||||
@ -88,7 +89,7 @@ export async function buildDmName (client: Client, employeeAccounts: PersonAccou
|
||||
|
||||
const employee = map.get(acc.person as unknown as Ref<Employee>)
|
||||
|
||||
if (employee !== undefined) {
|
||||
if (employee !== undefined && me.person !== employee._id) {
|
||||
names.push(getName(client.getHierarchy(), employee))
|
||||
processedPersons.push(acc.person)
|
||||
}
|
||||
@ -156,13 +157,14 @@ async function getDmAccounts (client: Client, space?: Space): Promise<PersonAcco
|
||||
|
||||
export async function getDmPersons (client: Client, space: Space): Promise<Person[]> {
|
||||
const personAccounts: PersonAccount[] = await getDmAccounts(client, space)
|
||||
const me = getCurrentAccount() as PersonAccount
|
||||
const persons: Person[] = []
|
||||
|
||||
const personRefs = new Set(personAccounts.map(({ person }) => person))
|
||||
|
||||
for (const personRef of personRefs) {
|
||||
const person = await client.findOne(contact.class.Person, { _id: personRef })
|
||||
if (person !== undefined) {
|
||||
if (person !== undefined && me.person !== person._id) {
|
||||
persons.push(person)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user