From a4379d72d113d453be39bc8f36076546b8e781ea Mon Sep 17 00:00:00 2001 From: Kristina Date: Mon, 23 Sep 2024 17:41:56 +0400 Subject: [PATCH 01/10] Fix thread blink in inbox (#6686) Signed-off-by: Kristina Fefelova --- .../src/components/ChannelScrollView.svelte | 3 +- .../src/components/threads/ThreadView.svelte | 9 +++- plugins/chunter-resources/src/navigation.ts | 13 +++-- plugins/notification-assets/lang/ru.json | 2 +- .../components/DocNotifyContextCard.svelte | 4 +- .../src/components/inbox/Inbox.svelte | 3 +- plugins/notification-resources/src/utils.ts | 47 ++++++++++++++----- .../src/components/issues/IssuesView.svelte | 2 +- .../components/sidebar/SidebarExpanded.svelte | 35 +++++--------- plugins/workbench-resources/src/sidebar.ts | 6 ++- 10 files changed, 73 insertions(+), 51 deletions(-) diff --git a/plugins/chunter-resources/src/components/ChannelScrollView.svelte b/plugins/chunter-resources/src/components/ChannelScrollView.svelte index d02a25591e..1863acb886 100644 --- a/plugins/chunter-resources/src/components/ChannelScrollView.svelte +++ b/plugins/chunter-resources/src/components/ChannelScrollView.svelte @@ -500,9 +500,9 @@ updateSelectedDate() if (selectedMessageId !== undefined && messages.some(({ _id }) => _id === selectedMessageId)) { - isScrollInitialized = true await wait() scrollToMessage() + isScrollInitialized = true isInitialScrolling = false } else if (separatorIndex === -1) { await wait() @@ -800,6 +800,7 @@ bind:divBox={scrollContentBox} noStretch={false} disableOverscroll + horizontal={false} onScroll={handleScroll} onResize={handleResize} > diff --git a/plugins/chunter-resources/src/components/threads/ThreadView.svelte b/plugins/chunter-resources/src/components/threads/ThreadView.svelte index 180a132bc5..9a249b28de 100644 --- a/plugins/chunter-resources/src/components/threads/ThreadView.svelte +++ b/plugins/chunter-resources/src/components/threads/ThreadView.svelte @@ -143,6 +143,8 @@ dispatch('channel') } + + $: messagesStore = dataProvider?.messagesStore {#if showHeader} @@ -167,10 +169,13 @@ - {#if message.replies && message.replies > 0} + {#if (message.replies ?? $messagesStore?.length ?? 0) > 0}
-
diff --git a/plugins/chunter-resources/src/navigation.ts b/plugins/chunter-resources/src/navigation.ts index 668543fb96..6e9cf29e75 100644 --- a/plugins/chunter-resources/src/navigation.ts +++ b/plugins/chunter-resources/src/navigation.ts @@ -150,6 +150,7 @@ export async function buildThreadLink ( loc.path[2] = chunterId } + loc.query = { message: '' } loc.path[3] = objectURI loc.path[4] = threadParent 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) { return } @@ -326,10 +327,14 @@ export async function openThreadInSidebar (_id: Ref, msg?: Acti const name = (await getChannelName(object._id, object._class, object)) ?? (await translate(titleIntl, {})) const tabName = await translate(chunter.string.ThreadIn, { name }) const loc = getCurrentLocation() - 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 (loc.path[2] === chunterId || loc.path[2] === notificationId) { + 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) { sidebarStore.update((s) => { diff --git a/plugins/notification-assets/lang/ru.json b/plugins/notification-assets/lang/ru.json index ada9f03cc5..f46bcb90e7 100644 --- a/plugins/notification-assets/lang/ru.json +++ b/plugins/notification-assets/lang/ru.json @@ -11,7 +11,7 @@ "Remove": "Удалить нотификацию", "RemoveAll": "Удалить все нотификации", "MarkAllAsRead": "Отметить все нотификации как прочитанные", - "MarkAsRead": "Отметить нотификация прочитанной", + "MarkAsRead": "Отметить прочитанным", "MarkAsUnread": "Отметить непрочитанным", "Archive": "Архивировать", "Inbox": "Входящие", diff --git a/plugins/notification-resources/src/components/DocNotifyContextCard.svelte b/plugins/notification-resources/src/components/DocNotifyContextCard.svelte index 9c5b3fd89a..d9c8b7ef75 100644 --- a/plugins/notification-resources/src/components/DocNotifyContextCard.svelte +++ b/plugins/notification-resources/src/components/DocNotifyContextCard.svelte @@ -198,7 +198,7 @@
{ - dispatch('click', { context: value }) + dispatch('click', { context: value, object }) }} > {#if isLoading} @@ -266,7 +266,7 @@ on:click={(e) => { e.preventDefault() e.stopPropagation() - dispatch('click', { context: value, notification: group[0] }) + dispatch('click', { context: value, notification: group[0], object }) }} />
diff --git a/plugins/notification-resources/src/components/inbox/Inbox.svelte b/plugins/notification-resources/src/components/inbox/Inbox.svelte index 079dce0cc1..5365b49ea1 100644 --- a/plugins/notification-resources/src/components/inbox/Inbox.svelte +++ b/plugins/notification-resources/src/components/inbox/Inbox.svelte @@ -256,7 +256,7 @@ 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 { @@ -373,6 +373,7 @@ } ] $: $deviceInfo.replacedPanel = replacedPanel + onDestroy(() => { $deviceInfo.replacedPanel = undefined unsubscribeLoc() diff --git a/plugins/notification-resources/src/utils.ts b/plugins/notification-resources/src/utils.ts index 1c7795dd7f..b3710c8675 100644 --- a/plugins/notification-resources/src/utils.ts +++ b/plugins/notification-resources/src/utils.ts @@ -583,7 +583,8 @@ export function resetInboxContext (): void { export async function selectInboxContext ( linkProviders: LinkIdProvider[], context: DocNotifyContext, - notification?: WithLookup + notification?: WithLookup, + object?: Doc ): Promise { const client = getClient() const hierarchy = client.getHierarchy() @@ -607,24 +608,42 @@ export async function selectInboxContext ( const message = (notification as WithLookup)?.$lookup?.attachedTo if (objectClass === chunter.class.ThreadMessage) { - const thread = await client.findOne( - chunter.class.ThreadMessage, - { - _id: objectId as Ref - }, - { projection: { _id: 1, attachedTo: 1 } } - ) + const thread = + object?._id === objectId + ? (object as ThreadMessage) + : await client.findOne( + chunter.class.ThreadMessage, + { + _id: objectId as Ref + }, + { 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 } if (isReactionMessage(message)) { const thread = loc.path[4] === objectId ? objectId : undefined + const reactedTo = + (object as ActivityMessage) ?? + (await client.findOne(activity.class.ActivityMessage, { _id: message.attachedTo as Ref })) + 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( linkProviders, - objectId, - objectClass, + channelId, + channelClass, thread as Ref, objectId as Ref ) @@ -633,11 +652,13 @@ export async function selectInboxContext ( const selectedMsg = (notification as ActivityInboxNotification)?.attachedTo 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( linkProviders, - objectId, - objectClass, + channelId, + channelClass, thread as Ref, selectedMsg ?? (objectId as Ref) ) diff --git a/plugins/tracker-resources/src/components/issues/IssuesView.svelte b/plugins/tracker-resources/src/components/issues/IssuesView.svelte index a631ef50e0..d92449af9d 100644 --- a/plugins/tracker-resources/src/components/issues/IssuesView.svelte +++ b/plugins/tracker-resources/src/components/issues/IssuesView.svelte @@ -28,7 +28,7 @@ $: if (query) updateSearchQuery(search) let resultQuery: DocumentQuery = { ...searchQuery } - $: if (!label && title) { + $: if (title) { void translate(title, {}, $themeStore.language).then((res) => { label = res }) diff --git a/plugins/workbench-resources/src/components/sidebar/SidebarExpanded.svelte b/plugins/workbench-resources/src/components/sidebar/SidebarExpanded.svelte index 7209b04357..880d765e1d 100644 --- a/plugins/workbench-resources/src/components/sidebar/SidebarExpanded.svelte +++ b/plugins/workbench-resources/src/components/sidebar/SidebarExpanded.svelte @@ -24,7 +24,7 @@ Breadcrumbs, getCurrentLocation } from '@hcengineering/ui' - import { onDestroy } from 'svelte' + import { onDestroy, onMount } from 'svelte' import { closeWidgetTab, sidebarStore, SidebarVariant, WidgetState, openWidgetTab, closeWidget } from '../../sidebar' import WidgetsBar from './widgets/WidgetsBar.svelte' @@ -46,36 +46,15 @@ $: widgetState = widget !== undefined ? $sidebarStore.widgetsState.get(widget._id) : undefined $: tabId = widgetState?.tab - $: tabs = getTabs(widget, widgetState) + $: tabs = widgetState?.tabs ?? [] $: tab = tabId !== undefined ? tabs.find((it) => it.id === tabId) ?? tabs[0] : tabs[0] $: if ($sidebarStore.widget === undefined) { sidebarStore.update((s) => ({ ...s, variant: SidebarVariant.MINI })) } - function getTabs (widget?: Widget, state?: WidgetState): WidgetTab[] { - 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) => { + function closeWrongTabs (loc: Location): void { if (widget === undefined) return - for (const tab of tabs) { if (tab.allowedPath !== undefined && !tab.isPinned) { const path = loc.path.join('/') @@ -84,6 +63,14 @@ } } } + } + + const unsubscribe = locationStore.subscribe((loc: Location) => { + closeWrongTabs(loc) + }) + + onMount(() => { + closeWrongTabs(getCurrentLocation()) }) onDestroy(() => { diff --git a/plugins/workbench-resources/src/sidebar.ts b/plugins/workbench-resources/src/sidebar.ts index 8bf9a40e1b..ee1ff76cdd 100644 --- a/plugins/workbench-resources/src/sidebar.ts +++ b/plugins/workbench-resources/src/sidebar.ts @@ -203,7 +203,6 @@ export function openWidgetTab (widget: Ref, tab: string): void { } export function createWidgetTab (widget: Widget, tab: WidgetTab, newTab = false): void { - openWidget(widget) const state = get(sidebarStore) const { widgetsState } = state const widgetState = widgetsState.get(widget._id) @@ -225,6 +224,7 @@ export function createWidgetTab (widget: Widget, tab: WidgetTab, newTab = false) } widgetsState.set(widget._id, { + ...widgetState, _id: widget._id, tabs: newTabs, tab: tab.id @@ -232,7 +232,9 @@ export function createWidgetTab (widget: Widget, tab: WidgetTab, newTab = false) sidebarStore.set({ ...state, - widgetsState + widget: widget._id, + widgetsState, + variant: SidebarVariant.EXPANDED }) } From 56280dc3a4e9610bc373ce0ac2b860e576ea3d63 Mon Sep 17 00:00:00 2001 From: Alexander Onnikov Date: Mon, 23 Sep 2024 21:24:16 +0700 Subject: [PATCH 02/10] UBERF-8233 Hide editor menu while user selecting (#6690) --- .../src/components/TextEditorToolbar.svelte | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/plugins/text-editor-resources/src/components/TextEditorToolbar.svelte b/plugins/text-editor-resources/src/components/TextEditorToolbar.svelte index 4e42f52d6f..f1b6a156de 100644 --- a/plugins/text-editor-resources/src/components/TextEditorToolbar.svelte +++ b/plugins/text-editor-resources/src/components/TextEditorToolbar.svelte @@ -23,6 +23,7 @@ } from '@hcengineering/text-editor' import { createQuery } from '@hcengineering/presentation' import { getResource } from '@hcengineering/platform' + import { onDestroy, onMount } from 'svelte' import { inlineToolbarKey } from './extension/inlineToolbar' import TextActionButton from './TextActionButton.svelte' @@ -93,11 +94,40 @@ $: categories.forEach((category) => { category.sort((a, b) => a[0] - b[0]) }) + + let selecting = false + + function handleMouseDown (): void { + function handleMouseMove (): void { + if (!editor.state.selection.empty) { + selecting = true + document.removeEventListener('mousemove', handleMouseMove) + } + } + + function handleMouseUp (): void { + selecting = false + + document.removeEventListener('mousemove', handleMouseMove) + document.removeEventListener('mouseup', handleMouseUp) + } + + document.addEventListener('mousemove', handleMouseMove) + document.addEventListener('mouseup', handleMouseUp) + } + + onMount(() => { + document.addEventListener('mousedown', handleMouseDown) + }) + + onDestroy(() => { + document.removeEventListener('mousedown', handleMouseDown) + }) -
- {#if editor && visible && visibleActions.length > 0} -
+