mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-23 11:31:57 +03:00
Chunter: Copy link to message (#2078)
Signed-off-by: Denis Bunakalya <denis.bunakalya@xored.com>
This commit is contained in:
parent
e0853ecf99
commit
9d772b786f
@ -16,13 +16,16 @@ let currentLocation: string | undefined
|
||||
location.subscribe((loc) => {
|
||||
if (loc.fragment !== currentLocation && loc.fragment !== undefined && loc.fragment.trim().length > 0) {
|
||||
const props = decodeURIComponent(loc.fragment).split('|')
|
||||
showPanel(
|
||||
props[0] as AnyComponent,
|
||||
props[1],
|
||||
props[2],
|
||||
(props[3] ?? undefined) as PopupAlignment,
|
||||
(props[4] ?? undefined) as AnyComponent
|
||||
)
|
||||
|
||||
if (props.length >= 3) {
|
||||
showPanel(
|
||||
props[0] as AnyComponent,
|
||||
props[1],
|
||||
props[2],
|
||||
(props[3] ?? undefined) as PopupAlignment,
|
||||
(props[4] ?? undefined) as AnyComponent
|
||||
)
|
||||
}
|
||||
} else if (
|
||||
(loc.fragment === undefined || (loc.fragment !== undefined && loc.fragment.trim().length === 0)) &&
|
||||
currentLocation !== undefined
|
||||
|
@ -65,6 +65,7 @@
|
||||
"ThreadMessage": "Thread message",
|
||||
"ChunterBrowser": "Search",
|
||||
"Messages": "Messages",
|
||||
"NoResults": "No results"
|
||||
"NoResults": "No results",
|
||||
"CopyLink": "Copy link"
|
||||
}
|
||||
}
|
@ -64,6 +64,7 @@
|
||||
"ThreadMessage": "Сообщение в обсуждении",
|
||||
"ChunterBrowser": "Поиск",
|
||||
"Messages": "Сообщения",
|
||||
"NoResults": "Нет результатов"
|
||||
"NoResults": "Нет результатов",
|
||||
"CopyLink": "Копировать ссылку"
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@
|
||||
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 chunter from '../plugin'
|
||||
import { getDay } from '../utils'
|
||||
@ -34,12 +35,27 @@
|
||||
|
||||
let div: HTMLDivElement | undefined
|
||||
let autoscroll: boolean = 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)
|
||||
|
||||
return
|
||||
}
|
||||
if (div && (autoscroll || isScrollForced)) {
|
||||
div.scrollTo(0, div.scrollHeight)
|
||||
isScrollForced = false
|
||||
@ -85,6 +101,15 @@
|
||||
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: {
|
||||
@ -205,6 +230,7 @@
|
||||
<JumpToDateSelector selectedDate={message.createOn} on:jumpToDate={handleJumpToDate} />
|
||||
{/if}
|
||||
<MessageComponent
|
||||
isHighlighted={messageIdForScroll === message._id && isMessageHighlighted}
|
||||
{message}
|
||||
{employees}
|
||||
on:openThread
|
||||
|
@ -22,7 +22,17 @@
|
||||
import { NotificationClientImpl } from '@anticrm/notification-resources'
|
||||
import { getResource } from '@anticrm/platform'
|
||||
import { Avatar, getClient, MessageViewer } from '@anticrm/presentation'
|
||||
import ui, { ActionIcon, IconMoreH, Menu, showPopup, Label, Tooltip, Button } from '@anticrm/ui'
|
||||
import ui, {
|
||||
ActionIcon,
|
||||
IconMoreH,
|
||||
Menu,
|
||||
showPopup,
|
||||
Label,
|
||||
Tooltip,
|
||||
Button,
|
||||
getCurrentLocation,
|
||||
locationToUrl
|
||||
} from '@anticrm/ui'
|
||||
import { Action } from '@anticrm/view'
|
||||
import { getActions, LinkPresenter } from '@anticrm/view-resources'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
@ -42,6 +52,7 @@
|
||||
export let thread: boolean = false
|
||||
export let isPinned: boolean = false
|
||||
export let isSaved: boolean = false
|
||||
export let isHighlighted = false
|
||||
|
||||
let refInput: AttachmentRefInput
|
||||
|
||||
@ -95,6 +106,24 @@
|
||||
}
|
||||
}
|
||||
|
||||
const copyLinkAction = {
|
||||
label: chunter.string.CopyLink,
|
||||
action: async () => {
|
||||
const location = getCurrentLocation()
|
||||
|
||||
location.fragment = message._id
|
||||
location.path[2] = message.space
|
||||
|
||||
if (message.attachedToClass === chunter.class.Message) {
|
||||
location.path.length = 4
|
||||
location.path[3] = message.attachedTo
|
||||
} else {
|
||||
location.path.length = 3
|
||||
}
|
||||
await navigator.clipboard.writeText(`${window.location.origin}${locationToUrl(location)}`)
|
||||
}
|
||||
}
|
||||
|
||||
let menuShowed = false
|
||||
|
||||
const showMenu = async (ev: Event): Promise<void> => {
|
||||
@ -115,6 +144,7 @@
|
||||
await impl(message, evt)
|
||||
}
|
||||
})),
|
||||
copyLinkAction,
|
||||
...(getCurrentAccount()._id === message.createBy ? [editAction, deleteAction] : [])
|
||||
]
|
||||
},
|
||||
@ -176,7 +206,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
<div class="container" class:highlighted={isHighlighted} id={message._id}>
|
||||
<div class="avatar"><Avatar size={'medium'} avatar={employee?.avatar} /></div>
|
||||
<div class="message">
|
||||
<div class="header">
|
||||
@ -253,11 +283,20 @@
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@keyframes highlight {
|
||||
50% {
|
||||
background-color: var(--warning-color);
|
||||
}
|
||||
}
|
||||
.container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: 0.5rem 2rem;
|
||||
|
||||
&.highlighted {
|
||||
animation: highlight 2000ms ease-in-out;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
min-width: 2.25rem;
|
||||
}
|
||||
|
@ -40,12 +40,27 @@
|
||||
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)
|
||||
|
||||
return
|
||||
}
|
||||
if (div && (autoscroll || isScrollForced)) {
|
||||
div.scrollTo(0, div.scrollHeight)
|
||||
isScrollForced = false
|
||||
@ -97,6 +112,15 @@
|
||||
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
|
||||
@ -211,6 +235,7 @@
|
||||
<ChannelSeparator title={chunter.string.New} line reverse isNew />
|
||||
{/if}
|
||||
<MsgView
|
||||
isHighlighted={messageIdForScroll === comment._id && isMessageHighlighted}
|
||||
message={comment}
|
||||
{employees}
|
||||
thread
|
||||
|
@ -85,6 +85,7 @@ export default mergeIds(chunterId, chunter, {
|
||||
MessagesBrowser: '' as IntlString,
|
||||
ChunterBrowser: '' as IntlString,
|
||||
Messages: '' as IntlString,
|
||||
NoResults: '' as IntlString
|
||||
NoResults: '' as IntlString,
|
||||
CopyLink: '' as IntlString
|
||||
}
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user