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}