Fix thread blink in inbox (#6686)

Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
Kristina 2024-09-23 17:41:56 +04:00 committed by GitHub
parent 21a5f07870
commit a4379d72d1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 73 additions and 51 deletions

View File

@ -500,9 +500,9 @@
updateSelectedDate() updateSelectedDate()
if (selectedMessageId !== undefined && messages.some(({ _id }) => _id === selectedMessageId)) { if (selectedMessageId !== undefined && messages.some(({ _id }) => _id === selectedMessageId)) {
isScrollInitialized = true
await wait() await wait()
scrollToMessage() scrollToMessage()
isScrollInitialized = true
isInitialScrolling = false isInitialScrolling = false
} else if (separatorIndex === -1) { } else if (separatorIndex === -1) {
await wait() await wait()
@ -800,6 +800,7 @@
bind:divBox={scrollContentBox} bind:divBox={scrollContentBox}
noStretch={false} noStretch={false}
disableOverscroll disableOverscroll
horizontal={false}
onScroll={handleScroll} onScroll={handleScroll}
onResize={handleResize} onResize={handleResize}
> >

View File

@ -143,6 +143,8 @@
dispatch('channel') dispatch('channel')
} }
$: messagesStore = dataProvider?.messagesStore
</script> </script>
{#if showHeader} {#if showHeader}
@ -167,10 +169,13 @@
<ThreadParentMessage {message} /> <ThreadParentMessage {message} />
</div> </div>
{#if message.replies && message.replies > 0} {#if (message.replies ?? $messagesStore?.length ?? 0) > 0}
<div class="separator"> <div class="separator">
<div class="label lower"> <div class="label lower">
<Label label={activity.string.RepliesCount} params={{ replies: message.replies }} /> <Label
label={activity.string.RepliesCount}
params={{ replies: message.replies ?? $messagesStore?.length ?? 1 }}
/>
</div> </div>
<div class="line" /> <div class="line" />
</div> </div>

View File

@ -150,6 +150,7 @@ export async function buildThreadLink (
loc.path[2] = chunterId loc.path[2] = chunterId
} }
loc.query = { message: '' }
loc.path[3] = objectURI loc.path[3] = objectURI
loc.path[4] = threadParent loc.path[4] = threadParent
loc.fragment = undefined loc.fragment = undefined
@ -177,7 +178,7 @@ export async function replyToThread (message: ActivityMessage, e: Event): Promis
} }
} }
void openThreadInSidebar(message._id, message) await openThreadInSidebar(message._id, message)
if (loc.path[2] !== chunterId && loc.path[2] !== notificationId) { if (loc.path[2] !== chunterId && loc.path[2] !== notificationId) {
return return
} }
@ -326,10 +327,14 @@ export async function openThreadInSidebar (_id: Ref<ActivityMessage>, msg?: Acti
const name = (await getChannelName(object._id, object._class, object)) ?? (await translate(titleIntl, {})) const name = (await getChannelName(object._id, object._class, object)) ?? (await translate(titleIntl, {}))
const tabName = await translate(chunter.string.ThreadIn, { name }) const tabName = await translate(chunter.string.ThreadIn, { name })
const loc = getCurrentLocation() const loc = getCurrentLocation()
const allowedPath = loc.path.join('/')
const currentTAbs = get(sidebarStore).widgetsState.get(widget._id)?.tabs ?? [] if (loc.path[2] === chunterId || loc.path[2] === notificationId) {
const tabsToClose = currentTAbs.filter((t) => t.isPinned !== true && t.allowedPath === allowedPath).map((t) => t.id) loc.path[4] = message._id
}
const allowedPath = loc.path.join('/')
const currentTabs = get(sidebarStore).widgetsState.get(widget._id)?.tabs ?? []
const tabsToClose = currentTabs.filter((t) => t.isPinned !== true && t.allowedPath === allowedPath).map((t) => t.id)
if (tabsToClose.length > 0) { if (tabsToClose.length > 0) {
sidebarStore.update((s) => { sidebarStore.update((s) => {

View File

@ -11,7 +11,7 @@
"Remove": "Удалить нотификацию", "Remove": "Удалить нотификацию",
"RemoveAll": "Удалить все нотификации", "RemoveAll": "Удалить все нотификации",
"MarkAllAsRead": "Отметить все нотификации как прочитанные", "MarkAllAsRead": "Отметить все нотификации как прочитанные",
"MarkAsRead": "Отметить нотификация прочитанной", "MarkAsRead": "Отметить прочитанным",
"MarkAsUnread": "Отметить непрочитанным", "MarkAsUnread": "Отметить непрочитанным",
"Archive": "Архивировать", "Archive": "Архивировать",
"Inbox": "Входящие", "Inbox": "Входящие",

View File

@ -198,7 +198,7 @@
<div <div
class="card" class="card"
on:click={() => { on:click={() => {
dispatch('click', { context: value }) dispatch('click', { context: value, object })
}} }}
> >
{#if isLoading} {#if isLoading}
@ -266,7 +266,7 @@
on:click={(e) => { on:click={(e) => {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
dispatch('click', { context: value, notification: group[0] }) dispatch('click', { context: value, notification: group[0], object })
}} }}
/> />
</div> </div>

View File

@ -256,7 +256,7 @@
const selectedNotification: InboxNotification | undefined = event?.detail?.notification const selectedNotification: InboxNotification | undefined = event?.detail?.notification
void selectInboxContext(linkProviders, selectedContext, selectedNotification) void selectInboxContext(linkProviders, selectedContext, selectedNotification, event?.detail.object)
} }
async function updateSelectedPanel (selectedContext?: DocNotifyContext): Promise<void> { async function updateSelectedPanel (selectedContext?: DocNotifyContext): Promise<void> {
@ -373,6 +373,7 @@
} }
] ]
$: $deviceInfo.replacedPanel = replacedPanel $: $deviceInfo.replacedPanel = replacedPanel
onDestroy(() => { onDestroy(() => {
$deviceInfo.replacedPanel = undefined $deviceInfo.replacedPanel = undefined
unsubscribeLoc() unsubscribeLoc()

View File

@ -583,7 +583,8 @@ export function resetInboxContext (): void {
export async function selectInboxContext ( export async function selectInboxContext (
linkProviders: LinkIdProvider[], linkProviders: LinkIdProvider[],
context: DocNotifyContext, context: DocNotifyContext,
notification?: WithLookup<InboxNotification> notification?: WithLookup<InboxNotification>,
object?: Doc
): Promise<void> { ): Promise<void> {
const client = getClient() const client = getClient()
const hierarchy = client.getHierarchy() const hierarchy = client.getHierarchy()
@ -607,7 +608,10 @@ export async function selectInboxContext (
const message = (notification as WithLookup<ActivityInboxNotification>)?.$lookup?.attachedTo const message = (notification as WithLookup<ActivityInboxNotification>)?.$lookup?.attachedTo
if (objectClass === chunter.class.ThreadMessage) { if (objectClass === chunter.class.ThreadMessage) {
const thread = await client.findOne( const thread =
object?._id === objectId
? (object as ThreadMessage)
: await client.findOne(
chunter.class.ThreadMessage, chunter.class.ThreadMessage,
{ {
_id: objectId as Ref<ThreadMessage> _id: objectId as Ref<ThreadMessage>
@ -615,16 +619,31 @@ export async function selectInboxContext (
{ projection: { _id: 1, attachedTo: 1 } } { projection: { _id: 1, attachedTo: 1 } }
) )
void navigateToInboxDoc(linkProviders, objectId, objectClass, thread?.attachedTo, thread?._id) void navigateToInboxDoc(
linkProviders,
thread?.objectId ?? objectId,
thread?.objectClass ?? objectClass,
thread?.attachedTo,
thread?._id
)
return return
} }
if (isReactionMessage(message)) { if (isReactionMessage(message)) {
const thread = loc.path[4] === objectId ? objectId : undefined const thread = loc.path[4] === objectId ? objectId : undefined
const reactedTo =
(object as ActivityMessage) ??
(await client.findOne(activity.class.ActivityMessage, { _id: message.attachedTo as Ref<ActivityMessage> }))
const isThread = hierarchy.isDerived(reactedTo._class, chunter.class.ThreadMessage)
const channelId = isThread ? (reactedTo as ThreadMessage)?.objectId : reactedTo?.attachedTo ?? objectId
const channelClass = isThread
? (reactedTo as ThreadMessage)?.objectClass
: reactedTo?.attachedToClass ?? objectClass
void navigateToInboxDoc( void navigateToInboxDoc(
linkProviders, linkProviders,
objectId, channelId,
objectClass, channelClass,
thread as Ref<ActivityMessage>, thread as Ref<ActivityMessage>,
objectId as Ref<ActivityMessage> objectId as Ref<ActivityMessage>
) )
@ -633,11 +652,13 @@ export async function selectInboxContext (
const selectedMsg = (notification as ActivityInboxNotification)?.attachedTo const selectedMsg = (notification as ActivityInboxNotification)?.attachedTo
const thread = selectedMsg !== objectId ? objectId : loc.path[4] === objectId ? objectId : undefined const thread = selectedMsg !== objectId ? objectId : loc.path[4] === objectId ? objectId : undefined
const channelId = (object as ActivityMessage)?.attachedTo ?? message?.attachedTo ?? objectId
const channelClass = (object as ActivityMessage)?.attachedToClass ?? message?.attachedToClass ?? objectClass
void navigateToInboxDoc( void navigateToInboxDoc(
linkProviders, linkProviders,
objectId, channelId,
objectClass, channelClass,
thread as Ref<ActivityMessage>, thread as Ref<ActivityMessage>,
selectedMsg ?? (objectId as Ref<ActivityMessage>) selectedMsg ?? (objectId as Ref<ActivityMessage>)
) )

View File

@ -28,7 +28,7 @@
$: if (query) updateSearchQuery(search) $: if (query) updateSearchQuery(search)
let resultQuery: DocumentQuery<Issue> = { ...searchQuery } let resultQuery: DocumentQuery<Issue> = { ...searchQuery }
$: if (!label && title) { $: if (title) {
void translate(title, {}, $themeStore.language).then((res) => { void translate(title, {}, $themeStore.language).then((res) => {
label = res label = res
}) })

View File

@ -24,7 +24,7 @@
Breadcrumbs, Breadcrumbs,
getCurrentLocation getCurrentLocation
} from '@hcengineering/ui' } from '@hcengineering/ui'
import { onDestroy } from 'svelte' import { onDestroy, onMount } from 'svelte'
import { closeWidgetTab, sidebarStore, SidebarVariant, WidgetState, openWidgetTab, closeWidget } from '../../sidebar' import { closeWidgetTab, sidebarStore, SidebarVariant, WidgetState, openWidgetTab, closeWidget } from '../../sidebar'
import WidgetsBar from './widgets/WidgetsBar.svelte' import WidgetsBar from './widgets/WidgetsBar.svelte'
@ -46,36 +46,15 @@
$: widgetState = widget !== undefined ? $sidebarStore.widgetsState.get(widget._id) : undefined $: widgetState = widget !== undefined ? $sidebarStore.widgetsState.get(widget._id) : undefined
$: tabId = widgetState?.tab $: tabId = widgetState?.tab
$: tabs = getTabs(widget, widgetState) $: tabs = widgetState?.tabs ?? []
$: tab = tabId !== undefined ? tabs.find((it) => it.id === tabId) ?? tabs[0] : tabs[0] $: tab = tabId !== undefined ? tabs.find((it) => it.id === tabId) ?? tabs[0] : tabs[0]
$: if ($sidebarStore.widget === undefined) { $: if ($sidebarStore.widget === undefined) {
sidebarStore.update((s) => ({ ...s, variant: SidebarVariant.MINI })) sidebarStore.update((s) => ({ ...s, variant: SidebarVariant.MINI }))
} }
function getTabs (widget?: Widget, state?: WidgetState): WidgetTab[] { function closeWrongTabs (loc: Location): void {
if (widget === undefined || !state?.tabs) return []
const loc = getCurrentLocation()
const result: WidgetTab[] = []
for (const tab of state.tabs) {
if (tab.allowedPath !== undefined && !tab.isPinned) {
const path = loc.path.join('/')
if (!path.startsWith(tab.allowedPath)) {
void handleTabClose(tab.id, widget)
continue
}
}
result.push(tab)
}
return result
}
const unsubscribe = locationStore.subscribe((loc: Location) => {
if (widget === undefined) return if (widget === undefined) return
for (const tab of tabs) { for (const tab of tabs) {
if (tab.allowedPath !== undefined && !tab.isPinned) { if (tab.allowedPath !== undefined && !tab.isPinned) {
const path = loc.path.join('/') const path = loc.path.join('/')
@ -84,6 +63,14 @@
} }
} }
} }
}
const unsubscribe = locationStore.subscribe((loc: Location) => {
closeWrongTabs(loc)
})
onMount(() => {
closeWrongTabs(getCurrentLocation())
}) })
onDestroy(() => { onDestroy(() => {

View File

@ -203,7 +203,6 @@ export function openWidgetTab (widget: Ref<Widget>, tab: string): void {
} }
export function createWidgetTab (widget: Widget, tab: WidgetTab, newTab = false): void { export function createWidgetTab (widget: Widget, tab: WidgetTab, newTab = false): void {
openWidget(widget)
const state = get(sidebarStore) const state = get(sidebarStore)
const { widgetsState } = state const { widgetsState } = state
const widgetState = widgetsState.get(widget._id) const widgetState = widgetsState.get(widget._id)
@ -225,6 +224,7 @@ export function createWidgetTab (widget: Widget, tab: WidgetTab, newTab = false)
} }
widgetsState.set(widget._id, { widgetsState.set(widget._id, {
...widgetState,
_id: widget._id, _id: widget._id,
tabs: newTabs, tabs: newTabs,
tab: tab.id tab: tab.id
@ -232,7 +232,9 @@ export function createWidgetTab (widget: Widget, tab: WidgetTab, newTab = false)
sidebarStore.set({ sidebarStore.set({
...state, ...state,
widgetsState widget: widget._id,
widgetsState,
variant: SidebarVariant.EXPANDED
}) })
} }