Inbox keyboard action (#2977)

This commit is contained in:
Denis Bykhov 2023-04-13 22:12:20 +06:00 committed by GitHub
parent 12974b5bb7
commit ad4394d541
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 93 additions and 39 deletions

View File

@ -269,9 +269,10 @@ export function createModel (builder: Builder): void {
label: notification.string.Archive,
icon: view.icon.Archive,
input: 'focus',
keyBinding: ['Backspace'],
category: notification.category.Notification,
target: notification.class.DocUpdates,
context: { mode: 'context', application: notification.app.Notification, group: 'edit' }
context: { mode: ['context', 'browser'], group: 'edit' }
},
notification.action.Hide
)

View File

@ -20,6 +20,7 @@
import { createQuery, getClient } from '@hcengineering/presentation'
import { AnyComponent, Component, Label, Loading, Scroller } from '@hcengineering/ui'
import view from '@hcengineering/view'
import { ActionContext, ListSelectionProvider, SelectDirection } from '@hcengineering/view-resources'
import NotificationView from './NotificationView.svelte'
export let visibileNav: boolean
@ -39,8 +40,11 @@
},
(res) => {
docs = res
if (loading && docs.length > 0) {
select(docs[0].attachedTo, docs[0].attachedToClass)
listProvider.update(docs)
if (loading || _id === undefined) {
changeSelected(selected)
} else if (docs.find((p) => p.attachedTo === _id) === undefined) {
changeSelected(selected)
}
loading = false
},
@ -51,16 +55,32 @@
}
)
function select (objectId: Ref<Doc>, objectClass: Ref<Class<Doc>>) {
const targetClass = hierarchy.getClass(objectClass)
const panelComponent = hierarchy.as(targetClass, view.mixin.ObjectPanel)
component = panelComponent.component ?? view.component.EditDoc
_id = objectId
_class = objectClass
$: changeSelected(selected)
function changeSelected (index: number) {
if (docs[index] !== undefined) {
select(docs[index])
} else if (docs.length) {
if (index < docs.length - 1) {
selected++
} else {
selected--
}
} else {
selected = 0
component = undefined
_id = undefined
_class = undefined
}
}
function selectHandler (e: CustomEvent) {
select(e.detail._id, e.detail._class)
function select (value: DocUpdates) {
listProvider.updateFocus(value)
const targetClass = hierarchy.getClass(value.attachedToClass)
const panelComponent = hierarchy.as(targetClass, view.mixin.ObjectPanel)
component = panelComponent.component ?? view.component.EditDoc
_id = value.attachedTo
_class = value.attachedToClass
}
let component: AnyComponent | undefined
@ -69,12 +89,28 @@
let viewlets: Map<ActivityKey, TxViewlet>
const listProvider = new ListSelectionProvider((offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection) => {
if (dir === 'vertical') {
const value = selected + offset
if (docs[value] !== undefined) {
selected = value
}
}
})
const descriptors = createQuery()
descriptors.query(activity.class.TxViewlet, {}, (result) => {
viewlets = new Map(result.map((r) => [activityKey(r.objectClass, r.txClass), r]))
})
let selected = 0
</script>
<ActionContext
context={{
mode: 'browser'
}}
/>
<div class="flex h-full">
{#if visibileNav}
<div class="antiPanel-component border-right filled indent aside">
@ -88,8 +124,15 @@
{#if loading}
<Loading />
{:else}
{#each docs as doc}
<NotificationView value={doc} selected={doc.attachedTo === _id} {viewlets} on:click={selectHandler} />
{#each docs as doc, i}
<NotificationView
value={doc}
selected={selected === i}
{viewlets}
on:click={() => {
selected = i
}}
/>
{/each}
{/if}
</Scroller>
@ -99,9 +142,7 @@
{#if component && _id && _class}
<Component is={component} props={{ embedded: true, _id, _class }} />
{:else}
<div class="antiPanel-component filled w-full">
<Loading />
</div>
<div class="antiPanel-component filled w-full" />
{/if}
</div>

View File

@ -24,7 +24,6 @@
import { AnySvelteComponent, Label, TimeSince, getEventPositionElement, showPopup } from '@hcengineering/ui'
import view from '@hcengineering/view'
import { Menu } from '@hcengineering/view-resources'
import { createEventDispatcher } from 'svelte'
import TxView from './TxView.svelte'
export let value: DocUpdates
@ -60,10 +59,10 @@
query.query(contact.class.EmployeeAccount, { _id: tx.modifiedBy as Ref<EmployeeAccount> }, (r) => ([account] = r))
$: employee = account && $employeeByIdStore.get(account.employee)
const dispatch = createEventDispatcher()
const docQuery = createQuery()
$: docQuery.query(value.attachedToClass, { _id: value.attachedTo }, (res) => ([doc] = res))
$: docQuery.query(value.attachedToClass, { _id: value.attachedTo }, (res) => {
;[doc] = res
})
$: newTxes = value.txes.length
@ -74,12 +73,7 @@
<!-- svelte-ignore a11y-click-events-have-key-events -->
{#if doc}
<div
class="container cursor-pointer bottom-divider"
class:selected
on:contextmenu|preventDefault={showMenu}
on:click={() => dispatch('click', { _id: value.attachedTo, _class: value.attachedToClass })}
>
<div class="container cursor-pointer bottom-divider" class:selected on:contextmenu|preventDefault={showMenu} on:click>
<div class="header flex">
<Avatar avatar={employee?.avatar} size="medium" />
<div class="ml-2 w-full clear-mins">

View File

@ -133,11 +133,19 @@ export async function unsubscribe (object: DocUpdates): Promise<void> {
/**
* @public
*/
export async function hide (object: DocUpdates): Promise<void> {
export async function hide (object: DocUpdates | DocUpdates[]): Promise<void> {
const client = getClient()
await client.update(object, {
hidden: true
})
if (Array.isArray(object)) {
for (const value of object) {
await client.update(value, {
hidden: true
})
}
} else {
await client.update(object, {
hidden: true
})
}
}
/**

View File

@ -15,7 +15,7 @@
<script lang="ts">
import { Doc, DocumentQuery, Ref } from '@hcengineering/core'
import { Issue, Project } from '@hcengineering/tracker'
import { Viewlet, ViewOptions } from '@hcengineering/view'
import { ViewOptions, Viewlet } from '@hcengineering/view'
import {
ActionContext,
List,
@ -23,7 +23,6 @@
SelectDirection,
selectionStore
} from '@hcengineering/view-resources'
import { onDestroy } from 'svelte'
import tracker from '../../../plugin'
export let query: DocumentQuery<Issue> | undefined = undefined
@ -43,10 +42,6 @@
list.select(offset, of)
}
})
onDestroy(() => {
ListSelectionProvider.Pop()
})
</script>
<ActionContext

View File

@ -146,13 +146,15 @@ export class ListSelectionProvider implements SelectionFocusProvider {
})
if (this._docs.length > 0) {
if (this._current?.focus === undefined) {
if (this._current === undefined) {
this.delegate(0, undefined, 'vertical')
} else {
// Check if we don't have object, we need to select first one.
this.delegate(0, this._current?.focus, 'vertical')
}
updateFocus({ focus: this._current?.focus, provider: this })
if (this._current?.focus === undefined) {
updateFocus({ focus: this._current?.focus, provider: this })
}
}
}

View File

@ -132,7 +132,10 @@ async function CommentCreate (tx: TxCUD<Doc>, control: TriggerControl): Promise<
const actualTx = TxProcessor.extractTx(tx)
if (actualTx._class !== core.class.TxCreateDoc) return []
const doc = TxProcessor.createDoc2Doc(actualTx as TxCreateDoc<Comment>)
if (!hierarchy.isDerived(doc._class, chunter.class.Comment)) {
if (
!hierarchy.isDerived(doc._class, chunter.class.Comment) ||
hierarchy.isDerived(doc._class, chunter.class.Backlink)
) {
return []
}
const res: Tx[] = []

View File

@ -94,6 +94,16 @@ export async function OnBacklinkCreate (tx: Tx, control: TriggerControl): Promis
}
)
res.push(collabTx)
res = res.concat(
await createCollabDocInfo(
[receiver._id],
tx as TxCUD<Doc>,
doc._id,
doc._class,
control,
tx._id as Ref<TxCUD<Doc>>
)
)
}
}
const notifyTx = await createNotificationTxes(