Chunter: Open message links without reload (#2124)

Signed-off-by: Denis Bunakalya <denis.bunakalya@xored.com>
This commit is contained in:
Denis Bunakalya 2022-06-27 16:55:52 +03:00 committed by GitHub
parent b12ee1d8b7
commit c7e916abd1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 67 additions and 52 deletions

View File

@ -14,7 +14,7 @@
// limitations under the License.
-->
<script lang="ts">
import { CheckBox, Component } from '@anticrm/ui'
import { CheckBox, Component, navigate, parseLocation } from '@anticrm/ui'
import view from '@anticrm/view'
export let nodes: NodeListOf<any>
@ -63,8 +63,19 @@
{:else if node.nodeName === 'DIV'}
<div><svelte:self nodes={node.childNodes} /></div>
{:else if node.nodeName === 'A'}
<a href={node.getAttribute('href')} target={node.getAttribute('target')}
><svelte:self nodes={node.childNodes} /></a
<a
href={node.getAttribute('href')}
target={node.getAttribute('target')}
on:click={(e) => {
try {
const url = new URL(node.getAttribute('href'))
if (url.origin === window.location.origin) {
e.preventDefault()
navigate(parseLocation(url))
}
} catch {}
}}><svelte:self nodes={node.childNodes} /></a
>
{:else if node.nodeName === 'LABEL'}
<svelte:self nodes={node.childNodes} />

View File

@ -40,5 +40,5 @@
dispatch('close')
}}
>
<EditBox placeholder={linkPlaceholder} bind:value={link} maxWidth={'16rem'} focus />
<EditBox placeholder={linkPlaceholder} bind:value={link} maxWidth={'37.75rem'} focus />
</Card>

View File

@ -43,7 +43,7 @@ export function locationToUrl (location: PlatformLocation): string {
return result
}
function parseLocation (location: Location): PlatformLocation {
export function parseLocation (location: Location | URL): PlatformLocation {
return {
path: parsePath(location.pathname),
query: parseQuery(location.search),

View File

@ -19,10 +19,10 @@
import core, { Doc, Ref, Space, Timestamp, WithLookup } from '@anticrm/core'
import { NotificationClientImpl } from '@anticrm/notification-resources'
import { createQuery } from '@anticrm/presentation'
import { getCurrentLocation, navigate } from '@anticrm/ui'
import { afterUpdate, beforeUpdate } from 'svelte'
import { location as locationStore } from '@anticrm/ui'
import { afterUpdate, beforeUpdate, onDestroy } from 'svelte'
import chunter from '../plugin'
import { getDay } from '../utils'
import { getDay, messageIdForScroll, shouldScrollToMessage, isMessageHighlighted, scrollAndHighLight } from '../utils'
import ChannelSeparator from './ChannelSeparator.svelte'
import JumpToDateSelector from './JumpToDateSelector.svelte'
import MessageComponent from './Message.svelte'
@ -35,24 +35,31 @@
let div: HTMLDivElement | undefined
let autoscroll: boolean = false
let messageIdForScroll = ''
let isMessageHighlighted = false
const unsubscribe = locationStore.subscribe((newLocation) => {
const messageId = newLocation.fragment
if (!messageId) {
messageIdForScroll.set('')
return
}
if (messageId === $messageIdForScroll) {
return
}
messageIdForScroll.set(messageId)
shouldScrollToMessage.set(true)
scrollAndHighLight()
})
onDestroy(unsubscribe)
beforeUpdate(() => {
autoscroll = div !== undefined && div.offsetHeight + div.scrollTop > div.scrollHeight - 20
})
afterUpdate(() => {
if (messageIdForScroll && !isMessageHighlighted) {
const messageElement = document.getElementById(messageIdForScroll)
messageElement?.scrollIntoView()
isMessageHighlighted = true
setTimeout(() => {
messageIdForScroll = ''
isMessageHighlighted = false
}, 2000)
if ($shouldScrollToMessage && !$isMessageHighlighted) {
scrollAndHighLight()
return
}
@ -101,15 +108,6 @@
messages = res
newMessagesPos = newMessagesStart(messages)
notificationClient.updateLastView(space, chunter.class.ChunterSpace)
const location = getCurrentLocation()
const messageId = location.fragment
if (messageId && location.path.length === 3) {
messageIdForScroll = messageId
location.fragment = undefined
navigate(location)
}
},
{
lookup: {
@ -230,7 +228,7 @@
<JumpToDateSelector selectedDate={message.createOn} on:jumpToDate={handleJumpToDate} />
{/if}
<MessageComponent
isHighlighted={messageIdForScroll === message._id && isMessageHighlighted}
isHighlighted={$messageIdForScroll === message._id && $isMessageHighlighted}
{message}
{employees}
on:openThread

View File

@ -24,6 +24,7 @@
import { afterUpdate, beforeUpdate, createEventDispatcher } from 'svelte'
import { createBacklinks } from '../backlinks'
import chunter from '../plugin'
import { messageIdForScroll, shouldScrollToMessage, isMessageHighlighted, scrollAndHighLight } from '../utils'
import ChannelSeparator from './ChannelSeparator.svelte'
import MsgView from './Message.svelte'
@ -40,24 +41,14 @@
let div: HTMLDivElement | undefined
let autoscroll: boolean = false
let isScrollForced = false
let messageIdForScroll = ''
let isMessageHighlighted = false
beforeUpdate(() => {
autoscroll = div !== undefined && div.offsetHeight + div.scrollTop > div.scrollHeight - 20
})
afterUpdate(() => {
if (messageIdForScroll && !isMessageHighlighted) {
const messageElement = document.getElementById(messageIdForScroll)
messageElement?.scrollIntoView()
isMessageHighlighted = true
setTimeout(() => {
messageIdForScroll = ''
isMessageHighlighted = false
}, 2000)
if ($shouldScrollToMessage && !$isMessageHighlighted) {
scrollAndHighLight()
return
}
@ -112,15 +103,6 @@
comments = res
newMessagesPos = newMessagesStart(comments, $lastViews)
notificationClient.updateLastView(id, chunter.class.Message)
const location = getCurrentLocation()
const messageId = location.fragment
if (messageId && location.path.length === 4) {
messageIdForScroll = messageId
location.fragment = undefined
navigate(location)
}
},
{
lookup
@ -235,7 +217,7 @@
<ChannelSeparator title={chunter.string.New} line reverse isNew />
{/if}
<MsgView
isHighlighted={messageIdForScroll === comment._id && isMessageHighlighted}
isHighlighted={$messageIdForScroll === comment._id && $isMessageHighlighted}
message={comment}
{employees}
thread

View File

@ -3,6 +3,7 @@ import contact, { EmployeeAccount, formatName } from '@anticrm/contact'
import { Account, Class, Client, Obj, Ref, Space, getCurrentAccount, Timestamp } from '@anticrm/core'
import { Asset } from '@anticrm/platform'
import { getCurrentLocation, locationToUrl, navigate } from '@anticrm/ui'
import { writable, get } from 'svelte/store'
import chunter from './plugin'
@ -97,3 +98,26 @@ export enum SearchType {
Files,
Contacts
}
export const messageIdForScroll = writable('')
export const shouldScrollToMessage = writable(false)
export const isMessageHighlighted = writable(false)
let highlightFinishTaskId: number
export function scrollAndHighLight (): void {
const messageElement = document.getElementById(get(messageIdForScroll))
if (messageElement == null) {
return
}
messageElement.scrollIntoView()
shouldScrollToMessage.set(false)
clearTimeout(highlightFinishTaskId)
isMessageHighlighted.set(true)
highlightFinishTaskId = window.setTimeout(() => {
isMessageHighlighted.set(false)
}, 2000)
}