dazscript-framework 0.3.2 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +361 -265
- package/dist/scripts/install-generator.js +85 -14
- package/package.json +7 -4
- package/src/Setup.dsa.ts +37 -9
- package/src/dialog/builders/list-view-builder.ts +5 -0
- package/src/examples/01-hello-world.dsa.ts +8 -0
- package/src/examples/02-persistence-dialog.dsa.ts +21 -0
- package/src/examples/02-persistence-dialog.ts +68 -0
- package/src/examples/03-simple-dialog.dsa.ts +23 -0
- package/src/examples/03-simple-dialog.ts +47 -0
- package/src/examples/04-settings-dialog.dsa.ts +29 -0
- package/src/examples/04-settings-dialog.ts +83 -0
- package/src/examples/05-list-dialog.dsa.ts +53 -0
- package/src/examples/05-list-dialog.ts +88 -0
- package/src/examples/06-showcase-dialog.dsa.ts +87 -0
- package/src/examples/06-showcase-dialog.ts +518 -0
- package/src/helpers/custom-action-helper.ts +2 -1
- package/src/helpers/custom-action-installer-helper.ts +306 -20
- package/src/lib/observable.test.ts +416 -0
- package/src/lib/observable.ts +24 -18
- package/src/lib/tree-node.test.ts +21 -0
- package/tsconfig.json +28 -112
- package/webpack.config.js +7 -0
- package/src/samples/hello-world.dsa.ts +0 -8
- package/src/samples/sample-dialog.dsa.ts +0 -47
- package/src/samples/sample-dialog.ts +0 -49
- /package/src/{samples → examples}/config.ts +0 -0
|
@@ -4,6 +4,7 @@ import { mainWindow } from '@dsf/core/global'
|
|
|
4
4
|
import * as array from '@dsf/helpers/array-helper'
|
|
5
5
|
import { keys } from '@dsf/helpers/object-helper'
|
|
6
6
|
import { progress } from '@dsf/helpers/progress-helper'
|
|
7
|
+
import CustomSet from '@dsf/lib/set'
|
|
7
8
|
import { getMenu } from './menu-helper'
|
|
8
9
|
import { getScriptPath } from './script-helper'
|
|
9
10
|
|
|
@@ -445,7 +446,7 @@ export const installCustomActions = (actions: CustomAction[]) => {
|
|
|
445
446
|
|
|
446
447
|
export const uninstallCustomActions = (actions: CustomAction[]) => {
|
|
447
448
|
debug(`Uninstalling Actions`)
|
|
448
|
-
const toolbarNames = new
|
|
449
|
+
const toolbarNames = new CustomSet<string>()
|
|
449
450
|
|
|
450
451
|
actions.forEach(action => {
|
|
451
452
|
if (!action) return
|
|
@@ -2,14 +2,15 @@ import { debug } from '@dsf/common/log'
|
|
|
2
2
|
import { CustomAction } from '@dsf/core/custom-action'
|
|
3
3
|
import { BasicDialog } from '@dsf/dialog/basic-dialog'
|
|
4
4
|
import { PopupMenuBuilder, PopupMenuItem } from '@dsf/dialog/builders/popup-menu-builder'
|
|
5
|
+
import { findAction, findActionsForShortcut, getActionShortcut, isCustomAction, normalizeShortcut, setActionShortcut } from '@dsf/helpers/action-helper'
|
|
5
6
|
import { addToToolbar, applyCustomActionTargets, cleanupEmptyToolbar, clearToolbar, getInstalledCustomActionState, removeCustomActionTargets } from '@dsf/helpers/custom-action-helper'
|
|
6
7
|
import { checkAll, getDataItem } from '@dsf/helpers/list-view-helper'
|
|
7
|
-
import { normalizeShortcut, setActionShortcut } from '@dsf/helpers/action-helper'
|
|
8
8
|
import { progress } from '@dsf/helpers/progress-helper'
|
|
9
9
|
import { Observable } from '@dsf/lib/observable'
|
|
10
10
|
import CustomSet from '@dsf/lib/set'
|
|
11
11
|
import { TreeNode } from '@dsf/lib/tree-node'
|
|
12
12
|
import { promptKeyboardShortcut } from '@dsf/shared/set-keyboard-shortcut'
|
|
13
|
+
import { readFromFile, saveToFile } from './file-helper'
|
|
13
14
|
|
|
14
15
|
type InstallerEntry = {
|
|
15
16
|
action: CustomAction
|
|
@@ -28,6 +29,45 @@ type InstallerEntry = {
|
|
|
28
29
|
type SetupDialogOptions = {
|
|
29
30
|
settingsPath: string
|
|
30
31
|
bundleName?: string
|
|
32
|
+
shortcuts?: ActionAccelerator[]
|
|
33
|
+
shortcutsSourcePath?: string
|
|
34
|
+
shortcutBackupPath?: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
type ActionAccelerator = {
|
|
38
|
+
name?: string
|
|
39
|
+
action?: string
|
|
40
|
+
text?: string
|
|
41
|
+
label?: string
|
|
42
|
+
shortcut?: string
|
|
43
|
+
accelerator?: string
|
|
44
|
+
key?: string
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
type ShortcutEntry = {
|
|
48
|
+
selected: boolean
|
|
49
|
+
name: string
|
|
50
|
+
label: string
|
|
51
|
+
currentShortcut: string
|
|
52
|
+
newShortcut: string
|
|
53
|
+
conflictText: string
|
|
54
|
+
exists: boolean
|
|
55
|
+
isCustom: boolean
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
type ShortcutBackupEntry = {
|
|
59
|
+
name: string
|
|
60
|
+
shortcut: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
type ShortcutBackupFile = {
|
|
64
|
+
version: number
|
|
65
|
+
shortcuts: ShortcutBackupEntry[]
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
type SetupSelection = {
|
|
69
|
+
actions: InstallerEntry[]
|
|
70
|
+
shortcuts: ShortcutEntry[]
|
|
31
71
|
}
|
|
32
72
|
|
|
33
73
|
const OVERRIDE_MARKER = '[ovr]'
|
|
@@ -37,6 +77,15 @@ const toKey = (action: CustomAction): string => String(action.filePath ?? action
|
|
|
37
77
|
const toTreeNode = (entry: InstallerEntry): TreeNode<InstallerEntry> =>
|
|
38
78
|
new TreeNode(String(entry.action.text), toKey(entry.action), entry)
|
|
39
79
|
|
|
80
|
+
const toShortcutTreeNode = (entry: ShortcutEntry): TreeNode<ShortcutEntry> =>
|
|
81
|
+
new TreeNode(entry.label, entry.name, entry)
|
|
82
|
+
|
|
83
|
+
const getEntry = (item: TreeNode<InstallerEntry>): InstallerEntry =>
|
|
84
|
+
item.value as InstallerEntry
|
|
85
|
+
|
|
86
|
+
const getShortcutEntry = (item: TreeNode<ShortcutEntry>): ShortcutEntry =>
|
|
87
|
+
item.value as ShortcutEntry
|
|
88
|
+
|
|
40
89
|
const getDisplayedToolbar = (entry: InstallerEntry): string => String(entry.action.toolbar ?? '')
|
|
41
90
|
|
|
42
91
|
const getSetupDialogOptions = (options: string | SetupDialogOptions): SetupDialogOptions =>
|
|
@@ -44,6 +93,9 @@ const getSetupDialogOptions = (options: string | SetupDialogOptions): SetupDialo
|
|
|
44
93
|
? { settingsPath: options }
|
|
45
94
|
: options
|
|
46
95
|
|
|
96
|
+
const getShortcutBackupPath = (options: SetupDialogOptions): string =>
|
|
97
|
+
`${App.getAppDataPath()}/${options.shortcutBackupPath ?? `${options.settingsPath}/keyboard-shortcuts-backup.json`}`
|
|
98
|
+
|
|
47
99
|
const getDisplayedShortcut = (entry: InstallerEntry): string => {
|
|
48
100
|
if (!entry.isShortcutOverridden) return entry.effectiveShortcut
|
|
49
101
|
return entry.effectiveShortcut
|
|
@@ -85,15 +137,66 @@ const buildEntries = (actions: CustomAction[]): InstallerEntry[] => {
|
|
|
85
137
|
})
|
|
86
138
|
}
|
|
87
139
|
|
|
140
|
+
const normalizeAccelerator = (accelerator: ActionAccelerator): { name: string, label: string, shortcut: string } | null => {
|
|
141
|
+
const name = String(accelerator.name ?? accelerator.action ?? '').trim()
|
|
142
|
+
const shortcut = normalizeShortcut(String(accelerator.shortcut ?? accelerator.accelerator ?? accelerator.key ?? '').trim())
|
|
143
|
+
if (!name || !shortcut) return null
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
name,
|
|
147
|
+
label: String(accelerator.text ?? accelerator.label ?? name),
|
|
148
|
+
shortcut
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const getShortcutConflictText = (name: string, shortcut: string): string => {
|
|
153
|
+
if (!shortcut) return ''
|
|
154
|
+
|
|
155
|
+
const conflicts = findActionsForShortcut(shortcut)
|
|
156
|
+
.filter(action => action && action.name !== name)
|
|
157
|
+
|
|
158
|
+
return conflicts.map(action => String(action.text || action.name)).join(', ')
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const buildShortcutEntries = (accelerators: ActionAccelerator[] = []): ShortcutEntry[] => {
|
|
162
|
+
return accelerators
|
|
163
|
+
.map(normalizeAccelerator)
|
|
164
|
+
.filter((accelerator): accelerator is { name: string, label: string, shortcut: string } => accelerator !== null)
|
|
165
|
+
.map((accelerator) => {
|
|
166
|
+
const action = findAction(accelerator.name)
|
|
167
|
+
const currentShortcut = getActionShortcut(accelerator.name)
|
|
168
|
+
const newShortcut = normalizeShortcut(accelerator.shortcut)
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
selected: true,
|
|
172
|
+
name: accelerator.name,
|
|
173
|
+
label: action?.text ? String(action.text) : accelerator.label,
|
|
174
|
+
currentShortcut,
|
|
175
|
+
newShortcut,
|
|
176
|
+
conflictText: getShortcutConflictText(accelerator.name, newShortcut),
|
|
177
|
+
exists: action !== null,
|
|
178
|
+
isCustom: action ? isCustomAction(action) : false
|
|
179
|
+
}
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
|
|
88
183
|
class InstallerSelectionDialog extends BasicDialog {
|
|
89
184
|
private readonly keywords$ = new Observable('')
|
|
90
185
|
private readonly items$: Observable<TreeNode<InstallerEntry>[]>
|
|
186
|
+
private readonly shortcutKeywords$ = new Observable('')
|
|
187
|
+
private readonly shortcutItems$: Observable<TreeNode<ShortcutEntry>[]>
|
|
91
188
|
private readonly refreshListEvent$ = new Observable<void>()
|
|
92
189
|
private listView: DzListView | null = null
|
|
190
|
+
private shortcutListView: DzListView | null = null
|
|
93
191
|
|
|
94
|
-
constructor(
|
|
192
|
+
constructor(
|
|
193
|
+
private readonly entries: InstallerEntry[],
|
|
194
|
+
private readonly shortcutEntries: ShortcutEntry[],
|
|
195
|
+
bundleName?: string
|
|
196
|
+
) {
|
|
95
197
|
super(bundleName ? `${bundleName} Setup` : 'Setup Scripts', 'dsfSetupScripts')
|
|
96
198
|
this.items$ = new Observable(entries.map(toTreeNode))
|
|
199
|
+
this.shortcutItems$ = new Observable(shortcutEntries.map(toShortcutTreeNode))
|
|
97
200
|
}
|
|
98
201
|
|
|
99
202
|
protected build(): void {
|
|
@@ -101,7 +204,28 @@ class InstallerSelectionDialog extends BasicDialog {
|
|
|
101
204
|
this.dialog.setAcceptButtonText('Apply')
|
|
102
205
|
this.dialog.setCancelButtonText('Cancel')
|
|
103
206
|
|
|
207
|
+
if (this.shortcutEntries.length > 0) {
|
|
208
|
+
const add = this.add
|
|
209
|
+
add.tab('Scripts').build(() => this.buildScriptsTab())
|
|
210
|
+
add.tab('Keyboard Shortcuts').build(() => this.buildShortcutsTab())
|
|
211
|
+
return
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
this.buildScriptsTab()
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
getSelections(): SetupSelection {
|
|
218
|
+
this.syncSelectionsFromListView()
|
|
219
|
+
this.syncShortcutSelectionsFromListView()
|
|
220
|
+
return {
|
|
221
|
+
actions: this.entries,
|
|
222
|
+
shortcuts: this.shortcutEntries
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private buildScriptsTab(): void {
|
|
104
227
|
const add = this.add
|
|
228
|
+
|
|
105
229
|
add.label('Choose which scripts to install, then use the columns to review their shortcut, menu, and toolbar targets.')
|
|
106
230
|
.wordWrap()
|
|
107
231
|
.build()
|
|
@@ -123,8 +247,9 @@ class InstallerSelectionDialog extends BasicDialog {
|
|
|
123
247
|
.sortOnBuild(true)
|
|
124
248
|
.refresh(this.refreshListEvent$)
|
|
125
249
|
.row((item, parent, id) => {
|
|
250
|
+
const entry = getEntry(item)
|
|
126
251
|
const listItem = new DzCheckListItem(parent, DzCheckListItem.CheckBox, id)
|
|
127
|
-
listItem.on =
|
|
252
|
+
listItem.on = entry.selected
|
|
128
253
|
listItem.setText(0, '')
|
|
129
254
|
return listItem
|
|
130
255
|
})
|
|
@@ -139,15 +264,18 @@ class InstallerSelectionDialog extends BasicDialog {
|
|
|
139
264
|
if (index === 5) return Math.max(width * 1.2, 140)
|
|
140
265
|
return width
|
|
141
266
|
})
|
|
142
|
-
.text((item) =>
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
267
|
+
.text((item) => {
|
|
268
|
+
const entry = getEntry(item)
|
|
269
|
+
return [
|
|
270
|
+
'',
|
|
271
|
+
String(entry.action.text ?? ''),
|
|
272
|
+
getDisplayedShortcut(entry),
|
|
273
|
+
String(entry.action.description ?? ''),
|
|
274
|
+
String(entry.action.menuPath ?? ''),
|
|
275
|
+
getDisplayedToolbar(entry),
|
|
276
|
+
]
|
|
277
|
+
})
|
|
278
|
+
.data((item) => getEntry(item))
|
|
151
279
|
.filter({
|
|
152
280
|
keywords: this.keywords$,
|
|
153
281
|
field: (listItem) => [
|
|
@@ -165,9 +293,71 @@ class InstallerSelectionDialog extends BasicDialog {
|
|
|
165
293
|
})
|
|
166
294
|
}
|
|
167
295
|
|
|
168
|
-
|
|
169
|
-
this.
|
|
170
|
-
|
|
296
|
+
private buildShortcutsTab(): void {
|
|
297
|
+
const add = this.add
|
|
298
|
+
|
|
299
|
+
add.label('Choose which keyboard shortcuts to apply. Current and new shortcut values are shown side by side.')
|
|
300
|
+
.wordWrap()
|
|
301
|
+
.build()
|
|
302
|
+
add.group('Search').horizontal().build(() => {
|
|
303
|
+
add.edit()
|
|
304
|
+
.value(this.shortcutKeywords$)
|
|
305
|
+
.placeholder('Search shortcuts...')
|
|
306
|
+
.toolTip('Search by action name, current shortcut, new shortcut, status, or conflicts.')
|
|
307
|
+
add.button('Select All').clicked(() => this.setVisibleShortcutSelections(true))
|
|
308
|
+
add.button('Deselect All').clicked(() => this.setVisibleShortcutSelections(false))
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
add.group('Keyboard Shortcuts')
|
|
312
|
+
.style({ flat: true })
|
|
313
|
+
.build(() => {
|
|
314
|
+
add.list.view<ShortcutEntry, ShortcutEntry>()
|
|
315
|
+
.sorting(true)
|
|
316
|
+
.sortOnBuild(true)
|
|
317
|
+
.row((item, parent, id) => {
|
|
318
|
+
const entry = getShortcutEntry(item)
|
|
319
|
+
const listItem = new DzCheckListItem(parent, DzCheckListItem.CheckBox, id)
|
|
320
|
+
listItem.on = entry.selected
|
|
321
|
+
listItem.setText(0, '')
|
|
322
|
+
return listItem
|
|
323
|
+
})
|
|
324
|
+
.items(this.shortcutItems$)
|
|
325
|
+
.columns(['Apply', 'Action', 'Current', 'New', 'Status', 'Conflicts'], (index, width) => {
|
|
326
|
+
if (index === 0) return Math.max(width, 70)
|
|
327
|
+
if (index === 1) return Math.max(width * 2, 260)
|
|
328
|
+
if (index === 2) return Math.max(width, 130)
|
|
329
|
+
if (index === 3) return Math.max(width, 130)
|
|
330
|
+
if (index === 4) return Math.max(width, 120)
|
|
331
|
+
if (index === 5) return Math.max(width * 2, 260)
|
|
332
|
+
return width
|
|
333
|
+
})
|
|
334
|
+
.text((item) => {
|
|
335
|
+
const entry = getShortcutEntry(item)
|
|
336
|
+
return [
|
|
337
|
+
'',
|
|
338
|
+
entry.label,
|
|
339
|
+
entry.currentShortcut || '(none)',
|
|
340
|
+
entry.newShortcut || '(none)',
|
|
341
|
+
entry.exists ? (entry.isCustom ? 'Custom Action' : 'DAZ Action') : 'Not currently found',
|
|
342
|
+
entry.conflictText || ''
|
|
343
|
+
]
|
|
344
|
+
})
|
|
345
|
+
.data((item) => getShortcutEntry(item))
|
|
346
|
+
.filter({
|
|
347
|
+
keywords: this.shortcutKeywords$,
|
|
348
|
+
field: (listItem) => [
|
|
349
|
+
listItem.text(1),
|
|
350
|
+
listItem.text(2),
|
|
351
|
+
listItem.text(3),
|
|
352
|
+
listItem.text(4),
|
|
353
|
+
listItem.text(5),
|
|
354
|
+
].join(' ')
|
|
355
|
+
})
|
|
356
|
+
.build((listView) => {
|
|
357
|
+
this.shortcutListView = listView
|
|
358
|
+
listView.allColumnsShowFocus = true
|
|
359
|
+
})
|
|
360
|
+
})
|
|
171
361
|
}
|
|
172
362
|
|
|
173
363
|
private buildContextMenu(listView: DzListView, listItem: DzListViewItem | null): DzPopupMenu {
|
|
@@ -274,24 +464,106 @@ class InstallerSelectionDialog extends BasicDialog {
|
|
|
274
464
|
}
|
|
275
465
|
})
|
|
276
466
|
}
|
|
467
|
+
|
|
468
|
+
private setVisibleShortcutSelections(onOff: boolean) {
|
|
469
|
+
if (!this.shortcutListView) return
|
|
470
|
+
this.checkShortcutVisible(this.shortcutListView, onOff)
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
private checkShortcutVisible(listView: DzListView, onOff: boolean) {
|
|
474
|
+
if (!this.shortcutKeywords$.value?.trim()) {
|
|
475
|
+
checkAll(listView, onOff)
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
listView.getItems(DzListView.All).forEach((item) => {
|
|
479
|
+
if (!item.visible || !(item as any).inherits('DzCheckListItem')) return
|
|
480
|
+
|
|
481
|
+
const checkbox = item as DzCheckListItem
|
|
482
|
+
checkbox.on = onOff
|
|
483
|
+
|
|
484
|
+
const data = getDataItem<ShortcutEntry>(item)
|
|
485
|
+
if (!data) return
|
|
486
|
+
data.selected = onOff
|
|
487
|
+
})
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
private syncShortcutSelectionsFromListView() {
|
|
491
|
+
if (!this.shortcutListView) return
|
|
492
|
+
|
|
493
|
+
const selectionByName: Record<string, boolean> = {}
|
|
494
|
+
|
|
495
|
+
this.shortcutListView.getItems(DzListView.All).forEach((item) => {
|
|
496
|
+
if (!(item as any).inherits('DzCheckListItem')) return
|
|
497
|
+
|
|
498
|
+
const data = getDataItem<ShortcutEntry>(item)
|
|
499
|
+
if (!data) return
|
|
500
|
+
|
|
501
|
+
const checkbox = item as DzCheckListItem
|
|
502
|
+
const selected = !(checkbox.state === 0 && !checkbox.on)
|
|
503
|
+
selectionByName[data.name] = selected
|
|
504
|
+
})
|
|
505
|
+
|
|
506
|
+
this.shortcutEntries.forEach((entry) => {
|
|
507
|
+
if (Object.prototype.hasOwnProperty.call(selectionByName, entry.name)) {
|
|
508
|
+
entry.selected = selectionByName[entry.name]
|
|
509
|
+
}
|
|
510
|
+
})
|
|
511
|
+
}
|
|
277
512
|
}
|
|
278
513
|
|
|
279
|
-
const runDialog = (actions: CustomAction[], options: SetupDialogOptions):
|
|
514
|
+
const runDialog = (actions: CustomAction[], options: SetupDialogOptions): SetupSelection | null => {
|
|
280
515
|
const entries = buildEntries(actions)
|
|
281
|
-
const
|
|
516
|
+
const shortcutEntries = buildShortcutEntries(options.shortcuts)
|
|
517
|
+
const dialog = new InstallerSelectionDialog(entries, shortcutEntries, options.bundleName)
|
|
282
518
|
return dialog.ok() ? dialog.getSelections() : null
|
|
283
519
|
}
|
|
284
520
|
|
|
521
|
+
const readShortcutBackup = (backupPath: string): ShortcutBackupFile => {
|
|
522
|
+
const backup = readFromFile<ShortcutBackupFile>(backupPath)
|
|
523
|
+
return backup ?? { version: 1, shortcuts: [] }
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const saveShortcutBackup = (backupPath: string, backup: ShortcutBackupFile): void => {
|
|
527
|
+
saveToFile(backupPath, JSON.stringify(backup, null, 2))
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
const backupCurrentShortcut = (entry: ShortcutEntry, backupPath: string): void => {
|
|
531
|
+
const action = findAction(entry.name)
|
|
532
|
+
if (!action || isCustomAction(action)) return
|
|
533
|
+
|
|
534
|
+
const backup = readShortcutBackup(backupPath)
|
|
535
|
+
const alreadyBackedUp = backup.shortcuts.some(shortcut => shortcut.name === entry.name)
|
|
536
|
+
if (alreadyBackedUp) return
|
|
537
|
+
|
|
538
|
+
backup.shortcuts.push({
|
|
539
|
+
name: entry.name,
|
|
540
|
+
shortcut: getActionShortcut(entry.name)
|
|
541
|
+
})
|
|
542
|
+
saveShortcutBackup(backupPath, backup)
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
const applyKeyboardShortcuts = (shortcuts: ShortcutEntry[], options: SetupDialogOptions): void => {
|
|
546
|
+
const selected = shortcuts.filter(shortcut => shortcut.selected)
|
|
547
|
+
if (selected.length === 0) return
|
|
548
|
+
|
|
549
|
+
const backupPath = getShortcutBackupPath(options)
|
|
550
|
+
|
|
551
|
+
progress('Applying Keyboard Shortcuts', selected, (shortcut) => {
|
|
552
|
+
backupCurrentShortcut(shortcut, backupPath)
|
|
553
|
+
setActionShortcut(shortcut.name, shortcut.newShortcut)
|
|
554
|
+
})
|
|
555
|
+
}
|
|
556
|
+
|
|
285
557
|
export const showSetupCustomActionsDialog = (actions: CustomAction[], options: string | SetupDialogOptions) => {
|
|
286
558
|
const settings = getSetupDialogOptions(options)
|
|
287
559
|
const selections = runDialog(actions, settings)
|
|
288
560
|
if (!selections) return
|
|
289
561
|
|
|
290
|
-
debug(`[Setup] applying ${selections.filter(selection => selection.selected).length}/${selections.length} selected actions`)
|
|
562
|
+
debug(`[Setup] applying ${selections.actions.filter(selection => selection.selected).length}/${selections.actions.length} selected actions`)
|
|
291
563
|
|
|
292
564
|
const removedToolbarNames = new CustomSet<string>()
|
|
293
565
|
|
|
294
|
-
progress('Setting Up Scripts', selections, (selection) => {
|
|
566
|
+
progress('Setting Up Scripts', selections.actions, (selection) => {
|
|
295
567
|
debug(`[Setup] ${selection.selected ? 'install' : 'remove'} "${selection.action.text}"`)
|
|
296
568
|
|
|
297
569
|
if (selection.selected) {
|
|
@@ -318,7 +590,7 @@ export const showSetupCustomActionsDialog = (actions: CustomAction[], options: s
|
|
|
318
590
|
removedToolbarNames.forEach((toolbarName) => {
|
|
319
591
|
clearToolbar(toolbarName)
|
|
320
592
|
|
|
321
|
-
const stillSelected = selections.filter(s => s.selected && s.supportsToolbar && s.action.toolbar === toolbarName)
|
|
593
|
+
const stillSelected = selections.actions.filter(s => s.selected && s.supportsToolbar && s.action.toolbar === toolbarName)
|
|
322
594
|
stillSelected.forEach((s) => addToToolbar({
|
|
323
595
|
...s.action,
|
|
324
596
|
shortcut: s.effectiveShortcut
|
|
@@ -329,4 +601,18 @@ export const showSetupCustomActionsDialog = (actions: CustomAction[], options: s
|
|
|
329
601
|
cleanupEmptyToolbar(toolbarName)
|
|
330
602
|
}
|
|
331
603
|
})
|
|
604
|
+
|
|
605
|
+
applyKeyboardShortcuts(selections.shortcuts, settings)
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
export const restoreSetupKeyboardShortcuts = (options: string | SetupDialogOptions) => {
|
|
609
|
+
const settings = getSetupDialogOptions(options)
|
|
610
|
+
const backupPath = getShortcutBackupPath(settings)
|
|
611
|
+
const backup = readFromFile<ShortcutBackupFile>(backupPath)
|
|
612
|
+
if (!backup || !backup.shortcuts || backup.shortcuts.length === 0) return
|
|
613
|
+
|
|
614
|
+
progress('Restoring Keyboard Shortcuts', backup.shortcuts, (shortcut) => {
|
|
615
|
+
if (!shortcut.name) return
|
|
616
|
+
setActionShortcut(shortcut.name, shortcut.shortcut ?? '')
|
|
617
|
+
})
|
|
332
618
|
}
|