@lenorin/dsh-tauri-launcher 1.0.0

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 (38) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +102 -0
  3. package/cordis.patch.yml +7 -0
  4. package/launcher/README.md +56 -0
  5. package/launcher/bin/dsh-launcher.exe +0 -0
  6. package/launcher/build.ps1 +44 -0
  7. package/launcher/src-tauri/Cargo.toml +20 -0
  8. package/launcher/src-tauri/build.rs +3 -0
  9. package/launcher/src-tauri/capabilities/default.json +9 -0
  10. package/launcher/src-tauri/icons/128x128.png +0 -0
  11. package/launcher/src-tauri/icons/128x128@2x.png +0 -0
  12. package/launcher/src-tauri/icons/32x32.png +0 -0
  13. package/launcher/src-tauri/icons/Square107x107Logo.png +0 -0
  14. package/launcher/src-tauri/icons/Square142x142Logo.png +0 -0
  15. package/launcher/src-tauri/icons/Square150x150Logo.png +0 -0
  16. package/launcher/src-tauri/icons/Square284x284Logo.png +0 -0
  17. package/launcher/src-tauri/icons/Square30x30Logo.png +0 -0
  18. package/launcher/src-tauri/icons/Square310x310Logo.png +0 -0
  19. package/launcher/src-tauri/icons/Square44x44Logo.png +0 -0
  20. package/launcher/src-tauri/icons/Square71x71Logo.png +0 -0
  21. package/launcher/src-tauri/icons/Square89x89Logo.png +0 -0
  22. package/launcher/src-tauri/icons/StoreLogo.png +0 -0
  23. package/launcher/src-tauri/icons/icon.icns +0 -0
  24. package/launcher/src-tauri/icons/icon.ico +0 -0
  25. package/launcher/src-tauri/icons/icon.png +0 -0
  26. package/launcher/src-tauri/src/dsh.rs +286 -0
  27. package/launcher/src-tauri/src/lib.rs +727 -0
  28. package/launcher/src-tauri/src/main.rs +6 -0
  29. package/launcher/src-tauri/tauri.conf.json +38 -0
  30. package/launcher/ui/index.html +64 -0
  31. package/launcher/ui/main.js +122 -0
  32. package/launcher/ui/settings.css +157 -0
  33. package/launcher/ui/settings.html +71 -0
  34. package/launcher/ui/settings.js +83 -0
  35. package/launcher/ui/styles.css +212 -0
  36. package/lib/client.js +241 -0
  37. package/lib/index.js +445 -0
  38. package/package.json +28 -0
@@ -0,0 +1,212 @@
1
+ :root {
2
+ color-scheme: dark;
3
+ }
4
+
5
+ * {
6
+ box-sizing: border-box;
7
+ margin: 0;
8
+ padding: 0;
9
+ }
10
+
11
+ html,
12
+ body,
13
+ #app {
14
+ height: 100%;
15
+ }
16
+
17
+ body {
18
+ font-family: "Segoe UI", "Microsoft YaHei", system-ui, -apple-system, sans-serif;
19
+ background:
20
+ radial-gradient(1200px 700px at 15% -10%, #15304b 0%, transparent 60%),
21
+ radial-gradient(1000px 620px at 110% 110%, #1c2644 0%, transparent 55%),
22
+ #0b0f17;
23
+ color: #e5eaf2;
24
+ -webkit-font-smoothing: antialiased;
25
+ overflow: hidden;
26
+ }
27
+
28
+ #app {
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ padding: 24px;
33
+ }
34
+
35
+ .card {
36
+ width: min(640px, 100%);
37
+ background: rgba(17, 23, 35, 0.9);
38
+ border: 1px solid rgba(148, 180, 220, 0.14);
39
+ border-radius: 18px;
40
+ padding: 42px 38px 26px;
41
+ text-align: center;
42
+ box-shadow: 0 24px 70px rgba(0, 0, 0, 0.45);
43
+ backdrop-filter: blur(14px);
44
+ }
45
+
46
+ .brand {
47
+ margin: 0 auto 18px;
48
+ display: flex;
49
+ justify-content: center;
50
+ }
51
+
52
+ .brand svg {
53
+ width: 220px;
54
+ height: auto;
55
+ color: #e0f2fe;
56
+ filter: drop-shadow(0 2px 12px rgba(14, 165, 233, 0.3));
57
+ }
58
+
59
+ .phase {
60
+ margin-top: 26px;
61
+ min-height: 200px;
62
+ display: flex;
63
+ flex-direction: column;
64
+ align-items: center;
65
+ justify-content: center;
66
+ gap: 14px;
67
+ }
68
+
69
+ .hidden {
70
+ display: none !important;
71
+ }
72
+
73
+ .spinner {
74
+ width: 46px;
75
+ height: 46px;
76
+ border-radius: 50%;
77
+ border: 3px solid rgba(96, 165, 250, 0.18);
78
+ border-top-color: #60a5fa;
79
+ animation: spin 0.9s linear infinite;
80
+ }
81
+
82
+ .check,
83
+ .cross {
84
+ width: 56px;
85
+ height: 56px;
86
+ border-radius: 50%;
87
+ display: flex;
88
+ align-items: center;
89
+ justify-content: center;
90
+ font-size: 28px;
91
+ font-weight: 700;
92
+ }
93
+
94
+ .check {
95
+ background: rgba(34, 197, 94, 0.14);
96
+ color: #4ade80;
97
+ border: 2px solid rgba(74, 222, 128, 0.5);
98
+ animation: pop 0.35s cubic-bezier(0.2, 1.4, 0.4, 1);
99
+ }
100
+
101
+ .cross {
102
+ background: rgba(239, 68, 68, 0.12);
103
+ color: #f87171;
104
+ border: 2px solid rgba(248, 113, 113, 0.5);
105
+ }
106
+
107
+ .status {
108
+ font-size: 16px;
109
+ font-weight: 500;
110
+ }
111
+
112
+ .hint {
113
+ font-size: 13px;
114
+ color: #8ea0b8;
115
+ line-height: 1.7;
116
+ max-width: 460px;
117
+ white-space: pre-wrap;
118
+ word-break: break-all;
119
+ }
120
+
121
+ .err-detail {
122
+ text-align: left;
123
+ width: 100%;
124
+ max-width: 100%;
125
+ max-height: 190px;
126
+ overflow: auto;
127
+ background: rgba(239, 68, 68, 0.06);
128
+ border: 1px solid rgba(248, 113, 113, 0.25);
129
+ border-radius: 10px;
130
+ padding: 10px 12px;
131
+ font-family: Consolas, "Cascadia Mono", monospace;
132
+ font-size: 12px;
133
+ }
134
+
135
+ .log {
136
+ width: 100%;
137
+ max-height: 160px;
138
+ overflow: auto;
139
+ background: #0a0e16;
140
+ border: 1px solid rgba(148, 180, 220, 0.12);
141
+ border-radius: 10px;
142
+ padding: 10px 12px;
143
+ font-family: Consolas, "Cascadia Mono", monospace;
144
+ font-size: 11px;
145
+ line-height: 1.5;
146
+ color: #9fb2c8;
147
+ text-align: left;
148
+ }
149
+
150
+ .log-line {
151
+ white-space: pre-wrap;
152
+ word-break: break-all;
153
+ }
154
+
155
+ .log-err {
156
+ color: #f0a6a6;
157
+ }
158
+
159
+ #retry-btn {
160
+ margin-top: 4px;
161
+ padding: 10px 36px;
162
+ border: none;
163
+ border-radius: 10px;
164
+ cursor: pointer;
165
+ background: linear-gradient(135deg, #0ea5e9, #4f46e5);
166
+ color: #fff;
167
+ font-size: 14px;
168
+ font-weight: 600;
169
+ box-shadow: 0 6px 18px rgba(14, 165, 233, 0.35);
170
+ transition: transform 0.12s ease, filter 0.12s ease;
171
+ }
172
+
173
+ #retry-btn:hover {
174
+ filter: brightness(1.12);
175
+ }
176
+
177
+ #retry-btn:active {
178
+ transform: scale(0.97);
179
+ }
180
+
181
+ .footer {
182
+ margin-top: 24px;
183
+ font-size: 12px;
184
+ color: #5c6b80;
185
+ }
186
+
187
+ @keyframes spin {
188
+ to {
189
+ transform: rotate(360deg);
190
+ }
191
+ }
192
+
193
+ @keyframes float {
194
+ 0%,
195
+ 100% {
196
+ transform: translateY(0);
197
+ }
198
+ 50% {
199
+ transform: translateY(-5px);
200
+ }
201
+ }
202
+
203
+ @keyframes pop {
204
+ from {
205
+ transform: scale(0.4);
206
+ opacity: 0;
207
+ }
208
+ to {
209
+ transform: scale(1);
210
+ opacity: 1;
211
+ }
212
+ }
package/lib/client.js ADDED
@@ -0,0 +1,241 @@
1
+ /**
2
+ * dsh-tauri-launcher — browser half.
3
+ * 在设置面板注册「桌面启动」分区:桌面端启动开关(含快速确认与乐观反馈)、
4
+ * 添加快捷方式按钮、关闭确认弹窗、诊断信息(仅出错时显示)。
5
+ * 与宿主通信走 /api/dsh-tauri-launcher/*(同源 fetch,仅回环)。
6
+ */
7
+ window.__ModuleLoader__.load({
8
+ id: '@lenorin/dsh-tauri-launcher',
9
+ factory: (require) => {
10
+ const module = { exports: {} }
11
+ const exports = module.exports
12
+ const React = require('react')
13
+
14
+ const CSS = `
15
+ .tauri-dsl-root { display: flex; flex-direction: column; gap: 12px; padding: 4px 0 8px; max-width: 560px; }
16
+ .tauri-dsl-desc { font-size: 12px; line-height: 1.6; color: var(--dsw-alias-label-secondary); }
17
+ .tauri-dsl-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 14px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 12px; background: var(--dsw-alias-bg-layer-2); cursor: pointer; }
18
+ .tauri-dsl-left { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
19
+ .tauri-dsl-label { font-size: 13px; font-weight: 600; color: var(--dsw-alias-label-primary); }
20
+ .tauri-dsl-state { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--dsw-alias-label-secondary); }
21
+ .tauri-dsl-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: var(--dsw-alias-label-secondary); }
22
+ .tauri-dsl-dot-on { background: var(--dsw-alias-state-success-primary); box-shadow: 0 0 6px var(--dsw-alias-state-success-primary); }
23
+ .tauri-dsl-dot-unknown { background: var(--dsw-alias-state-warn-primary); }
24
+ .tauri-dsl-dot-pending { background: var(--dsw-alias-state-warn-primary); animation: tauri-dsl-pulse 1s ease-in-out infinite; }
25
+ @keyframes tauri-dsl-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
26
+ .tauri-dsl-switch { position: relative; width: 42px; height: 24px; flex-shrink: 0; display: inline-block; }
27
+ .tauri-dsl-switch input { opacity: 0; width: 0; height: 0; position: absolute; }
28
+ .tauri-dsl-track { position: absolute; inset: 0; border-radius: 999px; background: var(--dsw-alias-bg-layer-1); border: 1px solid var(--dsw-alias-border-l2); transition: background 0.15s ease, border-color 0.15s ease; }
29
+ .tauri-dsl-track::before { content: ''; position: absolute; width: 16px; height: 16px; left: 3px; top: 3px; border-radius: 50%; background: var(--dsw-alias-label-secondary); transition: transform 0.15s ease, background 0.15s ease; }
30
+ .tauri-dsl-switch input:checked + .tauri-dsl-track { background: var(--dsw-alias-brand-primary); border-color: transparent; }
31
+ .tauri-dsl-switch input:checked + .tauri-dsl-track::before { transform: translateX(18px); background: var(--dsw-alias-label-primary-inverted); }
32
+ .tauri-dsl-switch input:disabled + .tauri-dsl-track { opacity: 0.55; }
33
+ .tauri-dsl-row:has(input:disabled) { cursor: wait; }
34
+ .tauri-dsl-linkbtn { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 8px; border: 1px solid var(--dsw-alias-border-l2); background: var(--dsw-alias-bg-layer-2); color: var(--dsw-alias-label-primary); font-size: 12px; cursor: pointer; }
35
+ .tauri-dsl-linkbtn:disabled { opacity: 0.55; cursor: default; }
36
+ .tauri-dsl-overlay { position: fixed; inset: 0; z-index: 9999; display: flex; align-items: center; justify-content: center; background: rgba(0, 0, 0, 0.45); }
37
+ .tauri-dsl-dialog { width: min(340px, calc(100vw - 48px)); padding: 18px 18px 14px; border-radius: 14px; background: var(--dsw-alias-bg-overlay); border: 1px solid var(--dsw-alias-border-l2); box-shadow: 0 18px 50px rgba(0, 0, 0, 0.4); display: flex; flex-direction: column; gap: 10px; }
38
+ .tauri-dsl-dialog-title { font-size: 14px; font-weight: 600; color: var(--dsw-alias-label-primary); }
39
+ .tauri-dsl-dialog-body { font-size: 13px; line-height: 1.7; color: var(--dsw-alias-label-secondary); }
40
+ .tauri-dsl-dialog-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 4px; }
41
+ .tauri-dsl-btn-ghost { padding: 7px 16px; border-radius: 8px; border: 1px solid var(--dsw-alias-border-l2); background: transparent; color: var(--dsw-alias-label-primary); font-size: 13px; cursor: pointer; }
42
+ .tauri-dsl-btn-ghost:hover { background: var(--dsw-alias-bg-layer-2); }
43
+ .tauri-dsl-btn-primary { padding: 7px 16px; border-radius: 8px; border: none; background: var(--dsw-alias-brand-primary); color: var(--dsw-alias-label-primary-inverted); font-size: 13px; font-weight: 600; cursor: pointer; }
44
+ .tauri-dsl-btn-primary:hover { filter: brightness(1.08); }
45
+ .tauri-dsl-error { font-size: 12px; color: var(--dsw-alias-state-error-primary); white-space: pre-wrap; word-break: break-all; }
46
+ .tauri-dsl-details { font-size: 12px; color: var(--dsw-alias-label-secondary); }
47
+ .tauri-dsl-details summary { cursor: pointer; user-select: none; }
48
+ .tauri-dsl-diag { margin: 6px 0 0; padding: 8px 10px; max-height: 220px; overflow: auto; background: var(--dsw-alias-bg-layer-2); border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; font-family: Consolas, 'Cascadia Mono', monospace; font-size: 11px; line-height: 1.5; color: var(--dsw-alias-label-secondary); white-space: pre-wrap; word-break: break-all; }
49
+ .VOzbGW_navList button:nth-child(5) svg { display: none; }
50
+ .VOzbGW_navList button:nth-child(5)::before {
51
+ content: '';
52
+ width: 16px;
53
+ height: 16px;
54
+ flex-shrink: 0;
55
+ background-color: currentColor;
56
+ -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='20' height='14' x='2' y='3' rx='2'/%3E%3Cline x1='8' x2='16' y1='21' y2='21'/%3E%3Cline x1='12' x2='12' y1='17' y2='21'/%3E%3C/svg%3E") center / 16px 16px no-repeat;
57
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='20' height='14' x='2' y='3' rx='2'/%3E%3Cline x1='8' x2='16' y1='21' y2='21'/%3E%3Cline x1='12' x2='12' y1='17' y2='21'/%3E%3C/svg%3E") center / 16px 16px no-repeat;
58
+ opacity: 0.85;
59
+ }
60
+ .VOzbGW_navList button:nth-child(5)[aria-current='true']::before {
61
+ background-color: var(--dsw-alias-brand-primary);
62
+ opacity: 1;
63
+ }
64
+ `
65
+
66
+ const API_BASE = '/api/dsh-tauri-launcher'
67
+
68
+ const api = {
69
+ async state() {
70
+ const response = await fetch(API_BASE + '/state')
71
+ return response.json()
72
+ },
73
+ async setDesktop(enabled) {
74
+ const response = await fetch(API_BASE + '/set-desktop', {
75
+ method: 'POST',
76
+ headers: { 'content-type': 'application/json' },
77
+ body: JSON.stringify({ enabled }),
78
+ })
79
+ return response.json()
80
+ },
81
+ async setShortcut() {
82
+ const response = await fetch(API_BASE + '/set-shortcut', { method: 'POST' })
83
+ return response.json()
84
+ },
85
+ }
86
+
87
+ exports.inject = ['slots']
88
+
89
+ exports.apply = function (ctx) {
90
+ const slots = ctx.get('slots')
91
+ if (slots === undefined) return
92
+
93
+ const styleEl = document.createElement('style')
94
+ styleEl.dataset.plugin = '@lenorin/dsh-tauri-launcher'
95
+ styleEl.textContent = CSS
96
+ document.head.appendChild(styleEl)
97
+ ctx.effect(() => () => styleEl.remove(), 'dsh-tauri-launcher: css')
98
+
99
+ function errText(error) {
100
+ if (typeof error === 'string') return error
101
+ if (error && error.message) return error.message
102
+ try { return JSON.stringify(error) } catch { return String(error) }
103
+ }
104
+
105
+ async function fetchState() {
106
+ try {
107
+ const state = await api.state()
108
+ return { desktop: state.desktop, shortcut: Boolean(state.shortcut), error: '', diag: state.diag || '' }
109
+ } catch (error) {
110
+ return { desktop: null, shortcut: false, error: '读取状态失败:' + errText(error), diag: '' }
111
+ }
112
+ }
113
+
114
+ function DesktopSection() {
115
+ const [snap, setSnap] = React.useState(null)
116
+ const [busy, setBusy] = React.useState(false)
117
+ const [pending, setPending] = React.useState(null)
118
+ const [linkBusy, setLinkBusy] = React.useState(false)
119
+ const [confirmOpen, setConfirmOpen] = React.useState(false)
120
+
121
+ React.useEffect(() => {
122
+ let alive = true
123
+ const merge = (s) => setSnap((prev) => (prev && prev.error ? { ...s, error: prev.error } : s))
124
+ fetchState().then((s) => { if (alive) merge(s) })
125
+ const timer = setInterval(() => { fetchState().then((s) => { if (alive) merge(s) }) }, 10000)
126
+ return () => { alive = false; clearInterval(timer) }
127
+ }, [])
128
+
129
+ const performToggle = async (target) => {
130
+ setBusy(true)
131
+ setPending(target ? 'on' : 'off')
132
+ try {
133
+ const result = await api.setDesktop(target)
134
+ if (result && result.ok) {
135
+ setSnap((prev) => ({
136
+ desktop: result.desktop,
137
+ shortcut: typeof result.shortcut === 'boolean' ? result.shortcut : (prev ? prev.shortcut : false),
138
+ error: '',
139
+ diag: result.diag || '',
140
+ }))
141
+ } else {
142
+ setSnap((prev) => ({
143
+ desktop: typeof result.desktop === 'boolean' ? result.desktop : (prev ? prev.desktop : null),
144
+ shortcut: prev ? prev.shortcut : false,
145
+ error: (result && result.error) || '操作失败',
146
+ diag: (result && result.diag) || (prev ? prev.diag : ''),
147
+ }))
148
+ }
149
+ } catch (error) {
150
+ setSnap((prev) => ({ desktop: prev ? prev.desktop : null, shortcut: prev ? prev.shortcut : false, error: '操作失败:' + errText(error), diag: prev ? prev.diag : '' }))
151
+ } finally {
152
+ setBusy(false)
153
+ setPending(null)
154
+ }
155
+ }
156
+
157
+ const toggle = async () => {
158
+ if (busy) return
159
+ const target = !(snap && snap.desktop === true)
160
+ if (target === false) {
161
+ setConfirmOpen(true)
162
+ return
163
+ }
164
+ await performToggle(true)
165
+ }
166
+
167
+ const addLink = async () => {
168
+ if (linkBusy) return
169
+ setLinkBusy(true)
170
+ try {
171
+ const result = await api.setShortcut()
172
+ if (result && result.ok) {
173
+ setSnap((prev) => ({ ...(prev || { desktop: null, shortcut: false, diag: '' }), shortcut: true, error: '', diag: result.diag || (prev ? prev.diag : '') }))
174
+ } else {
175
+ setSnap((prev) => ({ ...(prev || { desktop: null, shortcut: false, diag: '' }), error: (result && result.error) || '添加快捷方式失败', diag: (result && result.diag) || (prev ? prev.diag : '') }))
176
+ }
177
+ } catch (error) {
178
+ setSnap((prev) => ({ ...(prev || { desktop: null, shortcut: false, diag: '' }), error: '添加快捷方式失败:' + errText(error) }))
179
+ } finally {
180
+ setLinkBusy(false)
181
+ }
182
+ }
183
+
184
+ const desktop = snap ? snap.desktop : null
185
+ const shortcut = snap ? snap.shortcut : false
186
+ const checked = pending ? pending === 'on' : desktop === true
187
+ const stateText = pending
188
+ ? (pending === 'on' ? '正在启动…' : '正在退出…')
189
+ : desktop === true ? '运行中' : desktop === false ? '已停止' : '状态未知'
190
+ const dotClass = 'tauri-dsl-dot' + (pending ? ' tauri-dsl-dot-pending' : desktop === true ? ' tauri-dsl-dot-on' : desktop === null ? ' tauri-dsl-dot-unknown' : '')
191
+
192
+ return React.createElement('div', { className: 'tauri-dsl-root' },
193
+ React.createElement('div', { className: 'tauri-dsl-desc' }, '启动或退出本机桌面应用(DeepSeek Harness Tauri)。开启时自动创建桌面快捷方式,关闭时自动删除;开机启动与全局快捷键请在桌面应用托盘 → 设置中管理。'),
194
+ React.createElement('label', { className: 'tauri-dsl-row' },
195
+ React.createElement('div', { className: 'tauri-dsl-left' },
196
+ React.createElement('span', { className: 'tauri-dsl-label' }, '桌面端启动'),
197
+ React.createElement('span', { className: 'tauri-dsl-state' },
198
+ React.createElement('span', { className: dotClass }),
199
+ stateText,
200
+ ),
201
+ ),
202
+ React.createElement('span', { className: 'tauri-dsl-switch' },
203
+ React.createElement('input', { type: 'checkbox', checked, onChange: toggle, disabled: busy }),
204
+ React.createElement('span', { className: 'tauri-dsl-track' }),
205
+ ),
206
+ ),
207
+ desktop === true && !pending ? React.createElement('button', {
208
+ className: 'tauri-dsl-linkbtn',
209
+ onClick: addLink,
210
+ disabled: linkBusy || shortcut,
211
+ }, shortcut ? '已添加快捷方式' : '添加快捷方式') : null,
212
+ snap && snap.error ? React.createElement('div', { className: 'tauri-dsl-error' }, snap.error) : null,
213
+ snap && snap.error && snap.diag ? React.createElement('details', { className: 'tauri-dsl-details' },
214
+ React.createElement('summary', null, '诊断信息'),
215
+ React.createElement('pre', { className: 'tauri-dsl-diag' }, snap.diag),
216
+ ) : null,
217
+ confirmOpen ? React.createElement('div', { className: 'tauri-dsl-overlay', onClick: () => setConfirmOpen(false) },
218
+ React.createElement('div', { className: 'tauri-dsl-dialog', onClick: (event) => event.stopPropagation() },
219
+ React.createElement('div', { className: 'tauri-dsl-dialog-title' }, '确定关闭桌面端启动?'),
220
+ React.createElement('div', { className: 'tauri-dsl-dialog-body' }, '桌面应用将退出,同时删除桌面快捷方式。之后可随时在设置中重新开启,或通过命令行启动。'),
221
+ React.createElement('div', { className: 'tauri-dsl-dialog-actions' },
222
+ React.createElement('button', { className: 'tauri-dsl-btn-ghost', onClick: () => setConfirmOpen(false) }, '✗ 取消'),
223
+ React.createElement('button', {
224
+ className: 'tauri-dsl-btn-primary',
225
+ onClick: () => { setConfirmOpen(false); void performToggle(false) },
226
+ }, '✓ 确认关闭'),
227
+ ),
228
+ ),
229
+ ) : null,
230
+ )
231
+ }
232
+
233
+ slots.inject('settings.section', () => slots.register(
234
+ { name: 'settings.section', id: 'desktop-launch', order: 30, label: '桌面启动' },
235
+ () => React.createElement(DesktopSection, null),
236
+ ))
237
+ }
238
+
239
+ return module.exports
240
+ },
241
+ })