cj-tauri 2.0.0 → 2.1.1

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 (157) hide show
  1. package/README.md +206 -139
  2. package/bin/cj-tauri.js +287 -287
  3. package/cjpm.toml +63 -52
  4. package/cli/cjpm.toml +22 -22
  5. package/cli/src/doctor.cj +308 -306
  6. package/cli/src/main.cj +129 -129
  7. package/cli/src/manifest.cj +643 -558
  8. package/cli/src/manifest_test.cj +87 -0
  9. package/cli/src/project.cj +770 -770
  10. package/cli/src/resolve.cj +348 -348
  11. package/cli/src/scaffold.cj +369 -369
  12. package/cli/src/sync.cj +638 -526
  13. package/cli/src/util.cj +168 -168
  14. package/cli/templates/app/README.md +51 -48
  15. package/cli/templates/app/assets/capabilities/default.json +7 -7
  16. package/cli/templates/app/assets/ui/index.html +120 -118
  17. package/cli/templates/app/cj-tauri.toml +32 -22
  18. package/cli/templates/app/cjpm.toml +34 -34
  19. package/cli/templates/app/src/main.cj +101 -90
  20. package/cli/templates/app-react/README.md +56 -56
  21. package/cli/templates/app-react/assets/capabilities/default.json +7 -7
  22. package/cli/templates/app-react/assets/ui/index.html +25 -25
  23. package/cli/templates/app-react/assets/ui/package.json +19 -19
  24. package/cli/templates/app-react/assets/ui/src/App.css +67 -67
  25. package/cli/templates/app-react/assets/ui/src/App.jsx +124 -124
  26. package/cli/templates/app-react/assets/ui/src/main.jsx +6 -6
  27. package/cli/templates/app-react/assets/ui/vite.config.js +24 -24
  28. package/cli/templates/app-react/cj-tauri.toml +33 -23
  29. package/cli/templates/app-react/cjpm.toml +34 -34
  30. package/cli/templates/app-react/src/main.cj +91 -91
  31. package/cli/templates/app-vue/README.md +56 -56
  32. package/cli/templates/app-vue/assets/capabilities/default.json +7 -7
  33. package/cli/templates/app-vue/assets/ui/index.html +25 -25
  34. package/cli/templates/app-vue/assets/ui/package.json +18 -18
  35. package/cli/templates/app-vue/assets/ui/src/App.vue +176 -176
  36. package/cli/templates/app-vue/assets/ui/src/main.js +4 -4
  37. package/cli/templates/app-vue/assets/ui/vite.config.js +24 -24
  38. package/cli/templates/app-vue/cj-tauri.toml +33 -23
  39. package/cli/templates/app-vue/cjpm.toml +34 -34
  40. package/cli/templates/app-vue/src/main.cj +91 -91
  41. package/cli/templates/ohos-skeleton/AppScope/app.json5 +13 -13
  42. package/cli/templates/ohos-skeleton/AppScope/resources/base/element/string.json +8 -8
  43. package/cli/templates/ohos-skeleton/AppScope/resources/base/media/layered_image.json +6 -6
  44. package/cli/templates/ohos-skeleton/README.md +84 -79
  45. package/cli/templates/ohos-skeleton/build-hap.sh +15 -0
  46. package/cli/templates/ohos-skeleton/build-profile.json5 +46 -46
  47. package/cli/templates/ohos-skeleton/entry/build-profile.json5 +26 -26
  48. package/cli/templates/ohos-skeleton/entry/cjpm.toml +51 -43
  49. package/cli/templates/ohos-skeleton/entry/hvigorfile.ts +6 -6
  50. package/cli/templates/ohos-skeleton/entry/oh-package.json5 +9 -9
  51. package/cli/templates/ohos-skeleton/entry/src/main/cangjie/ability_stage.cj +17 -17
  52. package/cli/templates/ohos-skeleton/entry/src/main/cangjie/app_host.cj +94 -94
  53. package/cli/templates/ohos-skeleton/entry/src/main/cangjie/dialog_host.cj +217 -0
  54. package/cli/templates/ohos-skeleton/entry/src/main/cangjie/index.cj +527 -167
  55. package/cli/templates/ohos-skeleton/entry/src/main/cangjie/main_ability.cj +139 -139
  56. package/cli/templates/ohos-skeleton/entry/src/main/module.json5 +57 -49
  57. package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/color.json +8 -8
  58. package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/string.json +16 -16
  59. package/cli/templates/ohos-skeleton/entry/src/main/resources/base/media/layered_image.json +6 -6
  60. package/cli/templates/ohos-skeleton/entry/src/main/resources/base/profile/main_pages.json +2 -2
  61. package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/capabilities.json +6 -6
  62. package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/index.html +92 -92
  63. package/cli/templates/ohos-skeleton/hvigor/hvigor-config.json5 +5 -5
  64. package/cli/templates/ohos-skeleton/hvigorfile.ts +6 -6
  65. package/cli/templates/ohos-skeleton/oh-package.json5 +10 -10
  66. package/native/build_win.bat +62 -62
  67. package/native/core/bridge_core.c +1681 -1626
  68. package/native/core/bridge_core.h +675 -618
  69. package/native/core/bridge_js.h +108 -108
  70. package/native/platforms/harmonyos/README.md +115 -6
  71. package/native/platforms/linux/bridge_linux.c +2787 -2485
  72. package/native/platforms/windows/bridge_win.c +3745 -3248
  73. package/native/tests/gtk_threading_probe.c +143 -143
  74. package/native/tests/test_bridge_core.c +1339 -1228
  75. package/package.json +53 -53
  76. package/src/api_system.cj +67 -67
  77. package/src/app.cj +335 -969
  78. package/src/app_events.cj +166 -0
  79. package/src/app_host_ops.cj +287 -0
  80. package/src/app_run.cj +283 -0
  81. package/src/app_spec.cj +76 -76
  82. package/src/arkweb_menu.cj +216 -0
  83. package/src/arkweb_script.cj +142 -142
  84. package/src/capability.cj +409 -409
  85. package/src/clipboard_bridge.cj +178 -0
  86. package/src/dialog_spec.cj +79 -0
  87. package/src/dragdrop.cj +26 -26
  88. package/src/embedded_assets.cj +98 -98
  89. package/src/host.cj +752 -607
  90. package/src/host_arkweb.cj +924 -778
  91. package/src/host_webkit.cj +663 -570
  92. package/src/host_webview2.cj +663 -570
  93. package/src/hotkey.cj +66 -66
  94. package/src/ipc_hub.cj +401 -337
  95. package/src/ipc_message.cj +286 -286
  96. package/src/launch.cj +62 -62
  97. package/src/logging.cj +127 -127
  98. package/src/menu.cj +197 -197
  99. package/src/platform/platform_app_context.cj +77 -77
  100. package/src/platform/platform_assets.cj +33 -33
  101. package/src/platform/platform_discover.cj +176 -176
  102. package/src/platform/platform_env.cj +29 -29
  103. package/src/platform/platform_feature.cj +31 -31
  104. package/src/platform/platform_page_source.cj +87 -87
  105. package/src/platform/platform_target_info.cj +32 -32
  106. package/src/platform_host_provider.cj +87 -87
  107. package/src/plugin.cj +333 -333
  108. package/src/plugins/clipboard/plugin_clipboard.cj +152 -152
  109. package/src/plugins/dialog/plugin_dialog.cj +209 -209
  110. package/src/plugins/fs/plugin_fs.cj +105 -1
  111. package/src/plugins/http/http_backend.cj +131 -0
  112. package/src/plugins/http/http_desktop.cj +195 -0
  113. package/src/plugins/http/http_ohos.cj +204 -0
  114. package/src/plugins/http/plugin_http.cj +310 -459
  115. package/src/plugins/log/plugin_log.cj +105 -105
  116. package/src/plugins/menu/plugin_menu.cj +158 -158
  117. package/src/plugins/notification/plugin_notification.cj +154 -154
  118. package/src/plugins/serial/plugin_serial.cj +458 -454
  119. package/src/plugins/serial/serial_bridge.cj +194 -194
  120. package/src/plugins/serial/serial_manager_ohos.cj +92 -0
  121. package/src/plugins/serial/serial_ohos.cj +529 -0
  122. package/src/plugins/shell/plugin_shell.cj +258 -258
  123. package/src/plugins/sqlite/plugin_sqlite.cj +705 -710
  124. package/src/plugins/sqlite/sqlite_ffi.cj +206 -211
  125. package/src/plugins/ws/plugin_ws.cj +488 -470
  126. package/src/process_hidden.cj +174 -174
  127. package/src/scope.cj +391 -391
  128. package/src/shell_event.cj +69 -69
  129. package/src/tests/app_spec_test.cj +130 -127
  130. package/src/tests/capability_test.cj +243 -243
  131. package/src/tests/dialog_spec_test.cj +73 -0
  132. package/src/tests/fake_host.cj +201 -201
  133. package/src/tests/ipc_hub_test.cj +563 -487
  134. package/src/tests/logging_test.cj +62 -62
  135. package/src/tests/platform_contract_test.cj +264 -251
  136. package/src/tests/plugin_clipboard_test.cj +222 -222
  137. package/src/tests/plugin_dialog_test.cj +237 -237
  138. package/src/tests/plugin_fs_test.cj +207 -0
  139. package/src/tests/plugin_http_test.cj +124 -124
  140. package/src/tests/plugin_notification_test.cj +205 -205
  141. package/src/tests/plugin_serial_test.cj +48 -0
  142. package/src/tests/plugin_test.cj +605 -585
  143. package/src/tests/plugin_ws_test.cj +40 -40
  144. package/src/tests/process_hidden_test.cj +129 -129
  145. package/src/tests/scope_test.cj +350 -350
  146. package/src/tests/system_host_test.cj +99 -81
  147. package/src/tests/urlutil_test.cj +53 -53
  148. package/src/tests/version_test.cj +75 -75
  149. package/src/tests/window_registry_test.cj +123 -123
  150. package/src/tray.cj +90 -90
  151. package/src/urlutil.cj +159 -159
  152. package/src/version.cj +44 -44
  153. package/src/window.cj +51 -51
  154. package/src/window_registry.cj +116 -116
  155. package/prebuilt/win32-x64/cj-tauri.exe +0 -0
  156. package/src/plugins/serial/serial_ohos_stub.cj +0 -61
  157. package/src/plugins/sqlite/sqlite_ohos_stub.cj +0 -91
@@ -1,201 +1,201 @@
1
- package cjTauri.tests
2
-
3
- import cjTauri.*
4
- import cjTauri.platform.*
5
- import std.collection.*
6
-
7
- /*
8
- * WebViewHost 的测试替身:记录被调用的痕迹,其余空实现。
9
- * 用途:不创建原生窗口就能测装配路径(TauriApp 装配、WindowRegistry、事件派发)。
10
- * 接口增删方法时这里必须跟着改——那是**有意的**:编译器会点名这一处,
11
- * 免得像 C 桥那样「改了一份忘了另一份」。
12
- */
13
- class FakeHost <: WebViewHost {
14
- // 字段不叫 label:接口有 label() 方法,同名会撞
15
- public let windowLabel: String
16
- public var started: Bool = false
17
- public var startedUrl: String = ""
18
- public var shownHtml: String = ""
19
- public var jsCalls: ArrayList<String> = ArrayList<String>()
20
- public var initScripts: ArrayList<String> = ArrayList<String>()
21
- public var config: WindowConfig = WindowConfig()
22
- public var handler: (String) -> Unit = { _ => }
23
- public var disposed: Bool = false
24
- public var quitCalled: Bool = false
25
- public var devToolsEnabled: Bool = false
26
- // 对话框入参按「调一次记一次」存成字符串:桩不真弹窗,用例要断言的是「谁被调了、带了什么」
27
- public var fileDialogArgs: String = ""
28
- public var messageDialogArgs: String = ""
29
- // 选目录与文件框分开记:用例要断言「走的是目录那条路」,不能与 fileDialogArgs 混为一谈
30
- public var folderDialogTitle: String = ""
31
- // 菜单:线路文本 / 单项状态按原样记下(桩不建真菜单,用例断言的是投下来的内容)
32
- public var menuWire: String = ""
33
- public var menuItemStateArgs: String = ""
34
- // 标题栏副标题:桩只记最后一次文本(用例断言的是「投下来的是什么」)
35
- public var titlebarSubtitleText: String = ""
36
- public var dragDropArgs: String = ""
37
- public var hotkeyWire: String = ""
38
- public var trayWire: String = ""
39
- public var windowVisibleValue: Bool = true
40
- public var minimizeToTrayValue: Bool = false
41
- // shell 事件回调(菜单点击等):用例可以自己调它,模拟「桥把事件送进来了」
42
- public var shellHandler: (String) -> Unit = { _ => }
43
- // 销毁回调:用例可以自己调它,模拟「桥通知本窗销毁了」
44
- public var destroyHandler: () -> Unit = { => }
45
- // 剪贴板 / 通知:写与通知按「调一次记一次」,读值可注入(默认空,用例按需设)
46
- public var clipboardWritten: String = ""
47
- public var clipboardReadValue: Option<String> = None<String>
48
- public var notifiedArgs: String = ""
49
- // 能力位:桩给「有菜单」,用例要测「平台没这个本事」时自行覆盖它
50
- public var caps: Int32 = CJ_CAP_MENU
51
- // load(source) 收敛(批次 3-PR3):记最近一次 load 的来源原文与 resolver 注入痕迹
52
- public var loadedSource: String = ""
53
- public var resolverInjected: Option<AssetResolver> = None
54
-
55
- public init(windowLabel: String) {
56
- this.windowLabel = windowLabel
57
- }
58
-
59
- public func label(): String {
60
- return this.windowLabel
61
- }
62
-
63
- public func setAssetResolver(resolver: Option<AssetResolver>): Unit {
64
- this.resolverInjected = resolver
65
- }
66
-
67
- /**
68
- * 桩的 load 不做资产解析(那是对应真宿主的事,resolvePage 本身有独立单测):
69
- * 只记痕——用例断言的是「装配层把哪种来源投给了宿主」
70
- */
71
- public func load(source: PageSource): Unit {
72
- this.started = true
73
- match (source) {
74
- case Inline(html) => this.shownHtml = html
75
- case Url(url) => this.startedUrl = url
76
- case DevServer(url) => this.startedUrl = url
77
- case Asset(name) => this.loadedSource = "asset:${name}"
78
- }
79
- }
80
-
81
- public func addInitScript(js: String): Unit {
82
- this.initScripts.add(js)
83
- }
84
-
85
- public func reload(): Unit {}
86
-
87
- public func setWindowConfig(config: WindowConfig): Unit {
88
- this.config = config
89
- }
90
-
91
- public func setDevTools(enabled: Bool): Unit {
92
- this.devToolsEnabled = enabled
93
- }
94
-
95
- public func openDevTools(): Unit {}
96
-
97
- public func setMenu(wire: String): Unit {
98
- this.menuWire = wire
99
- }
100
-
101
- public func setMenuItemState(id: String, enabled: Bool, checked: Bool): Unit {
102
- this.menuItemStateArgs = "${id}|${enabled}|${checked}"
103
- }
104
-
105
- public func setTitlebarSubtitle(text: String): Unit {
106
- this.titlebarSubtitleText = text
107
- }
108
-
109
- public func setDragDropPolicy(enabled: Bool, files: Bool): Unit {
110
- this.dragDropArgs = "${enabled}|${files}"
111
- }
112
-
113
- public func setGlobalHotkeys(wire: String): Unit {
114
- this.hotkeyWire = wire
115
- }
116
-
117
- public func setTray(wire: String): Unit {
118
- this.trayWire = wire
119
- }
120
-
121
- // 窗口可见性 / 最小化策略:桩只记最后一次设置(用例断言的是「谁被调了、带了什么」)
122
- public func setWindowVisible(visible: Bool): Unit {
123
- this.windowVisibleValue = visible
124
- }
125
-
126
- public func setMinimizeToTray(enabled: Bool): Unit {
127
- this.minimizeToTrayValue = enabled
128
- }
129
-
130
- public func hostCapabilities(): Int32 {
131
- return this.caps
132
- }
133
-
134
- public func setShellHandler(handler: (String) -> Unit): Unit {
135
- this.shellHandler = handler
136
- }
137
-
138
- public func setDestroyHandler(handler: () -> Unit): Unit {
139
- this.destroyHandler = handler
140
- }
141
-
142
- public func showFileDialog(save: Bool, title: String, filter: String): String {
143
- this.fileDialogArgs = "${save}|${title}|${filter}"
144
- return ""
145
- }
146
-
147
- public func showFileDialogPreset(save: Bool, title: String, filter: String,
148
- defaultName: String): String {
149
- // 记痕带预置名:多窗取证靠它断言「本窗拿到的是本窗预置的名字」
150
- this.fileDialogArgs = "${save}|${title}|${filter}|${defaultName}"
151
- return ""
152
- }
153
-
154
- public func showFolderDialog(title: String): String {
155
- // 桩不真弹窗:记下标题即可(用例断言的是「谁被调了、带了什么」)
156
- this.folderDialogTitle = title
157
- return ""
158
- }
159
-
160
- public func showMessageDialog(kind: String, title: String, message: String): Bool {
161
- this.messageDialogArgs = "${kind}|${title}|${message}"
162
- return false
163
- }
164
-
165
- public func clipboardWriteText(text: String): Bool {
166
- this.clipboardWritten = text
167
- return true
168
- }
169
-
170
- public func clipboardReadText(): Option<String> {
171
- return this.clipboardReadValue
172
- }
173
-
174
- public func notify(title: String, body: String): Bool {
175
- this.notifiedArgs = "${title}|${body}"
176
- return true
177
- }
178
-
179
- public func runJs(js: String): Unit {
180
- this.jsCalls.add(js)
181
- }
182
-
183
- public func quit(): Unit {
184
- this.quitCalled = true
185
- }
186
-
187
- public func setMessageHandler(handler: (String) -> Unit): Unit {
188
- this.handler = handler
189
- }
190
-
191
- // run 收尾开关:run() 阻塞在 waitForExit,用例把它置 true 让 run 返回(批次 3-PR3 的 load 接线用例用)
192
- public var quitNow: Bool = false
193
-
194
- public func shouldQuit(): Bool {
195
- return this.quitNow
196
- }
197
-
198
- public func dispose(): Unit {
199
- this.disposed = true
200
- }
201
- }
1
+ package cjTauri.tests
2
+
3
+ import cjTauri.*
4
+ import cjTauri.platform.*
5
+ import std.collection.*
6
+
7
+ /*
8
+ * WebViewHost 的测试替身:记录被调用的痕迹,其余空实现。
9
+ * 用途:不创建原生窗口就能测装配路径(TauriApp 装配、WindowRegistry、事件派发)。
10
+ * 接口增删方法时这里必须跟着改——那是**有意的**:编译器会点名这一处,
11
+ * 免得像 C 桥那样「改了一份忘了另一份」。
12
+ */
13
+ class FakeHost <: WebViewHost {
14
+ // 字段不叫 label:接口有 label() 方法,同名会撞
15
+ public let windowLabel: String
16
+ public var started: Bool = false
17
+ public var startedUrl: String = ""
18
+ public var shownHtml: String = ""
19
+ public var jsCalls: ArrayList<String> = ArrayList<String>()
20
+ public var initScripts: ArrayList<String> = ArrayList<String>()
21
+ public var config: WindowConfig = WindowConfig()
22
+ public var handler: (String) -> Unit = { _ => }
23
+ public var disposed: Bool = false
24
+ public var quitCalled: Bool = false
25
+ public var devToolsEnabled: Bool = false
26
+ // 对话框入参按「调一次记一次」存成字符串:桩不真弹窗,用例要断言的是「谁被调了、带了什么」
27
+ public var fileDialogArgs: String = ""
28
+ public var messageDialogArgs: String = ""
29
+ // 选目录与文件框分开记:用例要断言「走的是目录那条路」,不能与 fileDialogArgs 混为一谈
30
+ public var folderDialogTitle: String = ""
31
+ // 菜单:线路文本 / 单项状态按原样记下(桩不建真菜单,用例断言的是投下来的内容)
32
+ public var menuWire: String = ""
33
+ public var menuItemStateArgs: String = ""
34
+ // 标题栏副标题:桩只记最后一次文本(用例断言的是「投下来的是什么」)
35
+ public var titlebarSubtitleText: String = ""
36
+ public var dragDropArgs: String = ""
37
+ public var hotkeyWire: String = ""
38
+ public var trayWire: String = ""
39
+ public var windowVisibleValue: Bool = true
40
+ public var minimizeToTrayValue: Bool = false
41
+ // shell 事件回调(菜单点击等):用例可以自己调它,模拟「桥把事件送进来了」
42
+ public var shellHandler: (String) -> Unit = { _ => }
43
+ // 销毁回调:用例可以自己调它,模拟「桥通知本窗销毁了」
44
+ public var destroyHandler: () -> Unit = { => }
45
+ // 剪贴板 / 通知:写与通知按「调一次记一次」,读值可注入(默认空,用例按需设)
46
+ public var clipboardWritten: String = ""
47
+ public var clipboardReadValue: Option<String> = None<String>
48
+ public var notifiedArgs: String = ""
49
+ // 能力位:桩给「有菜单」,用例要测「平台没这个本事」时自行覆盖它
50
+ public var caps: Int32 = CJ_CAP_MENU
51
+ // load(source) 收敛(批次 3-PR3):记最近一次 load 的来源原文与 resolver 注入痕迹
52
+ public var loadedSource: String = ""
53
+ public var resolverInjected: Option<AssetResolver> = None
54
+
55
+ public init(windowLabel: String) {
56
+ this.windowLabel = windowLabel
57
+ }
58
+
59
+ public func label(): String {
60
+ return this.windowLabel
61
+ }
62
+
63
+ public func setAssetResolver(resolver: Option<AssetResolver>): Unit {
64
+ this.resolverInjected = resolver
65
+ }
66
+
67
+ /**
68
+ * 桩的 load 不做资产解析(那是对应真宿主的事,resolvePage 本身有独立单测):
69
+ * 只记痕——用例断言的是「装配层把哪种来源投给了宿主」
70
+ */
71
+ public func load(source: PageSource): Unit {
72
+ this.started = true
73
+ match (source) {
74
+ case Inline(html) => this.shownHtml = html
75
+ case Url(url) => this.startedUrl = url
76
+ case DevServer(url) => this.startedUrl = url
77
+ case Asset(name) => this.loadedSource = "asset:${name}"
78
+ }
79
+ }
80
+
81
+ public func addInitScript(js: String): Unit {
82
+ this.initScripts.add(js)
83
+ }
84
+
85
+ public func reload(): Unit {}
86
+
87
+ public func setWindowConfig(config: WindowConfig): Unit {
88
+ this.config = config
89
+ }
90
+
91
+ public func setDevTools(enabled: Bool): Unit {
92
+ this.devToolsEnabled = enabled
93
+ }
94
+
95
+ public func openDevTools(): Unit {}
96
+
97
+ public func setMenu(wire: String): Unit {
98
+ this.menuWire = wire
99
+ }
100
+
101
+ public func setMenuItemState(id: String, enabled: Bool, checked: Bool): Unit {
102
+ this.menuItemStateArgs = "${id}|${enabled}|${checked}"
103
+ }
104
+
105
+ public func setTitlebarSubtitle(text: String): Unit {
106
+ this.titlebarSubtitleText = text
107
+ }
108
+
109
+ public func setDragDropPolicy(enabled: Bool, files: Bool): Unit {
110
+ this.dragDropArgs = "${enabled}|${files}"
111
+ }
112
+
113
+ public func setGlobalHotkeys(wire: String): Unit {
114
+ this.hotkeyWire = wire
115
+ }
116
+
117
+ public func setTray(wire: String): Unit {
118
+ this.trayWire = wire
119
+ }
120
+
121
+ // 窗口可见性 / 最小化策略:桩只记最后一次设置(用例断言的是「谁被调了、带了什么」)
122
+ public func setWindowVisible(visible: Bool): Unit {
123
+ this.windowVisibleValue = visible
124
+ }
125
+
126
+ public func setMinimizeToTray(enabled: Bool): Unit {
127
+ this.minimizeToTrayValue = enabled
128
+ }
129
+
130
+ public func hostCapabilities(): Int32 {
131
+ return this.caps
132
+ }
133
+
134
+ public func setShellHandler(handler: (String) -> Unit): Unit {
135
+ this.shellHandler = handler
136
+ }
137
+
138
+ public func setDestroyHandler(handler: () -> Unit): Unit {
139
+ this.destroyHandler = handler
140
+ }
141
+
142
+ public func showFileDialog(save: Bool, title: String, filter: String): String {
143
+ this.fileDialogArgs = "${save}|${title}|${filter}"
144
+ return ""
145
+ }
146
+
147
+ public func showFileDialogPreset(save: Bool, title: String, filter: String,
148
+ defaultName: String): String {
149
+ // 记痕带预置名:多窗取证靠它断言「本窗拿到的是本窗预置的名字」
150
+ this.fileDialogArgs = "${save}|${title}|${filter}|${defaultName}"
151
+ return ""
152
+ }
153
+
154
+ public func showFolderDialog(title: String): String {
155
+ // 桩不真弹窗:记下标题即可(用例断言的是「谁被调了、带了什么」)
156
+ this.folderDialogTitle = title
157
+ return ""
158
+ }
159
+
160
+ public func showMessageDialog(kind: String, title: String, message: String): Bool {
161
+ this.messageDialogArgs = "${kind}|${title}|${message}"
162
+ return false
163
+ }
164
+
165
+ public func clipboardWriteText(text: String): Bool {
166
+ this.clipboardWritten = text
167
+ return true
168
+ }
169
+
170
+ public func clipboardReadText(): Option<String> {
171
+ return this.clipboardReadValue
172
+ }
173
+
174
+ public func notify(title: String, body: String): Bool {
175
+ this.notifiedArgs = "${title}|${body}"
176
+ return true
177
+ }
178
+
179
+ public func runJs(js: String): Unit {
180
+ this.jsCalls.add(js)
181
+ }
182
+
183
+ public func quit(): Unit {
184
+ this.quitCalled = true
185
+ }
186
+
187
+ public func setMessageHandler(handler: (String) -> Unit): Unit {
188
+ this.handler = handler
189
+ }
190
+
191
+ // run 收尾开关:run() 阻塞在 waitForExit,用例把它置 true 让 run 返回(批次 3-PR3 的 load 接线用例用)
192
+ public var quitNow: Bool = false
193
+
194
+ public func shouldQuit(): Bool {
195
+ return this.quitNow
196
+ }
197
+
198
+ public func dispose(): Unit {
199
+ this.disposed = true
200
+ }
201
+ }