mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-13 21:27:46 +02:00
Direct typing and presence (#10147)
Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
@@ -51,7 +51,7 @@
|
||||
"@hcengineering/ui": "^0.7.0",
|
||||
"@hcengineering/view": "^0.7.0",
|
||||
"@hcengineering/view-resources": "^0.7.0",
|
||||
"@hcengineering/communication-types": "^0.7.7",
|
||||
"@hcengineering/communication-types": "^0.7.8",
|
||||
"@hcengineering/emoji": "^0.7.0",
|
||||
"@hcengineering/emoji-resources": "^0.7.0",
|
||||
"svelte": "^4.2.20"
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"dependencies": {
|
||||
"@hcengineering/presence": "^0.7.0",
|
||||
"@hcengineering/presentation": "^0.7.0",
|
||||
"@hcengineering/communication-types": "^0.7.7",
|
||||
"@hcengineering/communication-types": "^0.7.8",
|
||||
"@hcengineering/communication-resources": "^0.7.0",
|
||||
"@hcengineering/core": "^0.7.10",
|
||||
"@hcengineering/ui": "^0.7.0",
|
||||
|
||||
@@ -200,8 +200,14 @@
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="presence">
|
||||
<Component is={presence.component.Presence} props={{ object: doc }} />
|
||||
<Component is={presence.component.PresenceAvatars} props={{ object: doc, size: 'x-small', limit: 5 }} />
|
||||
<Component
|
||||
is={presence.component.Presence}
|
||||
props={{ object: doc, presenceId: doc.peerId ? `peer:${doc.peerId}` : doc._id }}
|
||||
/>
|
||||
<Component
|
||||
is={presence.component.PresenceAvatars}
|
||||
props={{ object: doc, size: 'x-small', limit: 5, presenceId: doc.peerId ? `peer:${doc.peerId}` : doc._id }}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="pre-utils">
|
||||
|
||||
@@ -57,6 +57,8 @@ export interface Card extends Doc, IconProps {
|
||||
parent?: Ref<Card> | null
|
||||
rank: Rank
|
||||
readonly?: boolean
|
||||
|
||||
peerId?: string
|
||||
}
|
||||
|
||||
export interface CardSpace extends Space {
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"@hcengineering/card": "^0.7.0",
|
||||
"@hcengineering/card-resources": "^0.7.0",
|
||||
"@hcengineering/chat": "^0.7.0",
|
||||
"@hcengineering/communication-types": "^0.7.7",
|
||||
"@hcengineering/communication-types": "^0.7.8",
|
||||
"@hcengineering/communication": "^0.7.0",
|
||||
"@hcengineering/contact": "^0.7.0",
|
||||
"@hcengineering/contact-resources": "^0.7.0",
|
||||
@@ -55,7 +55,7 @@
|
||||
"@hcengineering/workbench": "^0.7.0",
|
||||
"@hcengineering/workbench-resources": "^0.7.0",
|
||||
"@hcengineering/communication-resources": "^0.7.0",
|
||||
"@hcengineering/communication-shared": "^0.7.7",
|
||||
"@hcengineering/communication-shared": "^0.7.8",
|
||||
"@hcengineering/rank": "^0.7.5",
|
||||
"@hcengineering/text": "^0.7.5",
|
||||
"@hcengineering/text-markdown": "^0.7.5",
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
"@hcengineering/card": "^0.7.0",
|
||||
"@hcengineering/chat": "^0.7.0",
|
||||
"@hcengineering/communication": "^0.7.0",
|
||||
"@hcengineering/communication-types": "^0.7.7",
|
||||
"@hcengineering/communication-shared": "^0.7.7",
|
||||
"@hcengineering/communication-types": "^0.7.8",
|
||||
"@hcengineering/communication-shared": "^0.7.8",
|
||||
"@hcengineering/contact": "^0.7.0",
|
||||
"@hcengineering/contact-resources": "^0.7.0",
|
||||
"@hcengineering/core": "^0.7.10",
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
import communication from '../plugin'
|
||||
|
||||
export let cardId: CardID
|
||||
export let peerId: string | undefined
|
||||
|
||||
const maxTypingPersons = 3
|
||||
const acc = getCurrentAccount()
|
||||
@@ -40,6 +41,8 @@
|
||||
let typingInfo = new Map<string, TypingInfo>()
|
||||
let typingGroups: TypingGroup[] = []
|
||||
|
||||
$: objectId = peerId ? `peer${peerId}` : cardId
|
||||
|
||||
$: void updateTypingPersons(typingInfo)
|
||||
|
||||
async function updateTypingPersons (typingInfo: Map<string, TypingInfo>): Promise<void> {
|
||||
@@ -91,7 +94,7 @@
|
||||
class="root h-4 mt-1 mb-1 ml-0-5 overflow-label"
|
||||
use:typing={{
|
||||
socialId: acc.primarySocialId,
|
||||
objectId: cardId,
|
||||
objectId,
|
||||
onTyping: handleTyping
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -461,7 +461,7 @@
|
||||
if (message !== undefined) return
|
||||
if (!isEmptyMarkup(draft.content)) {
|
||||
throttle.call(() => {
|
||||
void setTyping(acc.primarySocialId, card._id)
|
||||
void setTyping(acc.primarySocialId, card.peerId ? `peer:${card.peerId}` : card._id)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -705,7 +705,7 @@
|
||||
</div>
|
||||
|
||||
{#if message === undefined}
|
||||
<TypingPresenter cardId={card._id} />
|
||||
<TypingPresenter cardId={card._id} peerId={card.peerId} />
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/platform": "^0.7.5",
|
||||
"@hcengineering/communication-types": "^0.7.7",
|
||||
"@hcengineering/communication-types": "^0.7.8",
|
||||
"@hcengineering/core": "^0.7.10",
|
||||
"@hcengineering/contact": "^0.7.0",
|
||||
"@hcengineering/ui": "^0.7.0",
|
||||
|
||||
@@ -42,8 +42,8 @@
|
||||
"@hcengineering/card": "^0.7.0",
|
||||
"@hcengineering/communication": "^0.7.0",
|
||||
"@hcengineering/communication-resources": "^0.7.0",
|
||||
"@hcengineering/communication-types": "^0.7.7",
|
||||
"@hcengineering/communication-shared": "^0.7.7",
|
||||
"@hcengineering/communication-types": "^0.7.8",
|
||||
"@hcengineering/communication-shared": "^0.7.8",
|
||||
"@hcengineering/contact": "^0.7.0",
|
||||
"@hcengineering/contact-resources": "^0.7.0",
|
||||
"@hcengineering/core": "^0.7.10",
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
import PresenceContext from './PresenceContext.svelte'
|
||||
|
||||
export let object: Doc
|
||||
export let presenceId: string | undefined = undefined
|
||||
</script>
|
||||
|
||||
{#key object._id}
|
||||
<PresenceContext {object} />
|
||||
<PresenceContext {object} {presenceId} />
|
||||
{/key}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
import { followee, toggleFollowee } from '../store'
|
||||
|
||||
export let object: Doc
|
||||
export let presenceId: string | undefined = undefined
|
||||
export let size: IconSize = 'small'
|
||||
export let limit: number = 4
|
||||
|
||||
@@ -55,7 +56,7 @@
|
||||
<div
|
||||
use:presence={{
|
||||
personId: me,
|
||||
objectId: object._id,
|
||||
objectId: presenceId ?? object._id,
|
||||
objectClass: object._class,
|
||||
onPresence
|
||||
}}
|
||||
|
||||
@@ -21,18 +21,19 @@
|
||||
import { updatePresence, deletePresence } from '../presence'
|
||||
|
||||
export let object: Doc
|
||||
export let presenceId: string | undefined = undefined
|
||||
export let presenceTtlSeconds: number = 5
|
||||
export let presenceUpdateSeconds: number = 2
|
||||
|
||||
const personId = getCurrentEmployee()
|
||||
|
||||
async function doUpdatePresence (): Promise<void> {
|
||||
const presence = { personId, objectId: object._id, objectClass: object._class }
|
||||
const presence = { personId, objectId: presenceId ?? object._id, objectClass: object._class }
|
||||
await updatePresence(presence, presenceTtlSeconds)
|
||||
}
|
||||
|
||||
async function doDeletePresence (object: Doc): Promise<void> {
|
||||
const presence = { personId, objectId: object._id, objectClass: object._class }
|
||||
async function doDeletePresence (object: Doc, presenceId?: string): Promise<void> {
|
||||
const presence = { personId, objectId: presenceId ?? object._id, objectClass: object._class }
|
||||
await deletePresence(presence)
|
||||
}
|
||||
|
||||
@@ -41,15 +42,20 @@
|
||||
const interval = setInterval(doUpdatePresence, presenceUpdateSeconds * 1000)
|
||||
return () => {
|
||||
clearInterval(interval)
|
||||
void doDeletePresence(object)
|
||||
void doDeletePresence(object, presenceId)
|
||||
}
|
||||
})
|
||||
|
||||
let previousObject: Doc = object
|
||||
let prevPresenceId: string | undefined = presenceId
|
||||
|
||||
$: if (object !== undefined && (object._id !== previousObject._id || object._class !== previousObject._class)) {
|
||||
$: if (
|
||||
object !== undefined &&
|
||||
(object._id !== previousObject._id || object._class !== previousObject._class || presenceId !== prevPresenceId)
|
||||
) {
|
||||
void doDeletePresence(previousObject)
|
||||
previousObject = object
|
||||
prevPresenceId = presenceId
|
||||
void doUpdatePresence()
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -19,13 +19,13 @@ import presentation, { createPulseClient } from '@hcengineering/presentation'
|
||||
|
||||
export interface PresenceInfo {
|
||||
personId: Ref<Person>
|
||||
objectId: Ref<Doc>
|
||||
objectId: string
|
||||
objectClass: Ref<Class<Doc>>
|
||||
}
|
||||
|
||||
export interface PresenceActionParams {
|
||||
personId: Ref<Employee>
|
||||
objectId: Ref<Doc>
|
||||
objectId: string
|
||||
objectClass: Ref<Class<Doc>>
|
||||
onPresence: (presence: Map<string, Ref<Person>>) => void
|
||||
}
|
||||
@@ -83,7 +83,7 @@ export function presence (node: HTMLElement, params: PresenceActionParams): any
|
||||
|
||||
export async function subscribePresence (
|
||||
objectClass: Ref<Class<Doc>>,
|
||||
objectId: Ref<Doc>,
|
||||
objectId: string,
|
||||
callback: Callback<PresenceInfo | undefined>
|
||||
): Promise<UnsubscribeCallback> {
|
||||
const client = await createPulseClient()
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
import { type UnsubscribeCallback, type Callback } from '@hcengineering/hulypulse-client'
|
||||
import { type IntlString, getMetadata } from '@hcengineering/platform'
|
||||
import presentation, { createPulseClient } from '@hcengineering/presentation'
|
||||
import { type Doc, type Ref, type PersonId } from '@hcengineering/core'
|
||||
import { type PersonId } from '@hcengineering/core'
|
||||
|
||||
const typingDelaySeconds = 2
|
||||
|
||||
@@ -24,13 +24,13 @@ function getWorkspace (): string {
|
||||
|
||||
export interface TypingInfo {
|
||||
socialId: PersonId
|
||||
objectId: Ref<Doc>
|
||||
objectId: string
|
||||
status?: IntlString
|
||||
}
|
||||
|
||||
export interface TypingActionParams {
|
||||
socialId: PersonId
|
||||
objectId: Ref<Doc>
|
||||
objectId: string
|
||||
onTyping: (presence: Map<string, TypingInfo>) => void
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ export function typing (node: HTMLElement, params: TypingActionParams): any {
|
||||
}
|
||||
|
||||
export async function subscribeTyping (
|
||||
objectId: Ref<Doc>,
|
||||
objectId: string,
|
||||
callback: Callback<TypingInfo | undefined>
|
||||
): Promise<UnsubscribeCallback> {
|
||||
const client = await createPulseClient()
|
||||
@@ -100,7 +100,7 @@ export async function subscribeTyping (
|
||||
return async () => false
|
||||
}
|
||||
|
||||
export async function setTyping (socialId: PersonId, objectId: Ref<Doc>, status?: IntlString): Promise<void> {
|
||||
export async function setTyping (socialId: PersonId, objectId: string, status?: IntlString): Promise<void> {
|
||||
const client = await createPulseClient()
|
||||
|
||||
if (client !== undefined) {
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
"@hcengineering/support-resources": "^0.7.0",
|
||||
"@hcengineering/view-resources": "^0.7.0",
|
||||
"@hcengineering/inbox": "^0.7.0",
|
||||
"@hcengineering/communication-types": "^0.7.7",
|
||||
"@hcengineering/communication-types": "^0.7.8",
|
||||
"fast-copy": "^3.0.2",
|
||||
"@hcengineering/analytics": "^0.7.5",
|
||||
"@hcengineering/account-client": "^0.7.7",
|
||||
|
||||
Reference in New Issue
Block a user