From f2c961c5d5d00a7ca923dbfe9d6abcb0ecb195c9 Mon Sep 17 00:00:00 2001 From: Kristina Date: Fri, 20 Sep 2024 19:07:04 +0400 Subject: [PATCH] [Part 2]: Sidebar and chat fixes (#6656) Signed-off-by: Kristina Fefelova --- models/activity/src/index.ts | 3 + models/chunter/src/types.ts | 5 +- packages/theme/styles/components.scss | 1 + packages/ui/src/components/Header.svelte | 11 ++- packages/ui/src/components/ModernTab.svelte | 1 + packages/ui/src/types.ts | 1 + .../ActivityMessageTemplate.svelte | 4 ++ plugins/activity/src/index.ts | 2 + .../components/CalendarWidgetHeader.svelte | 1 + .../src/components/Channel.svelte | 2 + .../src/components/ChannelHeader.svelte | 2 + .../src/components/ChannelScrollView.svelte | 70 ++++++++++++------- .../src/components/ChannelSidebarView.svelte | 12 +++- .../src/components/ChannelView.svelte | 2 +- .../src/components/ChatWidget.svelte | 11 +-- .../src/components/ChatWidgetTab.svelte | 2 +- .../src/components/Header.svelte | 2 + .../src/components/JumpToDateSelector.svelte | 12 ++-- .../chat-message/ChatMessageHeader.svelte | 5 -- .../chat-message/ChatMessagePresenter.svelte | 2 +- .../chat/create/CreateDirectChat.svelte | 2 +- .../threads/ThreadSidebarView.svelte | 2 +- .../src/components/threads/ThreadView.svelte | 30 ++++++-- plugins/chunter-resources/src/index.ts | 4 +- plugins/chunter-resources/src/navigation.ts | 45 +++++++----- plugins/chunter-resources/src/utils.ts | 13 ++-- plugins/chunter/src/index.ts | 4 +- .../src/components/inbox/Inbox.svelte | 7 ++ plugins/notification-resources/src/utils.ts | 13 +++- .../components/sidebar/SidebarExpanded.svelte | 2 + plugins/workbench-resources/src/sidebar.ts | 7 +- 31 files changed, 185 insertions(+), 95 deletions(-) diff --git a/models/activity/src/index.ts b/models/activity/src/index.ts index 14d804a652..c14f33b646 100644 --- a/models/activity/src/index.ts +++ b/models/activity/src/index.ts @@ -152,6 +152,9 @@ export class TActivityReference extends TActivityMessage implements ActivityRefe @Prop(TypeMarkup(), activity.string.Message) @Index(IndexKind.FullText) message!: string + + @Prop(TypeTimestamp(), activity.string.Edit) + editedOn?: Timestamp } @Model(activity.class.ActivityInfoMessage, activity.class.ActivityMessage) diff --git a/models/chunter/src/types.ts b/models/chunter/src/types.ts index c24f2e086e..bfe87f2bf9 100644 --- a/models/chunter/src/types.ts +++ b/models/chunter/src/types.ts @@ -22,7 +22,6 @@ import { TypeMarkup, TypeRef, TypeString, - TypeTimestamp, UX } from '@hcengineering/model' import core, { TAttachedDoc, TClass, TDoc, TSpace } from '@hcengineering/model-core' @@ -59,6 +58,7 @@ import type { DocNotifyContext } from '@hcengineering/notification' import chunter from './plugin' export const DOMAIN_CHUNTER = 'chunter' as Domain + @Model(chunter.class.ChunterSpace, core.class.Space) export class TChunterSpace extends TSpace implements ChunterSpace { @Prop(PropCollection(activity.class.ActivityMessage), chunter.string.Messages) @@ -84,9 +84,6 @@ export class TChatMessage extends TActivityMessage implements ChatMessage { @Index(IndexKind.FullText) message!: string - @Prop(TypeTimestamp(), chunter.string.Edit) - editedOn?: Timestamp - @Prop(PropCollection(attachment.class.Attachment), attachment.string.Attachments, { shortLabel: attachment.string.Files }) diff --git a/packages/theme/styles/components.scss b/packages/theme/styles/components.scss index 72607215e4..162151088a 100644 --- a/packages/theme/styles/components.scss +++ b/packages/theme/styles/components.scss @@ -321,6 +321,7 @@ width: 100%; min-width: 0; min-height: var(--spacing-6_5); + overflow: hidden; &.clearPadding > .hulyHeader-row { padding: 0; diff --git a/packages/ui/src/components/Header.svelte b/packages/ui/src/components/Header.svelte index 250b517774..edf9ae97d5 100644 --- a/packages/ui/src/components/Header.svelte +++ b/packages/ui/src/components/Header.svelte @@ -39,6 +39,7 @@ export let noPrint: boolean = false export let freezeBefore: boolean = false export let doubleRowWidth = 768 + export let closeOnEscape: boolean = true const dispatch = createEventDispatcher() @@ -61,7 +62,7 @@ }) function _close (ev: KeyboardEvent): void { - if (closeButton && ev.key === 'Escape') { + if (closeButton && ev.key === 'Escape' && closeOnEscape) { ev.preventDefault() ev.stopPropagation() @@ -138,7 +139,9 @@ {/if} {#if closeButton} {#if type !== 'type-popup'}
{/if} -
Esc
+ {#if closeOnEscape} +
Esc
+ {/if} dispatch('close')} /> {/if}
@@ -233,7 +236,9 @@ {/if} {#if closeButton} {#if type !== 'type-popup'}
{/if} -
Esc
+ {#if closeOnEscape} +
Esc
+ {/if} dispatch('close')} /> {/if} {/if} diff --git a/packages/ui/src/components/ModernTab.svelte b/packages/ui/src/components/ModernTab.svelte index 2be4c7f9cb..90b552fbf1 100644 --- a/packages/ui/src/components/ModernTab.svelte +++ b/packages/ui/src/components/ModernTab.svelte @@ -85,6 +85,7 @@ border-radius: 0.25rem; cursor: pointer; overflow: hidden; + color: var(--theme-content-color); &.primary { background-color: var(--theme-button-pressed); diff --git a/packages/ui/src/types.ts b/packages/ui/src/types.ts index 555e14935f..178a4ff5ac 100644 --- a/packages/ui/src/types.ts +++ b/packages/ui/src/types.ts @@ -126,6 +126,7 @@ export interface TabItem { } export interface BreadcrumbItem { + id?: string icon?: Asset | AnySvelteComponent | ComponentType iconProps?: any iconWidth?: string diff --git a/plugins/activity-resources/src/components/activity-message/ActivityMessageTemplate.svelte b/plugins/activity-resources/src/components/activity-message/ActivityMessageTemplate.svelte index 2b84bf79ac..9578c9f193 100644 --- a/plugins/activity-resources/src/components/activity-message/ActivityMessageTemplate.svelte +++ b/plugins/activity-resources/src/components/activity-message/ActivityMessageTemplate.svelte @@ -26,6 +26,7 @@ import { getActions, restrictionStore, showMenu } from '@hcengineering/view-resources' import { Asset } from '@hcengineering/platform' import { Action as ViewAction } from '@hcengineering/view' + import notification from '@hcengineering/notification' import ReactionsPresenter from '../reactions/ReactionsPresenter.svelte' import ActivityMessagePresenter from './ActivityMessagePresenter.svelte' @@ -228,6 +229,9 @@ + {#if message.editedOn} + ( + {/if} {#if withActions && inlineActions.length > 0 && !readonly}
diff --git a/plugins/activity/src/index.ts b/plugins/activity/src/index.ts index bc087b7bb3..b0b18aa027 100644 --- a/plugins/activity/src/index.ts +++ b/plugins/activity/src/index.ts @@ -46,6 +46,7 @@ export interface ActivityMessage extends AttachedDoc { replies?: number reactions?: number + editedOn?: Timestamp } export type DisplayActivityMessage = DisplayDocUpdateMessage | ActivityMessage @@ -81,6 +82,7 @@ export interface ActivityInfoMessage extends ActivityMessage { props?: Record icon?: Asset iconProps?: Record + editedOn?: Timestamp // A possible set of links to some platform resources. links?: { _class: Ref>, _id: Ref }[] diff --git a/plugins/calendar-resources/src/components/CalendarWidgetHeader.svelte b/plugins/calendar-resources/src/components/CalendarWidgetHeader.svelte index a00fbb52d4..da02fe2841 100644 --- a/plugins/calendar-resources/src/components/CalendarWidgetHeader.svelte +++ b/plugins/calendar-resources/src/components/CalendarWidgetHeader.svelte @@ -42,6 +42,7 @@ hideExtra={false} adaptive="autoExtra" doubleRowWidth={350} + closeOnEscape={false} on:close >
diff --git a/plugins/chunter-resources/src/components/Channel.svelte b/plugins/chunter-resources/src/components/Channel.svelte index cf9f74ac77..eb43c295af 100644 --- a/plugins/chunter-resources/src/components/Channel.svelte +++ b/plugins/chunter-resources/src/components/Channel.svelte @@ -30,6 +30,7 @@ export let filters: Ref[] = [] export let isAsideOpened = false export let syncLocation = true + export let freeze = false const client = getClient() const hierarchy = client.getHierarchy() @@ -111,5 +112,6 @@ provider={dataProvider} {isAsideOpened} loadMoreAllowed={!isDocChannel} + {freeze} /> {/if} diff --git a/plugins/chunter-resources/src/components/ChannelHeader.svelte b/plugins/chunter-resources/src/components/ChannelHeader.svelte index 37fd340167..284153a4eb 100644 --- a/plugins/chunter-resources/src/components/ChannelHeader.svelte +++ b/plugins/chunter-resources/src/components/ChannelHeader.svelte @@ -36,6 +36,7 @@ export let isAsideShown: boolean = false export let filters: Ref[] = [] export let canOpenInSidebar: boolean = false + export let closeOnEscape: boolean = true const client = getClient() const hierarchy = client.getHierarchy() @@ -80,6 +81,7 @@ {isAsideShown} {withSearch} {canOpenInSidebar} + {closeOnEscape} on:aside-toggled on:close > diff --git a/plugins/chunter-resources/src/components/ChannelScrollView.svelte b/plugins/chunter-resources/src/components/ChannelScrollView.svelte index c41d057f07..5dffbc7151 100644 --- a/plugins/chunter-resources/src/components/ChannelScrollView.svelte +++ b/plugins/chunter-resources/src/components/ChannelScrollView.svelte @@ -61,8 +61,9 @@ export let skipLabels = false export let loadMoreAllowed = true export let isAsideOpened = false - export let initialScrollBottom = true export let fullHeight = true + export let fixedInput = true + export let freeze = false const doc = object @@ -130,17 +131,21 @@ } }) + function isFreeze (): boolean { + return freeze + } + $: displayMessages = filterChatMessages(messages, filters, filterResources, doc._class, selectedFilters) const unsubscribe = inboxClient.inboxNotificationsByContext.subscribe(() => { - if (notifyContext !== undefined) { + if (notifyContext !== undefined && !isFreeze()) { recheckNotifications(notifyContext) readViewportMessages() } }) function scrollToBottom (afterScrollFn?: () => void): void { - if (scroller != null && scrollElement != null) { + if (scroller != null && scrollElement != null && !isFreeze()) { scroller.scrollBy(scrollElement.scrollHeight) updateSelectedDate() afterScrollFn?.() @@ -338,7 +343,7 @@ let messagesToReadAccumulatorTimer: any function readViewportMessages (): void { - if (!scrollElement || !scrollContentBox) { + if (!scrollElement || !scrollContentBox || isFreeze()) { return } @@ -452,22 +457,14 @@ isInitialScrolling = false } else if (separatorIndex === -1) { await wait() - if (initialScrollBottom) { - isScrollInitialized = true - shouldWaitAndRead = true - autoscroll = true - shouldScrollToNew = true - isInitialScrolling = false - waitLastMessageRenderAndRead(() => { - autoscroll = false - }) - } else { - isScrollInitialized = true + isScrollInitialized = true + shouldWaitAndRead = true + autoscroll = true + shouldScrollToNew = true + isInitialScrolling = false + waitLastMessageRenderAndRead(() => { autoscroll = false - updateShouldScrollToNew() - isInitialScrolling = false - readViewportMessages() - } + }) } else if (separatorElement) { await wait() scrollToSeparator() @@ -519,6 +516,7 @@ function scrollToNewMessages (): void { if (!scrollElement || !shouldScrollToNew) { + readViewportMessages() return } @@ -557,14 +555,22 @@ return } + if (isFreeze()) { + messagesCount = newCount + return + } + if (scrollToRestore > 0) { void restoreScroll() } else if (dateToJump !== undefined) { await wait() scrollToDate(dateToJump) - } else if (messagesCount > 0 && newCount > messagesCount) { + } else if (shouldScrollToNew && messagesCount > 0 && newCount > messagesCount) { await wait() scrollToNewMessages() + } else { + await wait() + readViewportMessages() } messagesCount = newCount @@ -576,7 +582,7 @@ return } - if (shouldScrollToNew && initialScrollBottom) { + if (shouldScrollToNew) { scrollToBottom() } @@ -660,7 +666,7 @@ } else if (element != null) { const { scrollHeight, scrollTop, offsetHeight } = element - showScrollDownButton = scrollHeight > offsetHeight + scrollTop + 300 + showScrollDownButton = scrollHeight > offsetHeight + scrollTop + 50 } else { showScrollDownButton = false } @@ -691,7 +697,7 @@ $: void forceReadContext(isScrollAtBottom, notifyContext) async function forceReadContext (isScrollAtBottom: boolean, context?: DocNotifyContext): Promise { - if (context === undefined || !isScrollAtBottom || forceRead) return + if (context === undefined || !isScrollAtBottom || forceRead || isFreeze()) return const { lastUpdateTimestamp = 0, lastViewedTimestamp = 0 } = context if (lastViewedTimestamp >= lastUpdateTimestamp) return @@ -708,6 +714,10 @@ } const canLoadNextForwardStore = provider.canLoadNextForwardStore + + $: if (!freeze) { + readViewportMessages() + } {#if isLoading} @@ -777,6 +787,16 @@ /> {/each} + {#if !fixedInput} +
+ +
+ {/if} + {#if loadMoreAllowed && $canLoadNextForwardStore} {/if} @@ -794,7 +814,7 @@
{/if}
- {#if object} + {#if fixedInput && object}
-{#if object} +{#if object && renderChannel}
{#key object._id} - + {/key}
{/if} {#if threadId}
- closeThreadInSidebarChannel(widget, tab)} /> + closeThreadInSidebarChannel(widget, tab)} on:close />
{/if} diff --git a/plugins/chunter-resources/src/components/ChannelView.svelte b/plugins/chunter-resources/src/components/ChannelView.svelte index ef849cd3fc..d0e9c5888f 100644 --- a/plugins/chunter-resources/src/components/ChannelView.svelte +++ b/plugins/chunter-resources/src/components/ChannelView.svelte @@ -93,7 +93,7 @@ } -
+
-{#if widget && tab && tab.type === 'channel'} +{#if widget && tab} -{:else if widget && tab && tab.type === 'thread'} - { - handleClose(tab?.id) - }} - /> {/if} diff --git a/plugins/chunter-resources/src/components/ChatWidgetTab.svelte b/plugins/chunter-resources/src/components/ChatWidgetTab.svelte index ffc126d5e6..5bfc57a6db 100644 --- a/plugins/chunter-resources/src/components/ChatWidgetTab.svelte +++ b/plugins/chunter-resources/src/components/ChatWidgetTab.svelte @@ -50,7 +50,7 @@ let count: number = 0 - $: objectId = tab.type === 'thread' ? tab.data.thread : tab.data._id + $: objectId = tab.data.thread ?? tab.data._id $: context = objectId ? $contextByDocStore.get(objectId) : undefined const unsubscribe = notificationClient.inboxNotificationsByContext.subscribe((res) => { diff --git a/plugins/chunter-resources/src/components/Header.svelte b/plugins/chunter-resources/src/components/Header.svelte index 89a1a3b412..6920564630 100644 --- a/plugins/chunter-resources/src/components/Header.svelte +++ b/plugins/chunter-resources/src/components/Header.svelte @@ -57,6 +57,7 @@ export let adaptive: HeaderAdaptive = 'default' export let hideActions: boolean = false export let canOpenInSidebar: boolean = false + export let closeOnEscape: boolean = true const client = getClient() const dispatch = createEventDispatcher() @@ -72,6 +73,7 @@ hideActions={!((canOpen && object) || withAside || $$slots.actions) || hideActions} hideDescription={!description} adaptive={adaptive !== 'default' ? adaptive : withFilters ? 'freezeActions' : 'disabled'} + {closeOnEscape} on:click on:close > diff --git a/plugins/chunter-resources/src/components/JumpToDateSelector.svelte b/plugins/chunter-resources/src/components/JumpToDateSelector.svelte index 4d7e760922..7630810893 100644 --- a/plugins/chunter-resources/src/components/JumpToDateSelector.svelte +++ b/plugins/chunter-resources/src/components/JumpToDateSelector.svelte @@ -33,7 +33,7 @@
{ showPopup(DateRangePopup, {}, div, (v) => { if (v) { @@ -68,13 +68,17 @@ left: 0; width: 100%; height: 1px; - background-color: var(--theme-divider-color); + background-color: var(--highlight-select-border); } + .dateSelectorButton { + cursor: pointer; padding: 0.25rem 0.5rem; height: max-content; - background-color: var(--theme-list-row-color); - border: 1px solid var(--theme-divider-color); + color: var(--theme-content-color); + background-color: var(--highlight-select); + border: 1px solid var(--highlight-select-border); + font-weight: 500; z-index: 10; } } diff --git a/plugins/chunter-resources/src/components/chat-message/ChatMessageHeader.svelte b/plugins/chunter-resources/src/components/chat-message/ChatMessageHeader.svelte index 2c649a9a3a..4c82e87122 100644 --- a/plugins/chunter-resources/src/components/chat-message/ChatMessageHeader.svelte +++ b/plugins/chunter-resources/src/components/chat-message/ChatMessageHeader.svelte @@ -14,20 +14,15 @@ --> {#if label} {/if} -{#if editedOn} - -{/if} diff --git a/plugins/workbench-resources/src/sidebar.ts b/plugins/workbench-resources/src/sidebar.ts index 50a4f6ad8f..8bf9a40e1b 100644 --- a/plugins/workbench-resources/src/sidebar.ts +++ b/plugins/workbench-resources/src/sidebar.ts @@ -101,7 +101,12 @@ export function openWidget (widget: Widget, data?: Record, active = const { widgetsState } = state const widgetState = widgetsState.get(widget._id) - widgetsState.set(widget._id, { _id: widget._id, data, tab: widgetState?.tab, tabs: widgetState?.tabs ?? [] }) + widgetsState.set(widget._id, { + _id: widget._id, + data: data ?? widgetState?.data, + tab: widgetState?.tab, + tabs: widgetState?.tabs ?? [] + }) sidebarStore.set({ ...state,