mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-22 03:14:40 +03:00
Scroll to activity message on inbox item click (#5747)
Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
parent
cae6113add
commit
6b74823cbb
@ -14,13 +14,14 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { afterUpdate, createEventDispatcher } from 'svelte'
|
||||
import { afterUpdate, createEventDispatcher, SvelteComponent } from 'svelte'
|
||||
import { Writable, writable } from 'svelte/store'
|
||||
|
||||
import activity from '@hcengineering/activity'
|
||||
import { Doc } from '@hcengineering/core'
|
||||
import { Component, deviceOptionsStore as deviceInfo, Panel, Scroller } from '@hcengineering/ui'
|
||||
import { Component, deviceOptionsStore as deviceInfo, Panel, Scroller, resizeObserver } from '@hcengineering/ui'
|
||||
import type { ButtonItem } from '@hcengineering/ui'
|
||||
import { getResource } from '@hcengineering/platform'
|
||||
|
||||
export let title: string | undefined = undefined
|
||||
export let withoutActivity: boolean = false
|
||||
@ -63,6 +64,8 @@
|
||||
let count: number = 0
|
||||
let panel: Panel
|
||||
|
||||
let activityRef: SvelteComponent | undefined
|
||||
|
||||
const waitCount = 10
|
||||
const PanelScrollTop: Writable<Record<string, number>> = writable<Record<string, number>>({})
|
||||
|
||||
@ -88,7 +91,13 @@
|
||||
}, 50)
|
||||
}
|
||||
|
||||
afterUpdate(() => {
|
||||
afterUpdate(async () => {
|
||||
const fn = await getResource(activity.function.ShouldScrollToActivity)
|
||||
|
||||
if (!withoutActivity && fn?.()) {
|
||||
return
|
||||
}
|
||||
|
||||
if (lastHref !== window.location.href) {
|
||||
startScrollHeightCheck()
|
||||
}
|
||||
@ -238,12 +247,19 @@
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div class={contentClasses ?? 'popupPanel-body__main-content py-8 clear-mins'} class:max={useMaxWidth}>
|
||||
<div
|
||||
class={contentClasses ?? 'popupPanel-body__main-content py-8'}
|
||||
class:max={useMaxWidth}
|
||||
use:resizeObserver={(element) => {
|
||||
activityRef?.onContainerResized?.(element)
|
||||
}}
|
||||
>
|
||||
<slot />
|
||||
{#if !withoutActivity}
|
||||
{#key object._id}
|
||||
<Component
|
||||
is={activity.component.Activity}
|
||||
bind:innerRef={activityRef}
|
||||
props={{
|
||||
object,
|
||||
showCommenInput: !withoutInput,
|
||||
|
@ -1,9 +1,10 @@
|
||||
import activity, { type SavedMessage } from '@hcengineering/activity'
|
||||
import { SortingOrder, type WithLookup } from '@hcengineering/core'
|
||||
import activity, { type ActivityMessage, type SavedMessage } from '@hcengineering/activity'
|
||||
import { type Ref, SortingOrder, type WithLookup } from '@hcengineering/core'
|
||||
import { writable } from 'svelte/store'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
|
||||
export const savedMessagesStore = writable<Array<WithLookup<SavedMessage>>>([])
|
||||
export const messageInFocus = writable<Ref<ActivityMessage> | undefined>(undefined)
|
||||
|
||||
const savedMessagesQuery = createQuery(true)
|
||||
|
||||
|
@ -16,12 +16,15 @@
|
||||
import activity, { ActivityExtension, ActivityMessage, DisplayActivityMessage } from '@hcengineering/activity'
|
||||
import { Doc, Ref, SortingOrder } from '@hcengineering/core'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { Component, Grid, Label, Lazy, Spinner } from '@hcengineering/ui'
|
||||
import { Grid, Label, Spinner, location, Lazy } from '@hcengineering/ui'
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
|
||||
import ActivityExtensionComponent from './ActivityExtension.svelte'
|
||||
import ActivityFilter from './ActivityFilter.svelte'
|
||||
import { combineActivityMessages } from '../activityMessagesUtils'
|
||||
import { canGroupMessages } from '../utils'
|
||||
import { canGroupMessages, getMessageFromLoc } from '../utils'
|
||||
import ActivityMessagePresenter from './activity-message/ActivityMessagePresenter.svelte'
|
||||
import { messageInFocus } from '../activity'
|
||||
|
||||
export let object: Doc
|
||||
export let showCommenInput: boolean = true
|
||||
@ -38,6 +41,122 @@
|
||||
let activityMessages: ActivityMessage[] = []
|
||||
let isLoading = false
|
||||
|
||||
let activityBox: HTMLElement | undefined
|
||||
let selectedMessageId: Ref<ActivityMessage> | undefined = undefined
|
||||
|
||||
let shouldScroll = true
|
||||
let isAutoScroll = false
|
||||
let prevScrollTimestamp = 0
|
||||
let timer: any
|
||||
|
||||
let prevContainerHeight = -1
|
||||
let prevContainerWidth = -1
|
||||
|
||||
const unsubscribe = messageInFocus.subscribe((id) => {
|
||||
if (id !== undefined) {
|
||||
selectedMessageId = id
|
||||
shouldScroll = true
|
||||
void scrollToMessage(id)
|
||||
messageInFocus.set(undefined)
|
||||
}
|
||||
})
|
||||
|
||||
const unsubscribeLocation = location.subscribe((loc) => {
|
||||
const id = getMessageFromLoc(loc)
|
||||
|
||||
if (id === undefined) {
|
||||
boundary?.scrollTo({ top: 0 })
|
||||
selectedMessageId = undefined
|
||||
}
|
||||
|
||||
messageInFocus.set(id)
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
if (!boundary) {
|
||||
return
|
||||
}
|
||||
|
||||
boundary.addEventListener('wheel', () => {
|
||||
shouldScroll = false
|
||||
})
|
||||
|
||||
boundary.addEventListener('scroll', (a) => {
|
||||
const diff = a.timeStamp - prevScrollTimestamp
|
||||
|
||||
if (!isAutoScroll) {
|
||||
shouldScroll = false
|
||||
}
|
||||
|
||||
isAutoScroll = isAutoScroll ? diff < 100 || prevScrollTimestamp === 0 : false
|
||||
prevScrollTimestamp = a.timeStamp
|
||||
})
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
unsubscribe()
|
||||
unsubscribeLocation()
|
||||
})
|
||||
|
||||
function restartAnimation (el: HTMLElement): void {
|
||||
el.style.animation = 'none'
|
||||
el.focus()
|
||||
el.style.animation = ''
|
||||
}
|
||||
|
||||
function tryScrollToMessage (delay: number = 100): void {
|
||||
if (timer) {
|
||||
clearTimeout(timer)
|
||||
}
|
||||
timer = setTimeout(() => {
|
||||
void scrollToMessage(selectedMessageId)
|
||||
}, delay)
|
||||
}
|
||||
|
||||
async function scrollToMessage (id?: Ref<ActivityMessage>): Promise<void> {
|
||||
if (!id || boundary == null || activityBox == null) {
|
||||
return
|
||||
}
|
||||
|
||||
const messagesElements = activityBox.getElementsByClassName('activityMessage')
|
||||
const msgElement = messagesElements[id as any] as HTMLElement | undefined
|
||||
|
||||
if (msgElement == null && filteredMessages.some((msg) => msg._id === id)) {
|
||||
tryScrollToMessage()
|
||||
return
|
||||
} else if (msgElement == null) {
|
||||
return
|
||||
}
|
||||
|
||||
shouldScroll = true
|
||||
isAutoScroll = true
|
||||
prevScrollTimestamp = 0
|
||||
|
||||
restartAnimation(msgElement)
|
||||
msgElement.scrollIntoView({ behavior: 'instant' })
|
||||
}
|
||||
|
||||
export function onContainerResized (container: HTMLElement): void {
|
||||
if (!shouldScroll) return
|
||||
|
||||
if (prevContainerWidth > 0 && container.clientWidth !== prevContainerWidth) {
|
||||
shouldScroll = false
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
selectedMessageId &&
|
||||
container.clientHeight !== prevContainerHeight &&
|
||||
container.clientHeight > prevContainerHeight
|
||||
) {
|
||||
// A little delay to avoid a lot of jumping/twitching
|
||||
tryScrollToMessage(300)
|
||||
}
|
||||
|
||||
prevContainerHeight = container.clientHeight
|
||||
prevContainerWidth = container.clientWidth
|
||||
}
|
||||
|
||||
let isNewestFirst = JSON.parse(localStorage.getItem('activity-newest-first') ?? 'false')
|
||||
|
||||
$: void client.findAll(activity.class.ActivityExtension, { ofClass: object._class }).then((res) => {
|
||||
@ -67,6 +186,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: areMessagesLoaded = !isLoading && filteredMessages.length > 0
|
||||
|
||||
$: if (activityBox && areMessagesLoaded) {
|
||||
shouldScroll = true
|
||||
void scrollToMessage(selectedMessageId)
|
||||
}
|
||||
|
||||
$: void updateActivityMessages(object._id, isNewestFirst ? SortingOrder.Descending : SortingOrder.Ascending)
|
||||
</script>
|
||||
|
||||
@ -93,23 +219,35 @@
|
||||
<ActivityExtensionComponent kind="input" {extensions} props={{ object, boundary, focusIndex }} />
|
||||
</div>
|
||||
{/if}
|
||||
<div class="p-activity select-text" id={activity.string.Activity} class:newest-first={isNewestFirst}>
|
||||
<div
|
||||
class="p-activity select-text"
|
||||
id={activity.string.Activity}
|
||||
class:newest-first={isNewestFirst}
|
||||
bind:this={activityBox}
|
||||
>
|
||||
{#if filteredMessages.length}
|
||||
<Grid column={1} rowGap={0}>
|
||||
{#each filteredMessages as message, index}
|
||||
{@const canGroup = canGroupMessages(message, filteredMessages[index - 1])}
|
||||
<Lazy>
|
||||
<Component
|
||||
is={activity.component.ActivityMessagePresenter}
|
||||
props={{
|
||||
value: message,
|
||||
hideLink: true,
|
||||
space: object.space,
|
||||
boundary,
|
||||
type: canGroup ? 'short' : 'default'
|
||||
}}
|
||||
{#if selectedMessageId}
|
||||
<ActivityMessagePresenter
|
||||
value={message}
|
||||
doc={object}
|
||||
hideLink={true}
|
||||
type={canGroup ? 'short' : 'default'}
|
||||
isHighlighted={selectedMessageId === message._id}
|
||||
/>
|
||||
</Lazy>
|
||||
{:else}
|
||||
<Lazy>
|
||||
<ActivityMessagePresenter
|
||||
value={message}
|
||||
doc={object}
|
||||
hideLink={true}
|
||||
type={canGroup ? 'short' : 'default'}
|
||||
isHighlighted={selectedMessageId === message._id}
|
||||
/>
|
||||
</Lazy>
|
||||
{/if}
|
||||
{/each}
|
||||
</Grid>
|
||||
{/if}
|
||||
@ -148,6 +286,4 @@
|
||||
:global(.grid .msgactivity-container.showIcon:last-child::after) {
|
||||
content: none;
|
||||
}
|
||||
|
||||
// Remove the line in the last Activity message
|
||||
</style>
|
||||
|
@ -20,6 +20,7 @@
|
||||
import { Class, Doc, Ref } from '@hcengineering/core'
|
||||
|
||||
export let value: DisplayActivityMessage
|
||||
export let doc: Doc | undefined = undefined
|
||||
export let showNotify: boolean = false
|
||||
export let isHighlighted: boolean = false
|
||||
export let isSelected: boolean = false
|
||||
@ -53,6 +54,7 @@
|
||||
props={{
|
||||
space: value.space,
|
||||
value,
|
||||
doc,
|
||||
showNotify,
|
||||
skipLabel,
|
||||
isHighlighted,
|
||||
|
@ -212,7 +212,7 @@
|
||||
<style lang="scss">
|
||||
@keyframes highlight {
|
||||
50% {
|
||||
background-color: var(--global-ui-highlight-BackgroundColor);
|
||||
background-color: var(--global-ui-hover-highlight-BackgroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
import { getIsTextType } from '../../utils'
|
||||
|
||||
export let value: DisplayDocUpdateMessage
|
||||
export let doc: Doc | undefined = undefined
|
||||
export let showNotify: boolean = false
|
||||
export let isHighlighted: boolean = false
|
||||
export let isSelected: boolean = false
|
||||
@ -117,10 +118,16 @@
|
||||
return personById.get(personAccount.person)
|
||||
}
|
||||
|
||||
$: void loadObject(value.objectId, value.objectClass)
|
||||
$: void loadParentObject(value, parentMessage)
|
||||
$: void loadObject(value.objectId, value.objectClass, doc)
|
||||
$: void loadParentObject(value, parentMessage, doc)
|
||||
|
||||
async function loadObject (_id: Ref<Doc>, _class: Ref<Class<Doc>>, doc?: Doc): Promise<void> {
|
||||
if (doc !== undefined && doc._id === _id) {
|
||||
object = doc
|
||||
isObjectRemoved = false
|
||||
return
|
||||
}
|
||||
|
||||
async function loadObject (_id: Ref<Doc>, _class: Ref<Class<Doc>>): Promise<void> {
|
||||
isObjectRemoved = await checkIsObjectRemoved(client, _id, _class)
|
||||
|
||||
if (isObjectRemoved) {
|
||||
@ -132,13 +139,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function loadParentObject (message: DocUpdateMessage, parentMessage?: ActivityMessage): Promise<void> {
|
||||
async function loadParentObject (
|
||||
message: DocUpdateMessage,
|
||||
parentMessage?: ActivityMessage,
|
||||
doc?: Doc
|
||||
): Promise<void> {
|
||||
if (!parentMessage && message.objectId === message.attachedTo) {
|
||||
return
|
||||
}
|
||||
|
||||
const _id = parentMessage ? parentMessage.attachedTo : message.attachedTo
|
||||
const _class = parentMessage ? parentMessage.attachedToClass : message.attachedToClass
|
||||
|
||||
if (doc !== undefined && doc._id === _id) {
|
||||
parentObject = doc
|
||||
return
|
||||
}
|
||||
|
||||
const isRemoved = await checkIsObjectRemoved(client, _id, _class)
|
||||
|
||||
if (isRemoved) {
|
||||
|
@ -37,7 +37,8 @@ import {
|
||||
pinMessage,
|
||||
canSaveForLater,
|
||||
canUnpinMessage,
|
||||
removeFromSaved
|
||||
removeFromSaved,
|
||||
shouldScrollToActivity
|
||||
} from './utils'
|
||||
|
||||
export * from './activity'
|
||||
@ -84,7 +85,8 @@ export default async (): Promise<Resources> => ({
|
||||
CanSaveForLater: canSaveForLater,
|
||||
CanRemoveFromSaved: canRemoveFromSaved,
|
||||
CanPinMessage: canPinMessage,
|
||||
CanUnpinMessage: canUnpinMessage
|
||||
CanUnpinMessage: canUnpinMessage,
|
||||
ShouldScrollToActivity: shouldScrollToActivity
|
||||
},
|
||||
backreference: {
|
||||
Update: updateReferences
|
||||
|
@ -2,7 +2,14 @@ import { get } from 'svelte/store'
|
||||
import type { ActivityMessage, Reaction } from '@hcengineering/activity'
|
||||
import core, { type Doc, type Ref, type TxOperations, getCurrentAccount, isOtherHour } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { type Location, getEventPositionElement, closePopup, showPopup, EmojiPopup } from '@hcengineering/ui'
|
||||
import {
|
||||
type Location,
|
||||
getEventPositionElement,
|
||||
closePopup,
|
||||
showPopup,
|
||||
EmojiPopup,
|
||||
getCurrentResolvedLocation
|
||||
} from '@hcengineering/ui'
|
||||
import { type AttributeModel } from '@hcengineering/view'
|
||||
import preference from '@hcengineering/preference'
|
||||
|
||||
@ -157,3 +164,8 @@ export function canGroupMessages (message: MessageData, prevMessage?: MessageDat
|
||||
|
||||
return time1 - time2 < groupMessagesThresholdMs
|
||||
}
|
||||
|
||||
export function shouldScrollToActivity (): boolean {
|
||||
const loc = getCurrentResolvedLocation()
|
||||
return getMessageFromLoc(loc) !== undefined
|
||||
}
|
||||
|
@ -320,6 +320,9 @@ export default plugin(activityId, {
|
||||
AllFilter: '' as Ref<ActivityMessagesFilter>,
|
||||
MentionNotification: '' as Ref<Doc>
|
||||
},
|
||||
function: {
|
||||
ShouldScrollToActivity: '' as Resource<() => boolean>
|
||||
},
|
||||
backreference: {
|
||||
// Update list of back references
|
||||
Update: '' as Resource<(source: Doc, key: string, target: RelatedDocument[], label: IntlString) => Promise<void>>
|
||||
|
@ -411,4 +411,42 @@ export class ChannelDataProvider implements IChannelDataProvider {
|
||||
this.clearMessages()
|
||||
await this.loadInitialMessages(msg._id)
|
||||
}
|
||||
|
||||
public jumpToMessage (message: ActivityMessage): boolean {
|
||||
const metadata = get(this.metadataStore).find(({ _id }) => _id === message._id)
|
||||
|
||||
if (metadata === undefined) {
|
||||
return false
|
||||
}
|
||||
|
||||
const isAlreadyLoaded = get(this.messagesStore).some(({ _id }) => _id === message._id)
|
||||
|
||||
if (isAlreadyLoaded) {
|
||||
return false
|
||||
}
|
||||
|
||||
this.clearMessages()
|
||||
void this.loadInitialMessages(message._id)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
public jumpToEnd (): boolean {
|
||||
const last = get(this.metadataStore)[get(this.metadataStore).length - 1]
|
||||
|
||||
if (last === undefined) {
|
||||
return false
|
||||
}
|
||||
|
||||
const isAlreadyLoaded = get(this.messagesStore).some(({ _id }) => _id === last._id)
|
||||
|
||||
if (isAlreadyLoaded) {
|
||||
return false
|
||||
}
|
||||
|
||||
this.clearMessages()
|
||||
void this.loadInitialMessages()
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -17,12 +17,13 @@
|
||||
import { DocNotifyContext } from '@hcengineering/notification'
|
||||
import activity, { ActivityMessage, ActivityMessagesFilter } from '@hcengineering/activity'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { getMessageFromLoc } from '@hcengineering/activity-resources'
|
||||
import { getMessageFromLoc, messageInFocus } from '@hcengineering/activity-resources'
|
||||
import { location as locationStore } from '@hcengineering/ui'
|
||||
|
||||
import chunter from '../plugin'
|
||||
import ChannelScrollView from './ChannelScrollView.svelte'
|
||||
import { ChannelDataProvider } from '../channelDataProvider'
|
||||
import { onDestroy } from 'svelte'
|
||||
|
||||
export let object: Doc
|
||||
export let context: DocNotifyContext | undefined
|
||||
@ -35,8 +36,23 @@
|
||||
let dataProvider: ChannelDataProvider | undefined
|
||||
let selectedMessageId: Ref<ActivityMessage> | undefined = undefined
|
||||
|
||||
locationStore.subscribe((newLocation) => {
|
||||
selectedMessageId = getMessageFromLoc(newLocation)
|
||||
const unsubscribe = messageInFocus.subscribe((id) => {
|
||||
if (id !== undefined && id !== selectedMessageId) {
|
||||
selectedMessageId = id
|
||||
}
|
||||
|
||||
messageInFocus.set(undefined)
|
||||
})
|
||||
|
||||
const unsubscribeLocation = locationStore.subscribe((newLocation) => {
|
||||
const id = getMessageFromLoc(newLocation)
|
||||
selectedMessageId = id
|
||||
messageInFocus.set(id)
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
unsubscribe()
|
||||
unsubscribeLocation()
|
||||
})
|
||||
|
||||
$: isDocChannel = !hierarchy.isDerived(object._class, chunter.class.ChunterSpace)
|
||||
|
@ -432,6 +432,29 @@
|
||||
}
|
||||
}
|
||||
|
||||
function reinitializeScroll (): void {
|
||||
isScrollInitialized = false
|
||||
void initializeScroll(isLoading, separatorElement, separatorIndex)
|
||||
}
|
||||
|
||||
function adjustScrollPosition (selectedMessageId: Ref<ActivityMessage> | undefined): void {
|
||||
if (isLoading || !isScrollInitialized || isInitialScrolling) {
|
||||
return
|
||||
}
|
||||
const msg = messages.find(({ _id }) => _id === selectedMessageId)
|
||||
if (msg !== undefined) {
|
||||
const isReload = provider.jumpToMessage(msg)
|
||||
if (isReload) {
|
||||
reinitializeScroll()
|
||||
}
|
||||
} else {
|
||||
provider.jumpToEnd()
|
||||
reinitializeScroll()
|
||||
}
|
||||
}
|
||||
|
||||
$: adjustScrollPosition(selectedMessageId)
|
||||
|
||||
function waitLastMessageRenderAndRead (onComplete?: () => void) {
|
||||
if (isLastMessageViewed()) {
|
||||
readViewportMessages()
|
||||
@ -614,6 +637,7 @@
|
||||
|
||||
<div class="msg">
|
||||
<ActivityMessagePresenter
|
||||
doc={object}
|
||||
value={message}
|
||||
skipLabel={skipLabels}
|
||||
{showEmbedded}
|
||||
|
@ -30,6 +30,7 @@
|
||||
import ChatMessageInput from './ChatMessageInput.svelte'
|
||||
|
||||
export let value: WithLookup<ChatMessage> | undefined
|
||||
export let doc: Doc | undefined = undefined
|
||||
export let showNotify: boolean = false
|
||||
export let isHighlighted: boolean = false
|
||||
export let isSelected: boolean = false
|
||||
@ -87,10 +88,13 @@
|
||||
parentMessage = res as DisplayActivityMessage
|
||||
})
|
||||
|
||||
$: value &&
|
||||
client.findOne(value.attachedToClass, { _id: value.attachedTo }).then((result) => {
|
||||
$: if (doc && value?.attachedTo === doc._id) {
|
||||
object = doc
|
||||
} else if (value) {
|
||||
void client.findOne(value.attachedToClass, { _id: value.attachedTo }).then((result) => {
|
||||
object = result
|
||||
})
|
||||
}
|
||||
|
||||
$: parentMessage &&
|
||||
client.findOne(parentMessage.attachedToClass, { _id: parentMessage.attachedTo }).then((result) => {
|
||||
|
@ -18,7 +18,7 @@ import activity, {
|
||||
type DisplayDocUpdateMessage,
|
||||
type DocUpdateMessage
|
||||
} from '@hcengineering/activity'
|
||||
import { activityMessagesComparator, combineActivityMessages } from '@hcengineering/activity-resources'
|
||||
import { activityMessagesComparator, combineActivityMessages, messageInFocus } from '@hcengineering/activity-resources'
|
||||
import {
|
||||
SortingOrder,
|
||||
getCurrentAccount,
|
||||
@ -49,7 +49,8 @@ import {
|
||||
parseLocation,
|
||||
showPopup,
|
||||
type Location,
|
||||
type ResolvedLocation
|
||||
type ResolvedLocation,
|
||||
locationStorageKeyId
|
||||
} from '@hcengineering/ui'
|
||||
import { get, writable } from 'svelte/store'
|
||||
|
||||
@ -525,6 +526,7 @@ export function openInboxDoc (
|
||||
if (_id === undefined || _class === undefined) {
|
||||
loc.query = { message: null }
|
||||
loc.path.length = 3
|
||||
localStorage.setItem(`${locationStorageKeyId}_${notificationId}`, JSON.stringify(loc))
|
||||
navigate(loc)
|
||||
return
|
||||
}
|
||||
@ -540,7 +542,7 @@ export function openInboxDoc (
|
||||
}
|
||||
|
||||
loc.query = { ...loc.query, message: message ?? null }
|
||||
|
||||
messageInFocus.set(message)
|
||||
navigate(loc)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user