tracker key actions (#2598)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2023-02-07 19:27:46 +06:00 committed by GitHub
parent 243bc1dede
commit c5be92d870
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 264 additions and 144 deletions

View File

@ -284,7 +284,9 @@ export function createModel (builder: Builder): void {
input: 'any',
category: board.category.Card,
target: board.class.Card,
context: { mode: 'context', application: board.app.Board, group: 'create' }
keyBinding: ['Enter'],
context: { mode: 'context', application: board.app.Board, group: 'create' },
override: [view.action.Open]
},
board.action.Open
)

View File

@ -30,7 +30,7 @@ import {
Persons,
Status
} from '@hcengineering/contact'
import { Class, DateRangeMode, Domain, Ref, Timestamp, DOMAIN_MODEL, IndexKind } from '@hcengineering/core'
import { Class, DateRangeMode, Domain, DOMAIN_MODEL, IndexKind, Ref, Timestamp } from '@hcengineering/core'
import {
Builder,
Collection,
@ -48,7 +48,7 @@ import attachment from '@hcengineering/model-attachment'
import chunter from '@hcengineering/model-chunter'
import core, { TAccount, TAttachedDoc, TDoc, TSpace } from '@hcengineering/model-core'
import presentation from '@hcengineering/model-presentation'
import view, { actionTemplates, createAction, ViewAction, Viewlet } from '@hcengineering/model-view'
import view, { createAction, ViewAction, Viewlet } from '@hcengineering/model-view'
import workbench from '@hcengineering/model-workbench'
import type { Asset, IntlString, Resource } from '@hcengineering/platform'
import setting from '@hcengineering/setting'
@ -498,15 +498,6 @@ export function createModel (builder: Builder): void {
contact.completion.OrganizationCategory
)
createAction(builder, {
...actionTemplates.open,
target: contact.class.Contact,
context: {
mode: ['browser', 'context'],
group: 'create'
}
})
createAction(
builder,
{

View File

@ -245,11 +245,15 @@ export function createModel (builder: Builder): void {
createAction(builder, {
...actionTemplates.open,
actionProps: {
component: document.component.EditDoc
},
target: document.class.Document,
context: {
mode: ['browser', 'context'],
group: 'create'
}
},
override: [view.action.Open]
})
builder.mixin(document.class.DocumentVersion, core.class.Class, view.mixin.CollectionEditor, {
editor: document.component.DocumentVersions

View File

@ -179,7 +179,7 @@ export function createModel (builder: Builder): void {
label: gmail.string.WrtieEmail,
icon: contact.icon.Email,
keyBinding: [],
input: 'none',
input: 'any',
category: contact.category.Contact,
target: contact.class.Contact,
context: {

View File

@ -620,7 +620,7 @@ export function createModel (builder: Builder): void {
},
label: recruit.string.CreateTalent,
icon: recruit.icon.Create,
keyBinding: ['c'],
keyBinding: ['keyC'],
input: 'none',
category: recruit.category.Recruit,
target: core.class.Doc,
@ -720,7 +720,7 @@ export function createModel (builder: Builder): void {
},
input: 'focus',
category: recruit.category.Recruit,
keyBinding: ['e'],
keyBinding: ['keyE'],
target: recruit.class.Vacancy,
context: {
mode: ['context', 'browser'],

View File

@ -117,6 +117,10 @@ export function createModel (builder: Builder): void {
component: tags.component.TagsFilter
})
builder.mixin(tags.class.TagElement, core.class.Class, view.mixin.IgnoreActions, {
actions: [view.action.Open]
})
builder.createDoc(
view.class.FilterMode,
core.space.Model,

View File

@ -48,7 +48,7 @@ import {
import attachment from '@hcengineering/model-attachment'
import chunter from '@hcengineering/model-chunter'
import core, { DOMAIN_SPACE, TAttachedDoc, TDoc, TSpace, TType } from '@hcengineering/model-core'
import view, { classPresenter, createAction } from '@hcengineering/model-view'
import view, { actionTemplates, classPresenter, createAction } from '@hcengineering/model-view'
import workbench, { createNavigateAction } from '@hcengineering/model-workbench'
import notification from '@hcengineering/notification'
import { Asset, IntlString } from '@hcengineering/platform'
@ -1053,6 +1053,29 @@ export function createModel (builder: Builder): void {
tracker.category.Tracker
)
createAction(
builder,
{
action: view.actionImpl.ShowPopup,
actionProps: {
component: tracker.component.CreateIssue,
element: 'top'
},
label: tracker.string.NewIssue,
icon: tracker.icon.Issue,
keyBinding: ['keyC'],
input: 'none',
category: tracker.category.Tracker,
target: tracker.class.Issue,
context: {
mode: ['browser'],
application: tracker.app.Tracker,
group: 'create'
}
},
tracker.action.NewSubIssue
)
createAction(
builder,
{
@ -1156,6 +1179,32 @@ export function createModel (builder: Builder): void {
}
})
createAction(builder, {
...actionTemplates.open,
actionProps: {
component: tracker.component.EditIssue
},
target: tracker.class.Issue,
context: {
mode: ['browser', 'context'],
group: 'create'
},
override: [view.action.Open]
})
createAction(builder, {
...actionTemplates.open,
actionProps: {
component: tracker.component.EditIssueTemplate
},
target: tracker.class.IssueTemplate,
context: {
mode: ['browser', 'context'],
group: 'create'
},
override: [view.action.Open]
})
builder.mixin(tracker.class.Issue, core.class.Class, view.mixin.ClassFilters, {
filters: ['status', 'priority', 'assignee', 'project', 'sprint', 'estimation', 'dueDate', 'modifiedOn']
})
@ -1182,6 +1231,27 @@ export function createModel (builder: Builder): void {
sort: { rank: SortingOrder.Ascending }
}
createAction(builder, {
action: view.actionImpl.ShowPopup,
actionProps: {
component: tracker.component.TimeSpendReportPopup,
fillProps: {
_object: 'issue'
}
},
label: tracker.string.TimeSpendReportAdd,
icon: tracker.icon.TimeReport,
input: 'focus',
keyBinding: ['keyT'],
category: tracker.category.Tracker,
target: tracker.class.Issue,
context: {
mode: ['context', 'browser'],
application: tracker.app.Tracker,
group: 'edit'
}
})
createAction(
builder,
{
@ -1198,12 +1268,12 @@ export function createModel (builder: Builder): void {
},
label: tracker.string.Status,
icon: tracker.icon.CategoryBacklog,
keyBinding: [],
input: 'none',
keyBinding: ['keyS->keyS'],
input: 'any',
category: tracker.category.Tracker,
target: tracker.class.Issue,
context: {
mode: ['context'],
mode: ['context', 'browser'],
application: tracker.app.Tracker,
group: 'edit'
}
@ -1222,12 +1292,12 @@ export function createModel (builder: Builder): void {
},
label: tracker.string.Priority,
icon: tracker.icon.PriorityHigh,
keyBinding: [],
input: 'none',
keyBinding: ['keyP-keyR'],
input: 'any',
category: tracker.category.Tracker,
target: tracker.class.Issue,
context: {
mode: ['context'],
mode: ['context', 'browser'],
application: tracker.app.Tracker,
group: 'edit'
}
@ -1247,12 +1317,12 @@ export function createModel (builder: Builder): void {
},
label: tracker.string.Assignee,
icon: contact.icon.Person,
keyBinding: [],
input: 'none',
keyBinding: ['keyA'],
input: 'any',
category: tracker.category.Tracker,
target: tracker.class.Issue,
context: {
mode: ['context'],
mode: ['context', 'browser'],
application: tracker.app.Tracker,
group: 'edit'
}
@ -1274,12 +1344,12 @@ export function createModel (builder: Builder): void {
},
label: tracker.string.Project,
icon: tracker.icon.Project,
keyBinding: [],
input: 'none',
keyBinding: ['keyP->keyP'],
input: 'any',
category: tracker.category.Tracker,
target: tracker.class.Issue,
context: {
mode: ['context'],
mode: ['context', 'browser'],
application: tracker.app.Tracker,
group: 'edit'
}
@ -1307,12 +1377,12 @@ export function createModel (builder: Builder): void {
},
label: tracker.string.Sprint,
icon: tracker.icon.Sprint,
keyBinding: [],
input: 'none',
keyBinding: ['keyS->keyP'],
input: 'any',
category: tracker.category.Tracker,
target: tracker.class.Issue,
context: {
mode: ['context'],
mode: ['context', 'browser'],
application: tracker.app.Tracker,
group: 'edit'
}
@ -1334,8 +1404,8 @@ export function createModel (builder: Builder): void {
},
label: tracker.string.SetDueDate,
icon: tracker.icon.DueDate,
keyBinding: [],
input: 'none',
keyBinding: ['keyD'],
input: 'any',
category: tracker.category.Tracker,
target: tracker.class.Issue,
context: {
@ -1356,7 +1426,7 @@ export function createModel (builder: Builder): void {
label: tracker.string.CopyIssueId,
icon: tracker.icon.CopyID,
keyBinding: [],
input: 'none',
input: 'focus',
category: tracker.category.Tracker,
target: tracker.class.Issue,
context: {
@ -1377,7 +1447,7 @@ export function createModel (builder: Builder): void {
label: tracker.string.CopyIssueTitle,
icon: tracker.icon.CopyBranch,
keyBinding: [],
input: 'none',
input: 'focus',
category: tracker.category.Tracker,
target: tracker.class.Issue,
context: {
@ -1398,7 +1468,7 @@ export function createModel (builder: Builder): void {
label: tracker.string.CopyIssueUrl,
icon: tracker.icon.CopyURL,
keyBinding: [],
input: 'none',
input: 'focus',
category: tracker.category.Tracker,
target: tracker.class.Issue,
context: {
@ -1416,7 +1486,7 @@ export function createModel (builder: Builder): void {
label: tracker.string.MoveToTeam,
icon: view.icon.Move,
keyBinding: [],
input: 'none',
input: 'any',
category: tracker.category.Tracker,
target: tracker.class.Issue,
context: {
@ -1465,7 +1535,7 @@ export function createModel (builder: Builder): void {
label: tracker.string.Duplicate,
icon: tracker.icon.Duplicate,
keyBinding: [],
input: 'none',
input: 'focus',
category: tracker.category.Tracker,
target: tracker.class.Issue,
context: {

View File

@ -41,7 +41,8 @@ export default mergeIds(trackerId, tracker, {
// Required to pass build without errorsF
Nope: '' as AnyComponent,
SprintSelector: '' as AnyComponent,
IssueStatistics: '' as AnyComponent
IssueStatistics: '' as AnyComponent,
TimeSpendReportPopup: '' as AnyComponent
},
app: {
Tracker: '' as Ref<Application>

View File

@ -731,6 +731,17 @@ export function createModel (builder: Builder): void {
target: core.class.Doc,
context: { mode: ['context', 'browser', 'editor'] }
})
createAction(
builder,
{
...actionTemplates.open,
target: core.class.Doc,
category: view.category.Editor,
context: { mode: ['browser', 'context'], group: 'edit' }
},
view.action.Open
)
}
export default view

View File

@ -137,11 +137,6 @@
key.stopPropagation()
handleSelection(key, selection)
}
if (key.code === 'Escape') {
key.preventDefault()
key.stopPropagation()
dispatch('close')
}
}
const manager = createFocusManager()

View File

@ -137,11 +137,6 @@
key.stopPropagation()
handleSelection(key, objects, selection)
}
if (key.code === 'Escape') {
key.preventDefault()
key.stopPropagation()
dispatch('close')
}
}
const manager = createFocusManager()

View File

@ -16,9 +16,9 @@
import type { IntlString } from '@hcengineering/platform'
import { translate } from '@hcengineering/platform'
import { createEventDispatcher, onMount } from 'svelte'
import { deviceOptionsStore, resizeObserver } from '..'
import { getPlatformColor } from '../colors'
import ListView from './ListView.svelte'
import { resizeObserver, deviceOptionsStore } from '..'
export let placeholder: IntlString | undefined = undefined
export let placeholderParam: any | undefined = undefined
@ -62,11 +62,6 @@
key.stopPropagation()
handleSelection(key, selection)
}
if (key.code === 'Escape') {
key.preventDefault()
key.stopPropagation()
dispatch('close')
}
}
let input: HTMLElement
onMount(() => {

View File

@ -16,11 +16,11 @@
import type { IntlString } from '@hcengineering/platform'
import { translate } from '@hcengineering/platform'
import { createEventDispatcher, onMount } from 'svelte'
import type { DropdownTextItem } from '../types'
import { deviceOptionsStore, resizeObserver } from '..'
import plugin from '../plugin'
import type { DropdownTextItem } from '../types'
import CheckBox from './CheckBox.svelte'
import ListView from './ListView.svelte'
import { resizeObserver, deviceOptionsStore } from '..'
export let placeholder: IntlString = plugin.string.SearchDots
export let items: DropdownTextItem[]
@ -76,11 +76,6 @@
key.stopPropagation()
handleSelection(key, selection)
}
if (key.code === 'Escape') {
key.preventDefault()
key.stopPropagation()
dispatch('close')
}
}
function isSelected (

View File

@ -16,11 +16,11 @@
import type { Asset, IntlString } from '@hcengineering/platform'
import { translate } from '@hcengineering/platform'
import { createEventDispatcher, onMount } from 'svelte'
import type { AnySvelteComponent, ListItem } from '../types'
import { deviceOptionsStore, resizeObserver } from '..'
import plugin from '../plugin'
import type { AnySvelteComponent, ListItem } from '../types'
import Icon from './Icon.svelte'
import ListView from './ListView.svelte'
import { resizeObserver, deviceOptionsStore } from '..'
export let icon: Asset | AnySvelteComponent
export let placeholder: IntlString = plugin.string.SearchDots
@ -69,11 +69,6 @@
key.stopPropagation()
handleSelection(key, selection)
}
if (key.code === 'Escape') {
key.preventDefault()
key.stopPropagation()
dispatch('close')
}
}
</script>

View File

@ -15,10 +15,10 @@
<script lang="ts">
import { IntlString } from '@hcengineering/platform'
import { createEventDispatcher } from 'svelte'
import { resizeObserver } from '..'
import CheckBox from './CheckBox.svelte'
import Label from './Label.svelte'
import ListView from './ListView.svelte'
import { resizeObserver } from '..'
export let items: Record<any, IntlString>
export let selected: any | undefined = undefined
@ -51,11 +51,6 @@
key.stopPropagation()
handleSelection(key, selection)
}
if (key.code === 'Escape') {
key.preventDefault()
key.stopPropagation()
dispatch('close')
}
}
</script>

View File

@ -15,15 +15,15 @@
<script lang="ts">
import type { Asset, IntlString } from '@hcengineering/platform'
import { createEventDispatcher } from 'svelte'
import { deviceOptionsStore, resizeObserver } from '..'
import { createFocusManager } from '../focus'
import type { AnySvelteComponent } from '../types'
import EditBox from './EditBox.svelte'
import FocusHandler from './FocusHandler.svelte'
import Icon from './Icon.svelte'
import IconCheck from './icons/Check.svelte'
import Label from './Label.svelte'
import ListView from './ListView.svelte'
import type { AnySvelteComponent } from '../types'
import { resizeObserver, deviceOptionsStore } from '..'
interface ValueType {
id: number | string | null
@ -74,11 +74,6 @@
key.stopPropagation()
dispatch('close', value[selection].id)
}
if (key.code === 'Escape') {
key.preventDefault()
key.stopPropagation()
dispatch('close')
}
}
const manager = createFocusManager()

View File

@ -23,10 +23,11 @@
import { getTimeReportDate, getTimeReportDayType } from '../../../utils'
import TimeReportDayDropdown from './TimeReportDayDropdown.svelte'
export let issueId: Ref<Issue>
export let issueClass: Ref<Class<Issue>>
export let space: Ref<Space>
export let assignee: Ref<Employee> | undefined
export let issue: Issue | undefined = undefined
export let issueId: Ref<Issue> | undefined = issue?._id
export let issueClass: Ref<Class<Issue>> = issue?._class ?? tracker.class.Issue
export let space: Ref<Space> | undefined = issue?.space
export let assignee: Ref<Employee> | null | undefined = issue?.assignee
export let value: TimeSpendReport | undefined
export let placeholder: IntlString = tracker.string.TimeSpendReportValue
@ -45,16 +46,20 @@
return true
}
const client = getClient()
async function create (): Promise<void> {
if (value === undefined) {
getClient().addCollection(
tracker.class.TimeSpendReport,
space,
issueId,
issueClass,
'reports',
data as AttachedData<TimeSpendReport>
)
if (space && issueId) {
await client.addCollection(
tracker.class.TimeSpendReport,
space,
issueId,
issueClass,
'reports',
data as AttachedData<TimeSpendReport>
)
}
} else {
const ops: DocumentUpdate<TimeSpendReport> = {}
if (value.value !== data.value) {
@ -70,15 +75,17 @@
ops.date = data.date
}
if (Object.keys(ops).length > 0) {
getClient().update(value, ops)
await client.update(value, ops)
}
}
}
$: canSave = Number.isFinite(data.value) && data.value !== 0 && space !== undefined && issueId !== undefined
</script>
<Card
label={tracker.string.TimeSpendReportAdd}
canSave={Number.isFinite(data.value) && data.value !== 0}
{canSave}
okAction={create}
on:close
okLabel={value === undefined ? presentation.string.Create : presentation.string.Save}

View File

@ -116,6 +116,7 @@ import StatusRefPresenter from './components/issues/StatusRefPresenter.svelte'
import SprintRefPresenter from './components/sprints/SprintRefPresenter.svelte'
import { EmployeeAccount } from '@hcengineering/contact'
import DeleteProjectPresenter from './components/projects/DeleteProjectPresenter.svelte'
import TimeSpendReportPopup from './components/issues/timereport/TimeSpendReportPopup.svelte'
export { default as SubIssueList } from './components/issues/edit/SubIssueList.svelte'
@ -368,7 +369,8 @@ export default async (): Promise<Resources> => ({
StatusRefPresenter,
RelatedIssuesSection,
RelatedIssueSelector,
DeleteProjectPresenter
DeleteProjectPresenter,
TimeSpendReportPopup
},
completion: {
IssueQuery: async (client: Client, query: string, filter?: { in?: RelatedDocument[], nin?: RelatedDocument[] }) =>

View File

@ -11,7 +11,7 @@ import {
showPanel,
showPopup
} from '@hcengineering/ui'
import { Action, ViewContext } from '@hcengineering/view'
import { ViewContext } from '@hcengineering/view'
import MoveView from './components/Move.svelte'
import { contextStore } from './context'
import view from './plugin'
@ -96,12 +96,13 @@ export function select (evt: Event | undefined, offset: 1 | -1 | 0, of?: Doc, di
}
}
function SelectItem (doc: Doc | undefined, evt: Event): void {
if (doc !== undefined) {
function SelectItem (doc: Doc | Doc[] | undefined, evt: Event): void {
const focus = $focusStore.focus
if (focus !== undefined) {
selectionStore.update((selection) => {
const ind = selection.findIndex((it) => it._id === doc._id)
const ind = selection.findIndex((it) => it._id === focus._id)
if (ind === -1) {
selection.push(doc)
selection.push(focus)
} else {
selection.splice(ind, 1)
}
@ -122,10 +123,10 @@ function SelectItemAll (doc: Doc | undefined, evt: Event): void {
evt.preventDefault()
}
const MoveUp = (doc: Doc | undefined, evt: Event): void => select(evt, -1, doc, 'vertical')
const MoveDown = (doc: Doc | undefined, evt: Event): void => select(evt, 1, doc, 'vertical')
const MoveLeft = (doc: Doc | undefined, evt: Event): void => select(evt, -1, doc, 'horizontal')
const MoveRight = (doc: Doc | undefined, evt: Event): void => select(evt, 1, doc, 'horizontal')
const MoveUp = (doc: Doc | undefined, evt: Event): void => select(evt, -1, $focusStore.focus, 'vertical')
const MoveDown = (doc: Doc | undefined, evt: Event): void => select(evt, 1, $focusStore.focus, 'vertical')
const MoveLeft = (doc: Doc | undefined, evt: Event): void => select(evt, -1, $focusStore.focus, 'horizontal')
const MoveRight = (doc: Doc | undefined, evt: Event): void => select(evt, 1, $focusStore.focus, 'horizontal')
function ShowActions (doc: Doc | Doc[] | undefined, evt: Event): void {
evt.preventDefault()
@ -143,9 +144,17 @@ function ShowPreview (doc: Doc | undefined, evt: Event): void {
evt.preventDefault()
}
function Open (doc: Doc, evt: Event): void {
function Open (
doc: Doc,
evt: Event,
props:
| {
component?: AnyComponent
}
| undefined
): void {
evt.preventDefault()
showPanel(view.component.EditDoc, doc._id, Hierarchy.mixinOrClass(doc), 'content')
showPanel(props?.component ?? view.component.EditDoc, doc._id, Hierarchy.mixinOrClass(doc), 'content')
}
/**
@ -319,7 +328,7 @@ function ValueSelector (
doc: Doc | Doc[],
evt: Event,
props: {
action: Action
actionPopup: AnyComponent
attribute: string
@ -340,9 +349,7 @@ function ValueSelector (
placeholder?: IntlString
}
): void {
if (props.action.actionPopup !== undefined) {
showPopup(props.action.actionPopup, { ...props, ...props.action.actionProps, value: doc, width: 'large' }, 'top')
}
showPopup(view.component.ValueSelector, { ...props, value: doc, width: 'large' }, 'top')
}
async function getPopupAlignment (

View File

@ -148,9 +148,6 @@ export function filterActions (
if (role < AccountRole.Maintainer && action.secured === true) {
continue
}
if (action.override !== undefined) {
overrideRemove.push(...action.override)
}
if (action.query !== undefined) {
const r = matchQuery([doc], action.query, doc._class, hierarchy)
if (r.length === 0) {
@ -161,6 +158,9 @@ export function filterActions (
(hierarchy.isDerived(doc._class, action.target) && client.getHierarchy().isDerived(action.target, derived)) ||
(hierarchy.isMixin(action.target) && hierarchy.hasMixin(doc, action.target))
) {
if (action.override !== undefined) {
overrideRemove.push(...action.override)
}
result.push(action)
}
}

View File

@ -38,6 +38,9 @@
})
let lastKey: KeyboardEvent | undefined
let sequences: Action<Doc, Record<string, any>>[] = []
let delayedAction: (() => Promise<void>) | undefined
let timer: number | undefined
async function getCurrentActions (
context: {
@ -70,23 +73,39 @@
)
}
function m (s1: string, s2: string): boolean {
return s1 === s2.toLowerCase()
return s1 === s2
}
function matchKey (key: KeyboardEvent, pattern: string, lastKey?: KeyboardEvent): boolean {
function findKeySequence (pattern: string, key: KeyboardEvent): boolean {
const lc = pattern.toLowerCase()
const pfp = (keyPrefix(key) + key.key).toLowerCase()
const pfp2 = (keyPrefix(key) + key.code).toLowerCase()
return lc.startsWith(`${pfp}->`) || lc.startsWith(`${pfp2}->`)
}
function getSequences (
key: KeyboardEvent,
currentActions: Action<Doc, Record<string, any>>[]
): Action<Doc, Record<string, any>>[] {
const res = currentActions.filter((p) => p.keyBinding?.find((p) => findKeySequence(p, key)))
return res
}
function matchKeySequence (key: KeyboardEvent, pattern: string, lastKey: KeyboardEvent): boolean {
const fp = (keyPrefix(key) + key.key).toLowerCase()
const fp2 = (keyPrefix(key) + key.code).toLowerCase()
const lc = pattern.toLowerCase()
if (m(fp, lc) || m(fp2, lc)) {
return true
}
if (lastKey !== undefined) {
// Check with last key
const pfp = (keyPrefix(key) + lastKey.key).toLowerCase()
const pfp2 = (keyPrefix(key) + lastKey.code).toLowerCase()
const pfp = (keyPrefix(lastKey) + lastKey.key).toLowerCase()
const pfp2 = (keyPrefix(lastKey) + lastKey.code).toLowerCase()
return m(`${pfp}->${fp}`, lc) || m(`${pfp2}->${fp}`, lc) || m(`${pfp}->${fp2}`, lc) || m(`${pfp2}->${fp2}`, lc)
}
return false
return m(`${pfp}->${fp}`, lc) || m(`${pfp2}->${fp}`, lc) || m(`${pfp}->${fp2}`, lc) || m(`${pfp2}->${fp2}`, lc)
}
function matchKey (key: KeyboardEvent, pattern: string): boolean {
const fp = (keyPrefix(key) + key.key).toLowerCase()
const fp2 = (keyPrefix(key) + key.code).toLowerCase()
const lc = pattern.toLowerCase()
return m(fp, lc) || m(fp2, lc)
}
async function handleKeys (evt: KeyboardEvent): Promise<void> {
@ -114,6 +133,7 @@
if (ctx.mode === 'none') {
return
}
clearTimeout(timer)
const docs = getSelection($focusStore, $selectionStore)
@ -121,22 +141,56 @@
// Retrieve actual list of actions for input context
currentActions = await getContextActions(client, docs, { ...ctx, mode: 'input' })
}
for (const a of currentActions) {
// TODO: Handle multiple keys here
if (a.keyBinding?.find((it) => matchKey(evt, it, lastKey)) !== undefined) {
lastKey = undefined
const action = await getResource(a.action)
if (action !== undefined) {
await action($focusStore.focus, evt, a.actionProps)
currentActions = currentActions.filter((p) => p.keyBinding !== undefined && p.keyBinding.length > 0)
if (lastKey !== undefined) {
for (const a of sequences) {
// TODO: Handle multiple keys here
if (a.keyBinding?.find((it) => (lastKey ? matchKeySequence(evt, it, lastKey) : false)) !== undefined) {
const action = await getResource(a.action)
if (action !== undefined) {
sequences = []
lastKey = undefined
delayedAction = undefined
return await action(docs, evt, a.actionProps)
}
}
}
}
sequences = getSequences(evt, currentActions)
let found = false
for (const a of currentActions) {
// TODO: Handle multiple keys here
if (a.keyBinding?.find((it) => matchKey(evt, it)) !== undefined) {
const action = await getResource(a.action)
if (action !== undefined) {
if (sequences.length === 0) {
lastKey = undefined
sequences = []
delayedAction = undefined
return await action(docs, evt, a.actionProps)
} else {
delayedAction = async () => await action(docs, evt, a.actionProps)
found = true
}
}
}
}
if (!found && delayedAction) {
delayedAction()
delayedAction = undefined
}
lastKey = evt
setTimeout(() => {
timer = setTimeout(() => {
lastKey = undefined
}, 500)
sequences = []
if (delayedAction !== undefined) {
delayedAction()
delayedAction = undefined
}
}, 300)
}
let presenter: AnyComponent | undefined

View File

@ -147,11 +147,6 @@
key.stopPropagation()
handleSelection(key, selection)
}
if (key.code === 'Escape') {
key.preventDefault()
key.stopPropagation()
closePopup()
}
}
function formatKey (key: string): string[][] {
const thens = key.split('->')

View File

@ -33,6 +33,7 @@
const dispatch = createEventDispatcher()
const changeStatus = async (newStatus: any) => {
console.log('CHANGE VALUE', newStatus)
if (newStatus === '#null') {
newStatus = null
return
@ -118,7 +119,10 @@
{#if values}
<SelectPopup
value={valuesToShow}
on:close={(evt) => changeStatus(evt.detail)}
on:close={(evt) => {
console.log(evt)
changeStatus(evt.detail)
}}
placeholder={placeholder ?? view.string.Filter}
searchable
{width}
@ -133,7 +137,10 @@
{searchField}
allowDeselect={true}
selected={current}
on:close={(evt) => changeStatus(evt.detail === null ? null : evt.detail?._id)}
on:close={(evt) => {
console.log(evt)
changeStatus(evt.detail === null ? null : evt.detail?._id)
}}
placeholder={placeholder ?? view.string.Filter}
{width}
{size}