dazscript-framework 0.1.15 → 0.1.17

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.
Files changed (82) hide show
  1. package/README.md +365 -93
  2. package/babel.config.js +33 -33
  3. package/dist/babel/trace-babel-plugin.js +243 -243
  4. package/dist/babel/trace-log-babel-plugin.js +164 -164
  5. package/dist/scripts/install-generator.js +185 -185
  6. package/package.json +72 -70
  7. package/src/common/dz-dump.ts +120 -120
  8. package/src/common/log.ts +56 -56
  9. package/src/common/trace.ts +26 -26
  10. package/src/core/action-decorator.ts +15 -15
  11. package/src/core/base-script.ts +30 -30
  12. package/src/core/custom-action.ts +11 -11
  13. package/src/core/global.ts +4 -4
  14. package/src/dialog/basic-dialog.ts +40 -32
  15. package/src/dialog/builders/button-builder.ts +52 -52
  16. package/src/dialog/builders/checkbox-builder.ts +29 -29
  17. package/src/dialog/builders/color-picker-builder.ts +35 -35
  18. package/src/dialog/builders/combo-box-builder.ts +38 -35
  19. package/src/dialog/builders/combo-edit-builder.ts +35 -35
  20. package/src/dialog/builders/dialog-builder.ts +49 -49
  21. package/src/dialog/builders/groupbox-builder.ts +121 -82
  22. package/src/dialog/builders/label-builder.ts +33 -28
  23. package/src/dialog/builders/layout-builder.ts +59 -59
  24. package/src/dialog/builders/line-edit-builder.ts +124 -119
  25. package/src/dialog/builders/list-box-builder.ts +103 -0
  26. package/src/dialog/builders/list-view-builder.ts +396 -328
  27. package/src/dialog/builders/node-selection-builder.ts +55 -55
  28. package/src/dialog/builders/path-combo-box-builder.ts +24 -24
  29. package/src/dialog/builders/popup-menu-builder.ts +46 -46
  30. package/src/dialog/builders/radio-builder.ts +42 -42
  31. package/src/dialog/builders/slider-builder.ts +39 -22
  32. package/src/dialog/builders/splitter-builder.ts +88 -88
  33. package/src/dialog/builders/tab-builder.ts +120 -106
  34. package/src/dialog/builders/widget-builder.ts +136 -124
  35. package/src/dialog/builders/widgets-builder.ts +140 -135
  36. package/src/dialog/input-dialog.ts +30 -27
  37. package/src/dialog/input-validator.ts +8 -8
  38. package/src/dialog/selection-dialog.ts +47 -0
  39. package/src/dialog/shared.ts +8 -8
  40. package/src/helpers/action-helper.ts +214 -81
  41. package/src/helpers/array-helper.ts +170 -145
  42. package/src/helpers/camera-helper.ts +12 -12
  43. package/src/helpers/custom-action-helper.ts +176 -176
  44. package/src/helpers/directory-helper.ts +14 -0
  45. package/src/helpers/file-helper.ts +90 -90
  46. package/src/helpers/http-helper.ts +190 -0
  47. package/src/helpers/input-helper.ts +18 -18
  48. package/src/helpers/list-view-helper.ts +105 -89
  49. package/src/helpers/menu-helper.ts +28 -28
  50. package/src/helpers/message-box-helper.ts +25 -15
  51. package/src/helpers/node-helper.ts +461 -236
  52. package/src/helpers/number-helper.ts +10 -10
  53. package/src/helpers/numeric-property-helper.ts +91 -91
  54. package/src/helpers/object-helper.ts +2 -2
  55. package/src/helpers/pane-helper.ts +28 -20
  56. package/src/helpers/progress-helper.ts +51 -33
  57. package/src/helpers/property-helper.ts +61 -52
  58. package/src/helpers/record-helper.ts +16 -16
  59. package/src/helpers/scene-helper.ts +144 -94
  60. package/src/helpers/script-helper.ts +15 -15
  61. package/src/helpers/skeleton-helper.ts +26 -26
  62. package/src/helpers/splitter-helper.ts +8 -8
  63. package/src/helpers/string-helper.ts +39 -31
  64. package/src/helpers/surface-helper.ts +5 -5
  65. package/src/helpers/undo-helper.ts +8 -8
  66. package/src/helpers/viewport-helper.ts +21 -8
  67. package/src/lib/delayed.ts +38 -38
  68. package/src/lib/dictionary.ts +3 -0
  69. package/src/lib/frame-keys.ts +67 -67
  70. package/src/lib/guid.ts +2 -2
  71. package/src/lib/menu-item.ts +10 -9
  72. package/src/lib/observable.ts +147 -94
  73. package/src/lib/set.ts +50 -25
  74. package/src/lib/settings.ts +112 -104
  75. package/src/lib/tree-node.ts +149 -145
  76. package/src/samples/config.ts +2 -2
  77. package/src/samples/hello-world.dsa.ts +12 -12
  78. package/src/samples/sample-dialog.dsa.ts +51 -51
  79. package/src/samples/sample-dialog.ts +48 -48
  80. package/src/shared/set-keyboard-shortcut.ts +146 -102
  81. package/tsconfig.json +116 -116
  82. package/webpack.config.js +70 -70
@@ -0,0 +1,190 @@
1
+ import * as log from '@dsf/common/log'
2
+
3
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD'
4
+ export type HttpConnectionMode = 'http' | 'https'
5
+ export type HttpResponseType = 'json' | 'text' | 'bytes'
6
+
7
+ export interface HttpAuthOptions {
8
+ basic?: {
9
+ username: string
10
+ password: string
11
+ }
12
+ bearerToken?: string
13
+ }
14
+
15
+ export interface HttpRequestOptions {
16
+ host: string
17
+ path: string
18
+ method?: HttpMethod
19
+ connectionMode?: HttpConnectionMode
20
+ timeoutMs?: number
21
+ responseType?: HttpResponseType
22
+ queryString?: string
23
+ headers?: Record<string, string>
24
+ contentType?: string
25
+ body?: string | ByteArray | object
26
+ auth?: HttpAuthOptions
27
+ transport?: any
28
+ }
29
+
30
+ export interface HttpResponse<T = any> {
31
+ ok: boolean
32
+ bytes: ByteArray
33
+ text: string
34
+ data: T | null
35
+ error: string
36
+ parseError: string
37
+ }
38
+
39
+ export const basicAuth = (username: string, password: string): string => {
40
+ const credentials = new ByteArray(username + ':' + password)
41
+ const encoded = credentials.toBase64().convertToString()
42
+ return 'Basic ' + encoded.replace(/\r|\n/g, '')
43
+ }
44
+
45
+ export const bearerAuth = (token: string): string => {
46
+ return 'Bearer ' + token
47
+ }
48
+
49
+ export const request = <T = any>(options: HttpRequestOptions): HttpResponse<T> => {
50
+ const emptyBytes = new ByteArray()
51
+ const emptyResponse: HttpResponse<T> = {
52
+ ok: false,
53
+ bytes: emptyBytes,
54
+ text: '',
55
+ data: null,
56
+ error: '',
57
+ parseError: ''
58
+ }
59
+
60
+ if (!options || !options.host || !options.path) {
61
+ return {
62
+ ...emptyResponse,
63
+ error: 'Http request requires host and path.'
64
+ }
65
+ }
66
+
67
+ // Parse host:port format
68
+ let hostOnly = options.host
69
+ let port = 0
70
+ const colonIdx = options.host.indexOf(':')
71
+ if (colonIdx > 0) {
72
+ hostOnly = options.host.substring(0, colonIdx)
73
+ const portStr = options.host.substring(colonIdx + 1)
74
+ port = parseInt(portStr)
75
+ }
76
+
77
+ const http = options.transport ?? new DzHttpHelper()
78
+ http.setConnectionMode(options.connectionMode ?? 'https')
79
+ http.setHost(hostOnly)
80
+ if (typeof http.setTimeoutMs === 'function' && options.timeoutMs && options.timeoutMs > 0) {
81
+ http.setTimeoutMs(options.timeoutMs)
82
+ }
83
+ if (port > 0) {
84
+ http.setPort(port)
85
+ }
86
+ http.setPath(options.path)
87
+ http.setRequestMethod(options.method ?? 'GET')
88
+
89
+ if (options.queryString) {
90
+ http.setQueryString(options.queryString)
91
+ }
92
+
93
+ const headers = buildHeaders(options)
94
+ const keys = Object.keys(headers)
95
+ if (keys.length > 0) {
96
+ const values: string[] = []
97
+ for (let i = 0; i < keys.length; i++) {
98
+ values.push(headers[keys[i]])
99
+ }
100
+ http.setHeaderValues(keys, values)
101
+ }
102
+
103
+ try {
104
+ const requestBody = buildRequestBody(options)
105
+ // buildRequestBody may set options.contentType to 'application/json' as a side
106
+ // effect when body is an object — so setContentType must come after
107
+ if (options.contentType) {
108
+ http.setContentType(options.contentType)
109
+ }
110
+ const bytes = requestBody ? http.doSynchronousRequest(requestBody) : http.doSynchronousRequest()
111
+ const error = http.getError()
112
+ const text = bytes ? bytes.convertToStringFromUtf8() : ''
113
+ const responseType = options.responseType ?? 'json'
114
+
115
+ let parseError = ''
116
+ let data: T | null = null
117
+
118
+ if (responseType === 'json' && text) {
119
+ try {
120
+ data = JSON.parse(text) as T
121
+ } catch (e) {
122
+ parseError = 'Json parse error: ' + e
123
+ }
124
+ }
125
+
126
+ return {
127
+ ok: !error && !parseError,
128
+ bytes: bytes,
129
+ text: text,
130
+ data: data,
131
+ error: error,
132
+ parseError: parseError
133
+ }
134
+ } catch (e) {
135
+ const exceptionText = 'Http request exception: ' + e
136
+ log.error(exceptionText)
137
+ return {
138
+ ...emptyResponse,
139
+ error: exceptionText
140
+ }
141
+ }
142
+ }
143
+
144
+ export const get = <T = any>(options: Omit<HttpRequestOptions, 'method'>): HttpResponse<T> => {
145
+ return request({ ...options, method: 'GET' })
146
+ }
147
+
148
+ export const post = <T = any>(options: Omit<HttpRequestOptions, 'method'>): HttpResponse<T> => {
149
+ return request({ ...options, method: 'POST' })
150
+ }
151
+
152
+ export const put = <T = any>(options: Omit<HttpRequestOptions, 'method'>): HttpResponse<T> => {
153
+ return request({ ...options, method: 'PUT' })
154
+ }
155
+
156
+ export const patch = <T = any>(options: Omit<HttpRequestOptions, 'method'>): HttpResponse<T> => {
157
+ return request({ ...options, method: 'PATCH' })
158
+ }
159
+
160
+ export const del = <T = any>(options: Omit<HttpRequestOptions, 'method'>): HttpResponse<T> => {
161
+ return request({ ...options, method: 'DELETE' })
162
+ }
163
+
164
+ export const head = <T = any>(options: Omit<HttpRequestOptions, 'method'>): HttpResponse<T> => {
165
+ return request({ ...options, method: 'HEAD' })
166
+ }
167
+
168
+ const buildRequestBody = (options: HttpRequestOptions): ByteArray | undefined => {
169
+ if (options.body == null) return undefined
170
+ if (typeof options.body === 'string') return new ByteArray(options.body)
171
+ if (options.body instanceof ByteArray) return options.body
172
+
173
+ if (!options.contentType) {
174
+ options.contentType = 'application/json'
175
+ }
176
+
177
+ return new ByteArray(JSON.stringify(options.body))
178
+ }
179
+
180
+ const buildHeaders = (options: HttpRequestOptions): Record<string, string> => {
181
+ const headers = { ...(options.headers ?? {}) }
182
+
183
+ if (options.auth?.bearerToken) {
184
+ headers.Authorization = bearerAuth(options.auth.bearerToken)
185
+ } else if (options.auth?.basic && !headers.Authorization) {
186
+ headers.Authorization = basicAuth(options.auth.basic.username, options.auth.basic.password)
187
+ }
188
+
189
+ return headers
190
+ }
@@ -1,19 +1,19 @@
1
- export const getModifierKeys = (): {
2
- shift: boolean,
3
- ctrl: boolean,
4
- command: boolean,
5
- win: boolean,
6
- control: boolean,
7
- alt: boolean
8
- } => {
9
- var nModifierState = App.modifierKeyState();
10
-
11
- return {
12
- shift: (nModifierState & 0x02000000) != 0,
13
- ctrl: (nModifierState & 0x04000000) != 0,
14
- alt: (nModifierState & 0x08000000) != 0,
15
- win: (nModifierState & 0x10000000) != 0,
16
- command: (nModifierState & 0x04000000) != 0,
17
- control: (nModifierState & 0x10000000) != 0
18
- };
1
+ export const getModifierKeys = (): {
2
+ shift: boolean,
3
+ ctrl: boolean,
4
+ command: boolean,
5
+ win: boolean,
6
+ control: boolean,
7
+ alt: boolean
8
+ } => {
9
+ var nModifierState = App.modifierKeyState();
10
+
11
+ return {
12
+ shift: (nModifierState & 0x02000000) != 0,
13
+ ctrl: (nModifierState & 0x04000000) != 0,
14
+ alt: (nModifierState & 0x08000000) != 0,
15
+ win: (nModifierState & 0x10000000) != 0,
16
+ command: (nModifierState & 0x04000000) != 0,
17
+ control: (nModifierState & 0x10000000) != 0
18
+ };
19
19
  }
@@ -1,89 +1,105 @@
1
- import { contains } from './string-helper'
2
-
3
- export const clearColumns = (listView: DzListView) => {
4
- for (let i = 0; i < listView.columns; i++) {
5
- listView.removeColumn(i)
6
- }
7
- }
8
-
9
- export const setDataItem = (listItem: DzListViewItem, data: any) => {
10
- listItem.addDataItem('data', data)
11
- }
12
-
13
- export const getDataItem = <T>(listItem: DzListViewItem): T | null => {
14
- return listItem?.getDataItem('data') ?? null
15
- }
16
-
17
- export const filter = (listView: DzListView, filterOn: (viewItem: DzListViewItem) => string, keywords: string, options?: { selectOnFilter?: boolean, filters?: (viewItem: DzListViewItem) => boolean }) => {
18
- listView.clearSelection()
19
- listView.getItems(DzListView.All).forEach(item => item.visible = true)
20
-
21
- const matchFilter = (text: string): boolean => {
22
- text = text.toLowerCase()
23
- var words = keywords?.toLowerCase().split(" ") ?? []
24
-
25
- return !keywords || keywords.trim() == "" ||
26
- words.every(w => {
27
- return w.length >= 1 || !isNaN(Number(w))
28
- ? contains(text, w)
29
- : text.startsWith(w)
30
- });
31
- }
32
-
33
- const setListViewItemVisibility = (viewItem: DzListViewItem): boolean => {
34
- let keywordMatch = matchFilter(filterOn(viewItem))
35
- let filtersMatch = !options?.filters || options.filters?.(viewItem) === true
36
- viewItem.visible = keywordMatch && filtersMatch
37
-
38
- if (options?.selectOnFilter === true && viewItem.visible && !listView.selectedItem()) {
39
- listView.setSelected(viewItem, true)
40
- listView.ensureItemVisible(viewItem)
41
- }
42
-
43
- return viewItem.visible;
44
- }
45
-
46
- const filterListViewItem = (viewItem: DzListViewItem): boolean => {
47
- var visible = false;
48
-
49
- if (viewItem.childCount() > 0) {
50
- var child = viewItem.firstChild()
51
- while (child) {
52
- visible = visible || filterListViewItem(child)
53
- child = child.nextSibling()
54
- }
55
- }
56
-
57
- viewItem.visible = visible || setListViewItemVisibility(viewItem);
58
- return viewItem.visible;
59
- }
60
-
61
- listView.getItems(DzListView.All).forEach(viewItem => {
62
- viewItem.visible = true
63
- filterListViewItem(viewItem)
64
- });
65
- }
66
-
67
- export const expand = (listView: DzListView, expandOrCollapse: boolean, listItem?: DzListViewItem) => {
68
- if (listItem) {
69
- listItem.open = expandOrCollapse
70
- if (listItem.childCount() > 0) {
71
- var child = listItem.firstChild()
72
- while (child) {
73
- expand(listView, expandOrCollapse, child)
74
- child = child.nextSibling()
75
- }
76
- }
77
- }
78
- else {
79
- listView.getItems(DzListView.All).forEach((item) => {
80
- item.open = expandOrCollapse
81
- })
82
- }
83
- }
84
-
85
- export const checkAll = (listView: DzListView, onOff: boolean) => {
86
- listView.getItems(onOff ? DzListView.NotChecked : DzListView.Checked).forEach(item => {
87
- (item as DzCheckListItem).on = onOff
88
- })
89
- }
1
+ import { contains } from './string-helper'
2
+
3
+ let filterRunId = 0
4
+
5
+ export const clearColumns = (listView: DzListView) => {
6
+ for (let i = 0; i < listView.columns; i++) {
7
+ listView.removeColumn(i)
8
+ }
9
+ }
10
+
11
+ export const setDataItem = (listItem: DzListViewItem, data: any) => {
12
+ listItem.addDataItem('data', data)
13
+ }
14
+
15
+ export const getDataItem = <T>(listItem: DzListViewItem): T | null => {
16
+ return listItem?.getDataItem('data') ?? null
17
+ }
18
+
19
+ export const filter = (listView: DzListView, filterOn: (viewItem: DzListViewItem) => string, keywords: string, options?: { selectOnFilter?: boolean, filters?: (viewItem: DzListViewItem) => boolean }) => {
20
+ filterRunId++
21
+ const currentRunId = filterRunId
22
+ const visitKey = '__dsfFilterVisitId'
23
+
24
+ listView.clearSelection()
25
+ const normalizedKeywords = keywords?.toLowerCase() ?? ''
26
+ const words = normalizedKeywords.split(" ")
27
+
28
+ listView.getItems(DzListView.All).forEach(item => item.visible = true)
29
+
30
+ const matchFilter = (text: string): boolean => {
31
+ text = text.toLowerCase()
32
+
33
+ return !keywords || keywords.trim() == "" ||
34
+ words.every(w => {
35
+ return w.length >= 1 || !isNaN(Number(w))
36
+ ? contains(text, w)
37
+ : text.startsWith(w)
38
+ });
39
+ }
40
+
41
+ const setListViewItemVisibility = (viewItem: DzListViewItem): boolean => {
42
+ let keywordMatch = matchFilter(filterOn(viewItem))
43
+ let filtersMatch = !options?.filters || options.filters?.(viewItem) === true
44
+ viewItem.visible = keywordMatch && filtersMatch
45
+
46
+ if (options?.selectOnFilter === true && viewItem.visible && viewItem.childCount() === 0 && !listView.selectedItem()) {
47
+ listView.setSelected(viewItem, true)
48
+ listView.ensureItemVisible(viewItem)
49
+ }
50
+
51
+ return viewItem.visible;
52
+ }
53
+
54
+ const filterListViewItem = (viewItem: DzListViewItem): boolean => {
55
+ if ((viewItem as any)[visitKey] === currentRunId) {
56
+ return viewItem.visible
57
+ }
58
+ ; (viewItem as any)[visitKey] = currentRunId
59
+
60
+ var visible = false;
61
+
62
+ if (viewItem.childCount() > 0) {
63
+ var child = viewItem.firstChild()
64
+ while (child) {
65
+ visible = visible || filterListViewItem(child)
66
+ child = child.nextSibling()
67
+ }
68
+ }
69
+
70
+ const selfVisible = setListViewItemVisibility(viewItem)
71
+ viewItem.visible = viewItem.childCount() > 0
72
+ ? visible
73
+ : selfVisible
74
+ return viewItem.visible;
75
+ }
76
+
77
+ listView.getItems(DzListView.All).forEach(viewItem => {
78
+ viewItem.visible = true
79
+ filterListViewItem(viewItem)
80
+ });
81
+ }
82
+
83
+ export const expand = (listView: DzListView, expandOrCollapse: boolean, listItem?: DzListViewItem) => {
84
+ if (listItem) {
85
+ listItem.open = expandOrCollapse
86
+ if (listItem.childCount() > 0) {
87
+ var child = listItem.firstChild()
88
+ while (child) {
89
+ expand(listView, expandOrCollapse, child)
90
+ child = child.nextSibling()
91
+ }
92
+ }
93
+ }
94
+ else {
95
+ listView.getItems(DzListView.All).forEach((item) => {
96
+ item.open = expandOrCollapse
97
+ })
98
+ }
99
+ }
100
+
101
+ export const checkAll = (listView: DzListView, onOff: boolean) => {
102
+ listView.getItems(onOff ? DzListView.NotChecked : DzListView.Checked).forEach(item => {
103
+ (item as DzCheckListItem).on = onOff
104
+ })
105
+ }
@@ -1,29 +1,29 @@
1
- import { mainWindow } from '@dsf/core/global'
2
-
3
- const actionMgr = mainWindow.getActionMgr()
4
- const paneMgr = mainWindow.getPaneMgr()
5
-
6
- export const getMenu = (menuPath: string, createIfNotFound: boolean): DzActionMenu => {
7
- var index = menuPath.indexOf("::")
8
- var hasPaneDelimiter = index >= 0
9
-
10
- // TODO: Check what a path delimiter is and how to use it
11
- if (hasPaneDelimiter) {
12
- var paneClass = menuPath.substring(0, index)
13
- var paneManager = paneMgr.findPane(paneClass)
14
- if (paneManager) {
15
- var menu = paneManager.getOptionsMenu();
16
- var subMenu = menuPath.substring(index + 2)
17
- // Get/Create the sub menu
18
- return createIfNotFound
19
- ? menu.findOrCreateSubMenu(subMenu)
20
- : menu.findSubMenu(subMenu);
21
- }
22
- }
23
- else {
24
- // Get/Create the sub menu
25
- return createIfNotFound
26
- ? actionMgr.getMenu().findOrCreateSubMenu(menuPath)
27
- : actionMgr.getMenu().findSubMenu(menuPath)
28
- }
1
+ import { mainWindow } from '@dsf/core/global'
2
+
3
+ const actionMgr = mainWindow.getActionMgr()
4
+ const paneMgr = mainWindow.getPaneMgr()
5
+
6
+ export const getMenu = (menuPath: string, createIfNotFound: boolean): DzActionMenu => {
7
+ var index = menuPath.indexOf("::")
8
+ var hasPaneDelimiter = index >= 0
9
+
10
+ // TODO: Check what a path delimiter is and how to use it
11
+ if (hasPaneDelimiter) {
12
+ var paneClass = menuPath.substring(0, index)
13
+ var paneManager = paneMgr.findPane(paneClass)
14
+ if (paneManager) {
15
+ var menu = paneManager.getOptionsMenu();
16
+ var subMenu = menuPath.substring(index + 2)
17
+ // Get/Create the sub menu
18
+ return createIfNotFound
19
+ ? menu.findOrCreateSubMenu(subMenu)
20
+ : menu.findSubMenu(subMenu);
21
+ }
22
+ }
23
+ else {
24
+ // Get/Create the sub menu
25
+ return createIfNotFound
26
+ ? actionMgr.getMenu().findOrCreateSubMenu(menuPath)
27
+ : actionMgr.getMenu().findSubMenu(menuPath)
28
+ }
29
29
  }
@@ -1,16 +1,26 @@
1
- import * as log from "@dsf/common/log"
2
-
3
- export const info = (msg: string) => {
4
- MessageBox.information(msg, "", "Ok")
5
- }
6
-
7
- export const error = (message: string, writeLog?: boolean) => {
8
- if (writeLog) log.debug(message)
9
- MessageBox.critical(message, "Error", "Ok")
10
- }
11
-
12
- export const confirm = (message?: string): { ok: boolean, cancel: boolean } => {
13
- var response = MessageBox.question(message ?? "Confirm?", "", "Ok", "Cancel");
14
-
15
- return { ok: response == 0, cancel: response != 0 };
1
+ import * as log from "@dsf/common/log"
2
+
3
+ export const info = (msg: string) => {
4
+ MessageBox.information(msg, "", "Ok")
5
+ }
6
+
7
+ export const error = (message: string, writeLog: boolean = true) => {
8
+ if (writeLog) log.debug(message)
9
+ MessageBox.critical(message, "Error", "Ok")
10
+ }
11
+
12
+ export const warning = (message: string) => {
13
+ MessageBox.warning(message, "Warning", "Ok")
14
+ }
15
+
16
+ export const confirm = (message?: string): { ok: boolean, cancel: boolean } => {
17
+ var response = MessageBox.question(message ?? "Confirm?", "", "Ok", "Cancel");
18
+
19
+ return { ok: response == 0, cancel: response != 0 };
20
+ }
21
+
22
+ export const prompt = (text: string, title: string, button0: string, button1?: string): { cancel: boolean, selection: number } => {
23
+ const response = MessageBox.question(text, title, button0, button1, "Cancel")
24
+
25
+ return { cancel: response === 0, selection: response };
16
26
  }