@lokvis/ui-react 0.2.1 → 0.4.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.
- package/dist/components/AssetPanel.d.ts.map +1 -1
- package/dist/components/AssetPanel.js +18 -62
- package/dist/components/AssetPanel.js.map +1 -1
- package/dist/components/Canvas.d.ts +4 -4
- package/dist/components/Canvas.d.ts.map +1 -1
- package/dist/components/Canvas.js +9 -9
- package/dist/components/Canvas.js.map +1 -1
- package/dist/components/CommandPalette.d.ts +7 -7
- package/dist/components/CommandPalette.d.ts.map +1 -1
- package/dist/components/CommandPalette.js +10 -10
- package/dist/components/CommandPalette.js.map +1 -1
- package/dist/components/CompareSlider.d.ts +9 -8
- package/dist/components/CompareSlider.d.ts.map +1 -1
- package/dist/components/CompareSlider.js +10 -9
- package/dist/components/CompareSlider.js.map +1 -1
- package/dist/components/DownloadPanel.d.ts +3 -3
- package/dist/components/DownloadPanel.d.ts.map +1 -1
- package/dist/components/DownloadPanel.js +10 -17
- package/dist/components/DownloadPanel.js.map +1 -1
- package/dist/components/ErrorBanner.d.ts +2 -2
- package/dist/components/ErrorBanner.d.ts.map +1 -1
- package/dist/components/ErrorBanner.js +3 -3
- package/dist/components/ErrorBanner.js.map +1 -1
- package/dist/components/ErrorBoundary.d.ts +40 -0
- package/dist/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/components/ErrorBoundary.js +52 -0
- package/dist/components/ErrorBoundary.js.map +1 -0
- package/dist/components/ExifPanel.d.ts +1 -1
- package/dist/components/ExifPanel.d.ts.map +1 -1
- package/dist/components/ExifPanel.js +2 -2
- package/dist/components/ExifPanel.js.map +1 -1
- package/dist/components/GlobalDropzone.d.ts +5 -5
- package/dist/components/GlobalDropzone.d.ts.map +1 -1
- package/dist/components/GlobalDropzone.js +15 -8
- package/dist/components/GlobalDropzone.js.map +1 -1
- package/dist/components/HistoryPanel.d.ts +2 -2
- package/dist/components/HistoryPanel.d.ts.map +1 -1
- package/dist/components/HistoryPanel.js +23 -23
- package/dist/components/HistoryPanel.js.map +1 -1
- package/dist/components/Inspector.d.ts.map +1 -1
- package/dist/components/Inspector.js +13 -10
- package/dist/components/Inspector.js.map +1 -1
- package/dist/components/ParamForm.d.ts.map +1 -1
- package/dist/components/ParamForm.js +10 -7
- package/dist/components/ParamForm.js.map +1 -1
- package/dist/components/PipelineBar.d.ts.map +1 -1
- package/dist/components/PipelineBar.js +19 -28
- package/dist/components/PipelineBar.js.map +1 -1
- package/dist/components/ProgressBar.d.ts +4 -4
- package/dist/components/ProgressBar.d.ts.map +1 -1
- package/dist/components/ProgressBar.js +8 -8
- package/dist/components/ProgressBar.js.map +1 -1
- package/dist/components/StatusBar.d.ts +3 -3
- package/dist/components/StatusBar.d.ts.map +1 -1
- package/dist/components/StatusBar.js +12 -21
- package/dist/components/StatusBar.js.map +1 -1
- package/dist/components/StatusDot.d.ts +12 -0
- package/dist/components/StatusDot.d.ts.map +1 -0
- package/dist/components/StatusDot.js +15 -0
- package/dist/components/StatusDot.js.map +1 -0
- package/dist/components/ThemeToggle.d.ts +4 -4
- package/dist/components/ThemeToggle.d.ts.map +1 -1
- package/dist/components/ThemeToggle.js +7 -7
- package/dist/components/ThemeToggle.js.map +1 -1
- package/dist/components/ToolRunner.d.ts +53 -0
- package/dist/components/ToolRunner.d.ts.map +1 -0
- package/dist/components/ToolRunner.js +142 -0
- package/dist/components/ToolRunner.js.map +1 -0
- package/dist/components/Toolbar.d.ts.map +1 -1
- package/dist/components/Toolbar.js +3 -3
- package/dist/components/Toolbar.js.map +1 -1
- package/dist/components/WorkflowEditor.d.ts +6 -6
- package/dist/components/WorkflowEditor.d.ts.map +1 -1
- package/dist/components/WorkflowEditor.js +40 -49
- package/dist/components/WorkflowEditor.js.map +1 -1
- package/dist/components/WorkflowTemplates.d.ts +2 -2
- package/dist/components/WorkflowTemplates.d.ts.map +1 -1
- package/dist/components/WorkflowTemplates.js +17 -7
- package/dist/components/WorkflowTemplates.js.map +1 -1
- package/dist/components/Workspace.d.ts +45 -23
- package/dist/components/Workspace.d.ts.map +1 -1
- package/dist/components/Workspace.js +87 -40
- package/dist/components/Workspace.js.map +1 -1
- package/dist/hooks/useCustomPresets.d.ts +98 -0
- package/dist/hooks/useCustomPresets.d.ts.map +1 -0
- package/dist/hooks/useCustomPresets.js +210 -0
- package/dist/hooks/useCustomPresets.js.map +1 -0
- package/dist/hooks/useLokvis.d.ts +19 -1
- package/dist/hooks/useLokvis.d.ts.map +1 -1
- package/dist/hooks/useLokvis.js +30 -9
- package/dist/hooks/useLokvis.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/store/assets-slice.d.ts +8 -1
- package/dist/store/assets-slice.d.ts.map +1 -1
- package/dist/store/assets-slice.js +101 -54
- package/dist/store/assets-slice.js.map +1 -1
- package/dist/store/capabilities-slice.d.ts +1 -1
- package/dist/store/capabilities-slice.d.ts.map +1 -1
- package/dist/store/capabilities-slice.js +8 -1
- package/dist/store/capabilities-slice.js.map +1 -1
- package/dist/store/index.d.ts +1 -1
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +1 -1
- package/dist/store/index.js.map +1 -1
- package/dist/store/runtime-slice.d.ts.map +1 -1
- package/dist/store/runtime-slice.js +22 -16
- package/dist/store/runtime-slice.js.map +1 -1
- package/dist/store/subscribe-utils.d.ts +45 -0
- package/dist/store/subscribe-utils.d.ts.map +1 -0
- package/dist/store/subscribe-utils.js +69 -0
- package/dist/store/subscribe-utils.js.map +1 -0
- package/dist/store/types.d.ts +19 -11
- package/dist/store/types.d.ts.map +1 -1
- package/dist/store/types.js +0 -10
- package/dist/store/types.js.map +1 -1
- package/dist/store/workflow-slice.d.ts +1 -1
- package/dist/store/workflow-slice.d.ts.map +1 -1
- package/dist/store/workflow-slice.js +19 -51
- package/dist/store/workflow-slice.js.map +1 -1
- package/dist/utils.d.ts +24 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +31 -0
- package/dist/utils.js.map +1 -0
- package/package.json +7 -6
- package/src/components/AssetPanel.tsx +224 -264
- package/src/components/Canvas.tsx +178 -174
- package/src/components/CommandPalette.tsx +242 -242
- package/src/components/CompareSlider.tsx +168 -165
- package/src/components/DownloadPanel.tsx +201 -207
- package/src/components/ErrorBanner.tsx +64 -64
- package/src/components/ErrorBoundary.tsx +101 -0
- package/src/components/ExifPanel.tsx +154 -154
- package/src/components/GlobalDropzone.tsx +175 -170
- package/src/components/HistoryPanel.tsx +219 -219
- package/src/components/Inspector.tsx +145 -137
- package/src/components/ParamForm.tsx +140 -137
- package/src/components/PipelineBar.tsx +97 -104
- package/src/components/ProgressBar.tsx +78 -78
- package/src/components/StatusBar.tsx +145 -152
- package/src/components/StatusDot.tsx +27 -0
- package/src/components/ThemeToggle.tsx +98 -98
- package/src/components/ToolRunner.tsx +352 -0
- package/src/components/Toolbar.tsx +65 -65
- package/src/components/WorkflowEditor.tsx +333 -326
- package/src/components/WorkflowTemplates.tsx +101 -78
- package/src/components/Workspace.tsx +310 -223
- package/src/css-modules.d.ts +3 -0
- package/src/hooks/useCustomPresets.ts +284 -0
- package/src/hooks/useLokvis.ts +43 -10
- package/src/index.ts +7 -0
- package/src/store/assets-slice.ts +106 -52
- package/src/store/capabilities-slice.ts +10 -2
- package/src/store/index.ts +1 -1
- package/src/store/runtime-slice.ts +20 -15
- package/src/store/subscribe-utils.ts +82 -0
- package/src/store/types.ts +19 -12
- package/src/store/workflow-slice.ts +19 -53
- package/src/utils.ts +41 -0
- package/dist/store.d.ts +0 -76
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -217
- package/dist/store.js.map +0 -1
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useCustomPresets - 自定义尺寸预设持久化 hook(W17.5)
|
|
3
|
+
*
|
|
4
|
+
* 提供用户自定义图像尺寸预设的本地保存能力(免费 3 / Pro 无限)。
|
|
5
|
+
* 数据存储在 localStorage 的 `lokvis.customPresets` key,JSON 数组形式。
|
|
6
|
+
*
|
|
7
|
+
* 与 useWorkflows 的区别:
|
|
8
|
+
* - 自定义预设是尺寸配置(name/width/height/fit/format),轻量
|
|
9
|
+
* - 工作流槽位是完整 Workflow 定义(含 nodes/edges/inputs/outputs)
|
|
10
|
+
*
|
|
11
|
+
* 与 PLATFORM_PRESETS 的区别:
|
|
12
|
+
* - PLATFORM_PRESETS 是内置的固定预设(YouTube/TikTok 等平台标准尺寸)
|
|
13
|
+
* - 自定义预设是用户自建的任意尺寸配置,自由命名
|
|
14
|
+
*
|
|
15
|
+
* id 命名空间约定:自定义预设 id 以 `custom.` 前缀,与内置预设区分
|
|
16
|
+
* (如 `custom.my-instagram-square`),避免 PlatformPresetSelector 冲突。
|
|
17
|
+
*
|
|
18
|
+
* 多 tab / 多实例同步:
|
|
19
|
+
* - 原生 storage 事件:跨 tab 同步
|
|
20
|
+
* - 自定义 SYNC_EVENT:同 tab 多实例同步
|
|
21
|
+
*
|
|
22
|
+
* @module useCustomPresets
|
|
23
|
+
*/
|
|
24
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
25
|
+
const STORAGE_KEY = 'lokvis.customPresets';
|
|
26
|
+
/** 同 tab 多实例同步用的自定义事件名 */
|
|
27
|
+
const SYNC_EVENT = 'lokvis:custom-presets-change';
|
|
28
|
+
/** 免费用户自定义预设上限 */
|
|
29
|
+
export const FREE_PRESET_LIMIT = 3;
|
|
30
|
+
/** Pro 用户无上限 */
|
|
31
|
+
export const PRO_PRESET_LIMIT = Infinity;
|
|
32
|
+
/** 类型守卫:判断 unknown 是否为 Record<string, unknown> */
|
|
33
|
+
function isRecord(x) {
|
|
34
|
+
return typeof x === 'object' && x !== null;
|
|
35
|
+
}
|
|
36
|
+
const VALID_FIT_STRATEGIES = ['cover', 'contain', 'fill', 'inside', 'outside'];
|
|
37
|
+
const VALID_FORMATS = ['png', 'jpeg', 'webp'];
|
|
38
|
+
/** 从 localStorage 读取自定义预设。
|
|
39
|
+
* 容错:JSON 解析失败 / 非数组 / 字段缺失时返回空数组。
|
|
40
|
+
*
|
|
41
|
+
* 导出供测试直接调用(避免渲染 React 组件)。 */
|
|
42
|
+
export function readCustomPresetsFromStorage() {
|
|
43
|
+
if (typeof window === 'undefined')
|
|
44
|
+
return [];
|
|
45
|
+
try {
|
|
46
|
+
const raw = window.localStorage.getItem(STORAGE_KEY);
|
|
47
|
+
if (!raw)
|
|
48
|
+
return [];
|
|
49
|
+
const parsed = JSON.parse(raw);
|
|
50
|
+
if (!Array.isArray(parsed))
|
|
51
|
+
return [];
|
|
52
|
+
// 字段白名单过滤(防御损坏数据)
|
|
53
|
+
const result = parsed.filter((it) => {
|
|
54
|
+
if (!isRecord(it))
|
|
55
|
+
return false;
|
|
56
|
+
if (typeof it.id !== 'string' ||
|
|
57
|
+
typeof it.name !== 'string' ||
|
|
58
|
+
typeof it.width !== 'number' ||
|
|
59
|
+
typeof it.height !== 'number' ||
|
|
60
|
+
typeof it.fit !== 'string' ||
|
|
61
|
+
typeof it.createdAt !== 'number' ||
|
|
62
|
+
typeof it.updatedAt !== 'number') {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
// id 必须以 custom. 前缀开头,与内置 PLATFORM_PRESETS 隔离
|
|
66
|
+
if (!it.id.startsWith('custom.'))
|
|
67
|
+
return false;
|
|
68
|
+
// fit 必须是合法值
|
|
69
|
+
if (!VALID_FIT_STRATEGIES.includes(it.fit)) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
// format 可选,若有则必须是合法值
|
|
73
|
+
if (it.format !== undefined && !VALID_FORMATS.includes(it.format)) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
// width / height 必须为正整数
|
|
77
|
+
if (it.width <= 0 || it.height <= 0)
|
|
78
|
+
return false;
|
|
79
|
+
return true;
|
|
80
|
+
});
|
|
81
|
+
// 按 updatedAt 降序(最新在前),与接口契约一致
|
|
82
|
+
result.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
console.warn('[lokvis] Failed to read custom presets from storage');
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* 写入 localStorage。
|
|
92
|
+
* @returns true 成功;false 失败(隐私模式 / 配额超限 / 序列化异常)
|
|
93
|
+
*
|
|
94
|
+
* 导出供测试直接调用。
|
|
95
|
+
*/
|
|
96
|
+
export function writeCustomPresetsToStorage(presets) {
|
|
97
|
+
if (typeof window === 'undefined')
|
|
98
|
+
return false;
|
|
99
|
+
try {
|
|
100
|
+
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(presets));
|
|
101
|
+
window.dispatchEvent(new CustomEvent(SYNC_EVENT));
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
console.warn('[lokvis] Failed to persist custom presets to localStorage:', err);
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/** 生成唯一 ID(custom. 前缀,与内置预设命名空间隔离) */
|
|
110
|
+
export function genCustomPresetId() {
|
|
111
|
+
const rand = Math.random().toString(36).slice(2, 8);
|
|
112
|
+
return `custom.${Date.now()}-${rand}`;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* @param isPro 是否为 Pro 模式。父组件从 runtime.isPro 传入。
|
|
116
|
+
* 影响 limit:免费 3 / Pro 无上限。
|
|
117
|
+
*/
|
|
118
|
+
export function useCustomPresets(isPro = false) {
|
|
119
|
+
const limit = isPro ? PRO_PRESET_LIMIT : FREE_PRESET_LIMIT;
|
|
120
|
+
const [presets, setPresets] = useState(() => readCustomPresetsFromStorage());
|
|
121
|
+
// 监听跨 tab storage + 同 tab SYNC_EVENT
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
const handler = () => setPresets(readCustomPresetsFromStorage());
|
|
124
|
+
window.addEventListener('storage', handler);
|
|
125
|
+
window.addEventListener(SYNC_EVENT, handler);
|
|
126
|
+
return () => {
|
|
127
|
+
window.removeEventListener('storage', handler);
|
|
128
|
+
window.removeEventListener(SYNC_EVENT, handler);
|
|
129
|
+
};
|
|
130
|
+
}, []);
|
|
131
|
+
const save = useCallback((input) => {
|
|
132
|
+
// 输入校验
|
|
133
|
+
if (input.width <= 0 || input.height <= 0) {
|
|
134
|
+
throw new Error('预设尺寸必须为正数');
|
|
135
|
+
}
|
|
136
|
+
if (!input.name.trim()) {
|
|
137
|
+
throw new Error('预设名称不能为空');
|
|
138
|
+
}
|
|
139
|
+
const current = readCustomPresetsFromStorage();
|
|
140
|
+
const now = Date.now();
|
|
141
|
+
// 更新已有
|
|
142
|
+
if (input.id) {
|
|
143
|
+
const existing = current.find((p) => p.id === input.id);
|
|
144
|
+
if (existing) {
|
|
145
|
+
const updated = {
|
|
146
|
+
...existing,
|
|
147
|
+
name: input.name,
|
|
148
|
+
width: input.width,
|
|
149
|
+
height: input.height,
|
|
150
|
+
fit: input.fit ?? existing.fit,
|
|
151
|
+
format: input.format ?? existing.format,
|
|
152
|
+
updatedAt: now,
|
|
153
|
+
};
|
|
154
|
+
const next = current.map((p) => (p.id === input.id ? updated : p));
|
|
155
|
+
const ok = writeCustomPresetsToStorage(next);
|
|
156
|
+
if (!ok) {
|
|
157
|
+
console.warn('[lokvis] 自定义预设未持久化到 localStorage,仅当前会话有效');
|
|
158
|
+
}
|
|
159
|
+
setPresets(next);
|
|
160
|
+
return updated;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// 新增
|
|
164
|
+
if (current.length >= limit) {
|
|
165
|
+
throw new Error(`自定义预设已达上限(${limit} 个)${isPro ? '' : ',升级 Pro 可无限制保存'}`);
|
|
166
|
+
}
|
|
167
|
+
const preset = {
|
|
168
|
+
id: genCustomPresetId(),
|
|
169
|
+
name: input.name,
|
|
170
|
+
width: input.width,
|
|
171
|
+
height: input.height,
|
|
172
|
+
fit: input.fit ?? 'cover',
|
|
173
|
+
format: input.format,
|
|
174
|
+
createdAt: now,
|
|
175
|
+
updatedAt: now,
|
|
176
|
+
};
|
|
177
|
+
const next = [...current, preset];
|
|
178
|
+
const ok = writeCustomPresetsToStorage(next);
|
|
179
|
+
if (!ok) {
|
|
180
|
+
console.warn('[lokvis] 自定义预设未持久化到 localStorage,仅当前会话有效');
|
|
181
|
+
}
|
|
182
|
+
setPresets(next);
|
|
183
|
+
return preset;
|
|
184
|
+
}, [limit, isPro]);
|
|
185
|
+
const remove = useCallback((id) => {
|
|
186
|
+
const current = readCustomPresetsFromStorage();
|
|
187
|
+
const next = current.filter((p) => p.id !== id);
|
|
188
|
+
const ok = writeCustomPresetsToStorage(next);
|
|
189
|
+
if (!ok) {
|
|
190
|
+
console.warn('[lokvis] Failed to persist custom presets removal');
|
|
191
|
+
}
|
|
192
|
+
setPresets(next);
|
|
193
|
+
}, []);
|
|
194
|
+
const get = useCallback((id) => {
|
|
195
|
+
const current = readCustomPresetsFromStorage();
|
|
196
|
+
return current.find((p) => p.id === id) ?? null;
|
|
197
|
+
}, []);
|
|
198
|
+
const canSaveMore = presets.length < limit;
|
|
199
|
+
const remaining = Math.max(0, limit - presets.length);
|
|
200
|
+
return {
|
|
201
|
+
presets,
|
|
202
|
+
save,
|
|
203
|
+
remove,
|
|
204
|
+
get,
|
|
205
|
+
limit,
|
|
206
|
+
canSaveMore,
|
|
207
|
+
remaining,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=useCustomPresets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCustomPresets.js","sourceRoot":"","sources":["../../src/hooks/useCustomPresets.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,14 +14,32 @@
|
|
|
14
14
|
* return <Workspace />;
|
|
15
15
|
* }
|
|
16
16
|
* ```
|
|
17
|
+
*
|
|
18
|
+
* @example 接 cloud session(W17.6)
|
|
19
|
+
* ```tsx
|
|
20
|
+
* const { runtime } = useLokvis({
|
|
21
|
+
* plugins: [imageToolsPlugin()],
|
|
22
|
+
* auth: { session: cloudJwt }, // → isPro: true,批量/槽位无上限
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
17
25
|
*/
|
|
18
26
|
import type { LokvisRuntime, RuntimeConfig } from '@lokvis/runtime';
|
|
19
|
-
import type { PluginLoadEntry } from '@lokvis/sdk';
|
|
27
|
+
import type { LokvisAuthSession, PluginLoadEntry } from '@lokvis/sdk';
|
|
20
28
|
export interface UseLokvisOptions extends RuntimeConfig {
|
|
21
29
|
/** 预加载的插件列表 */
|
|
22
30
|
plugins?: PluginLoadEntry[];
|
|
23
31
|
/** 是否在挂载时自动初始化(默认 true) */
|
|
24
32
|
autoInit?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Cloud 注入的认证信息(W17.3 / W17.6)。
|
|
35
|
+
*
|
|
36
|
+
* 透传到 `createLokvis({ auth })`,SDK 据 presence 推导 `isPro`:
|
|
37
|
+
* - 传入非空 `session` 或 `token` 且未显式 `isPro: false` → Pro 模式
|
|
38
|
+
* - 不传 `auth`:保持 free 模式
|
|
39
|
+
*
|
|
40
|
+
* 详见 `@lokvis/sdk` 的 `LokvisAuthSession` 与 `resolveIsPro()` 文档。
|
|
41
|
+
*/
|
|
42
|
+
auth?: LokvisAuthSession;
|
|
25
43
|
}
|
|
26
44
|
export interface UseLokvisResult {
|
|
27
45
|
runtime: LokvisRuntime | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLokvis.d.ts","sourceRoot":"","sources":["../../src/hooks/useLokvis.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"useLokvis.d.ts","sourceRoot":"","sources":["../../src/hooks/useLokvis.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGtE,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACrD,eAAe;IACf,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,iBAAiB,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC;IACpD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,eAAe,CAuDzE"}
|
package/dist/hooks/useLokvis.js
CHANGED
|
@@ -14,33 +14,55 @@
|
|
|
14
14
|
* return <Workspace />;
|
|
15
15
|
* }
|
|
16
16
|
* ```
|
|
17
|
+
*
|
|
18
|
+
* @example 接 cloud session(W17.6)
|
|
19
|
+
* ```tsx
|
|
20
|
+
* const { runtime } = useLokvis({
|
|
21
|
+
* plugins: [imageToolsPlugin()],
|
|
22
|
+
* auth: { session: cloudJwt }, // → isPro: true,批量/槽位无上限
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
17
25
|
*/
|
|
18
26
|
import { useEffect, useRef, useState } from 'react';
|
|
19
27
|
import { createLokvis } from '@lokvis/sdk';
|
|
20
28
|
import { useWorkspaceStore } from '../store/index.js';
|
|
21
29
|
export function useLokvis(options = {}) {
|
|
22
|
-
const { plugins = [], autoInit = true, ...runtimeConfig } = options;
|
|
30
|
+
const { plugins = [], autoInit = true, auth, ...runtimeConfig } = options;
|
|
23
31
|
const [runtime, setRuntime] = useState(null);
|
|
24
32
|
const [status, setStatus] = useState('idle');
|
|
25
33
|
const [error, setError] = useState(null);
|
|
26
|
-
const initRef = useRef(false);
|
|
27
34
|
const storeInit = useWorkspaceStore((s) => s.init);
|
|
35
|
+
// 用 useRef 持有 plugins / runtimeConfig / auth / storeInit 的最新值,
|
|
36
|
+
// 避免 effect 依赖这些对象引用导致每次 render 都重新初始化 runtime。
|
|
37
|
+
// effect 仅在 authKey / autoInit 变化时触发,内部从 ref 读取当前值。
|
|
38
|
+
const pluginsRef = useRef(plugins);
|
|
39
|
+
const runtimeConfigRef = useRef(runtimeConfig);
|
|
40
|
+
const authRef = useRef(auth);
|
|
41
|
+
const storeInitRef = useRef(storeInit);
|
|
42
|
+
pluginsRef.current = plugins;
|
|
43
|
+
runtimeConfigRef.current = runtimeConfig;
|
|
44
|
+
authRef.current = auth;
|
|
45
|
+
storeInitRef.current = storeInit;
|
|
46
|
+
// 用 JSON.stringify(auth) 作为 effect 依赖,使 auth 变化时重新初始化。
|
|
47
|
+
// (auth 是对象,直接放依赖数组会因引用变化每次 render 都触发;
|
|
48
|
+
// JSON.stringify 提供稳定的 primitive 依赖,只在 auth 内容变化时重 init)
|
|
49
|
+
const authKey = JSON.stringify(auth ?? null);
|
|
28
50
|
useEffect(() => {
|
|
29
|
-
if (!autoInit
|
|
51
|
+
if (!autoInit)
|
|
30
52
|
return;
|
|
31
|
-
initRef.current = true;
|
|
32
53
|
let cancelled = false;
|
|
33
54
|
(async () => {
|
|
34
55
|
try {
|
|
35
56
|
setStatus('initializing');
|
|
36
57
|
const rt = await createLokvis({
|
|
37
|
-
...
|
|
38
|
-
plugins,
|
|
58
|
+
...runtimeConfigRef.current,
|
|
59
|
+
plugins: pluginsRef.current,
|
|
60
|
+
auth: authRef.current,
|
|
39
61
|
});
|
|
40
62
|
if (cancelled)
|
|
41
63
|
return;
|
|
42
64
|
setRuntime(rt);
|
|
43
|
-
await
|
|
65
|
+
await storeInitRef.current(rt);
|
|
44
66
|
if (cancelled)
|
|
45
67
|
return;
|
|
46
68
|
setStatus('ready');
|
|
@@ -55,8 +77,7 @@ export function useLokvis(options = {}) {
|
|
|
55
77
|
return () => {
|
|
56
78
|
cancelled = true;
|
|
57
79
|
};
|
|
58
|
-
|
|
59
|
-
}, []);
|
|
80
|
+
}, [authKey, autoInit]);
|
|
60
81
|
return { runtime, status, error };
|
|
61
82
|
}
|
|
62
83
|
//# sourceMappingURL=useLokvis.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLokvis.js","sourceRoot":"","sources":["../../src/hooks/useLokvis.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"useLokvis.js","sourceRoot":"","sources":["../../src/hooks/useLokvis.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAyBtD,MAAM,UAAU,SAAS,CAAC,UAA4B,EAAE;IACtD,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,IAAI,EAAE,IAAI,EAAE,GAAG,aAAa,EAAE,GAAG,OAAO,CAAC;IAC1E,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAuB,IAAI,CAAC,CAAC;IACnE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAA4B,MAAM,CAAC,CAAC;IACxE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAExD,MAAM,SAAS,GAAG,iBAAiB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAEnD,+DAA+D;IAC/D,gDAAgD;IAChD,oDAAoD;IACpD,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,gBAAgB,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IACvC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAC7B,gBAAgB,CAAC,OAAO,GAAG,aAAa,CAAC;IACzC,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IACvB,YAAY,CAAC,OAAO,GAAG,SAAS,CAAC;IAEjC,uDAAuD;IACvD,wCAAwC;IACxC,0DAA0D;IAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;IAE7C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,CAAC,KAAK,IAAI,EAAE;YACV,IAAI,CAAC;gBACH,SAAS,CAAC,cAAc,CAAC,CAAC;gBAC1B,MAAM,EAAE,GAAG,MAAM,YAAY,CAAC;oBAC5B,GAAG,gBAAgB,CAAC,OAAO;oBAC3B,OAAO,EAAE,UAAU,CAAC,OAAO;oBAC3B,IAAI,EAAE,OAAO,CAAC,OAAO;iBACtB,CAAC,CAAC;gBACH,IAAI,SAAS;oBAAE,OAAO;gBACtB,UAAU,CAAC,EAAE,CAAC,CAAC;gBACf,MAAM,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBAC/B,IAAI,SAAS;oBAAE,OAAO;gBACtB,SAAS,CAAC,OAAO,CAAC,CAAC;YACrB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,SAAS;oBAAE,OAAO;gBACtB,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC3D,SAAS,CAAC,OAAO,CAAC,CAAC;YACrB,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QAEL,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAExB,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACpC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -22,14 +22,17 @@
|
|
|
22
22
|
* - `useMediaQuery()` / `useBreakpoints()` - Responsive hooks (W9.8)
|
|
23
23
|
* - `useCommandPalette()` - ⌘K shortcut registration hook (W9.2)
|
|
24
24
|
*/
|
|
25
|
+
import '@lokvis/ui-core/styles.css';
|
|
25
26
|
export { useLokvis, type UseLokvisOptions, type UseLokvisResult } from './hooks/useLokvis.js';
|
|
26
27
|
export { useTheme, type UseThemeResult, type ThemeMode } from './hooks/useTheme.js';
|
|
27
28
|
export { useMediaQuery, useBreakpoints, type Breakpoints } from './hooks/useMediaQuery.js';
|
|
28
29
|
export { useWorkflows, FREE_WORKFLOW_LIMIT, PRO_WORKFLOW_LIMIT, type UseWorkflowsResult, type WorkflowSlot, type SaveWorkflowInput } from './hooks/useWorkflows.js';
|
|
30
|
+
export { useCustomPresets, FREE_PRESET_LIMIT, PRO_PRESET_LIMIT, readCustomPresetsFromStorage, writeCustomPresetsToStorage, genCustomPresetId, type UseCustomPresetsResult, type CustomSizePreset, type SavePresetInput } from './hooks/useCustomPresets.js';
|
|
29
31
|
export { useDebouncedRun, type UseDebouncedRunOptions, type UseDebouncedRunResult } from './hooks/useDebouncedRun.js';
|
|
30
32
|
export { useShareLink, type UseShareLinkResult, encodeWorkflowForShare, decodeWorkflowFromShare } from './hooks/useShareLink.js';
|
|
31
33
|
export { useWorkspaceStore, type WorkspaceState, type WorkspaceActions } from './store/index.js';
|
|
32
34
|
export { Workspace, type WorkspaceProps } from './components/Workspace.js';
|
|
35
|
+
export { ErrorBoundary, type ErrorBoundaryProps } from './components/ErrorBoundary.js';
|
|
33
36
|
export { AssetPanel } from './components/AssetPanel.js';
|
|
34
37
|
export { Canvas } from './components/Canvas.js';
|
|
35
38
|
export { Inspector } from './components/Inspector.js';
|
|
@@ -48,6 +51,7 @@ export { GlobalDropzone, type GlobalDropzoneProps } from './components/GlobalDro
|
|
|
48
51
|
export { CompareSlider, type CompareSliderProps } from './components/CompareSlider.js';
|
|
49
52
|
export { DownloadPanel, type DownloadPanelProps } from './components/DownloadPanel.js';
|
|
50
53
|
export { ThemeToggle, type ThemeToggleProps } from './components/ThemeToggle.js';
|
|
54
|
+
export { ToolRunner, type ToolRunnerProps } from './components/ToolRunner.js';
|
|
51
55
|
export { WORKFLOW_TEMPLATES, type WorkflowTemplate, type WorkflowTemplateNode, findTemplate, } from './data/workflow-templates.js';
|
|
52
56
|
export type { WorkspaceEvent, NodeStatus, } from './types.js';
|
|
53
57
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -22,14 +22,19 @@
|
|
|
22
22
|
* - `useMediaQuery()` / `useBreakpoints()` - Responsive hooks (W9.8)
|
|
23
23
|
* - `useCommandPalette()` - ⌘K shortcut registration hook (W9.2)
|
|
24
24
|
*/
|
|
25
|
+
// 引入设计 token(--lokvis-* CSS 变量),消费方无需手动 import styles.css。
|
|
26
|
+
// sideEffects: ["**/*.css"] 保证 bundler 不 tree-shake 此 import。
|
|
27
|
+
import '@lokvis/ui-core/styles.css';
|
|
25
28
|
export { useLokvis } from './hooks/useLokvis.js';
|
|
26
29
|
export { useTheme } from './hooks/useTheme.js';
|
|
27
30
|
export { useMediaQuery, useBreakpoints } from './hooks/useMediaQuery.js';
|
|
28
31
|
export { useWorkflows, FREE_WORKFLOW_LIMIT, PRO_WORKFLOW_LIMIT } from './hooks/useWorkflows.js';
|
|
32
|
+
export { useCustomPresets, FREE_PRESET_LIMIT, PRO_PRESET_LIMIT, readCustomPresetsFromStorage, writeCustomPresetsToStorage, genCustomPresetId } from './hooks/useCustomPresets.js';
|
|
29
33
|
export { useDebouncedRun } from './hooks/useDebouncedRun.js';
|
|
30
34
|
export { useShareLink, encodeWorkflowForShare, decodeWorkflowFromShare } from './hooks/useShareLink.js';
|
|
31
35
|
export { useWorkspaceStore } from './store/index.js';
|
|
32
36
|
export { Workspace } from './components/Workspace.js';
|
|
37
|
+
export { ErrorBoundary } from './components/ErrorBoundary.js';
|
|
33
38
|
export { AssetPanel } from './components/AssetPanel.js';
|
|
34
39
|
export { Canvas } from './components/Canvas.js';
|
|
35
40
|
export { Inspector } from './components/Inspector.js';
|
|
@@ -48,5 +53,6 @@ export { GlobalDropzone } from './components/GlobalDropzone.js';
|
|
|
48
53
|
export { CompareSlider } from './components/CompareSlider.js';
|
|
49
54
|
export { DownloadPanel } from './components/DownloadPanel.js';
|
|
50
55
|
export { ThemeToggle } from './components/ThemeToggle.js';
|
|
56
|
+
export { ToolRunner } from './components/ToolRunner.js';
|
|
51
57
|
export { WORKFLOW_TEMPLATES, findTemplate, } from './data/workflow-templates.js';
|
|
52
58
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,SAAS,EAA+C,MAAM,sBAAsB,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAuC,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,cAAc,EAAoB,MAAM,0BAA0B,CAAC;AAC3F,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAsE,MAAM,yBAAyB,CAAC;AACpK,OAAO,EAAE,eAAe,EAA2D,MAAM,4BAA4B,CAAC;AACtH,OAAO,EAAE,YAAY,EAA2B,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACjI,OAAO,EAAE,iBAAiB,EAA8C,MAAM,kBAAkB,CAAC;AAEjG,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAA4B,MAAM,gCAAgC,CAAC;AAC1F,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAA+B,MAAM,mCAAmC,CAAC;AACnG,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAA2D,MAAM,gCAAgC,CAAC;AAC5I,OAAO,EAAE,cAAc,EAA4B,MAAM,gCAAgC,CAAC;AAC1F,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,2DAA2D;AAC3D,8DAA8D;AAC9D,OAAO,4BAA4B,CAAC;AAEpC,OAAO,EAAE,SAAS,EAA+C,MAAM,sBAAsB,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAuC,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,cAAc,EAAoB,MAAM,0BAA0B,CAAC;AAC3F,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAsE,MAAM,yBAAyB,CAAC;AACpK,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,2BAA2B,EAAE,iBAAiB,EAA4E,MAAM,6BAA6B,CAAC;AAC5P,OAAO,EAAE,eAAe,EAA2D,MAAM,4BAA4B,CAAC;AACtH,OAAO,EAAE,YAAY,EAA2B,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACjI,OAAO,EAAE,iBAAiB,EAA8C,MAAM,kBAAkB,CAAC;AAEjG,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAA4B,MAAM,gCAAgC,CAAC;AAC1F,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAA+B,MAAM,mCAAmC,CAAC;AACnG,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAA2D,MAAM,gCAAgC,CAAC;AAC5I,OAAO,EAAE,cAAc,EAA4B,MAAM,gCAAgC,CAAC;AAC1F,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAC;AAE9E,OAAO,EACL,kBAAkB,EAGlB,YAAY,GACb,MAAM,8BAA8B,CAAC"}
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Assets slice —— 资产导入 / 选择 / 删除 / 缩略图
|
|
3
|
+
*
|
|
4
|
+
* TD-5.1 长期方案:缩略图 ObjectURL 的创建 / 替换 / 释放统一在 store 内管理,
|
|
5
|
+
* 消除原先"创建在 AssetPanel effect、释放在 removeAsset action"的跨边界脆弱性。
|
|
6
|
+
* - ensureThumbnails:iterate assets → exportAsset → createObjectURL → setThumbnail
|
|
7
|
+
* - setThumbnail:替换时自动 revoke 旧 ObjectURL
|
|
8
|
+
* - removeAsset:删除时 revoke ObjectURL + 清理 entry
|
|
9
|
+
* inflight 去重通过闭包捕获的 Set(非响应式,不触发额外 re-render)。
|
|
3
10
|
*/
|
|
4
11
|
import type { StateCreator } from 'zustand';
|
|
5
12
|
import type { WorkspaceStore, WorkspaceState, WorkspaceActions } from './types.js';
|
|
6
|
-
export interface AssetsSlice extends Pick<WorkspaceState, 'assets' | 'selectedAssetId' | 'thumbnails'>, Pick<WorkspaceActions, 'refreshAssets' | 'importFiles' | 'selectAsset' | 'setThumbnail' | 'removeAsset'> {
|
|
13
|
+
export interface AssetsSlice extends Pick<WorkspaceState, 'assets' | 'selectedAssetId' | 'thumbnails'>, Pick<WorkspaceActions, 'refreshAssets' | 'importFiles' | 'selectAsset' | 'setThumbnail' | 'ensureThumbnails' | 'removeAsset'> {
|
|
7
14
|
}
|
|
8
15
|
export declare const createAssetsSlice: StateCreator<WorkspaceStore, [
|
|
9
16
|
], [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assets-slice.d.ts","sourceRoot":"","sources":["../../src/store/assets-slice.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"assets-slice.d.ts","sourceRoot":"","sources":["../../src/store/assets-slice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnF,MAAM,WAAW,WACf,SAAQ,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,iBAAiB,GAAG,YAAY,CAAC,EACvE,IAAI,CACF,gBAAgB,EACd,eAAe,GACf,aAAa,GACb,aAAa,GACb,cAAc,GACd,kBAAkB,GAClB,aAAa,CAChB;CAAG;AAER,eAAO,MAAM,iBAAiB,EAAE,YAAY,CAC1C,cAAc,EACd;CAAE,EACF;CAAE,EACF,WAAW,CAoGZ,CAAC"}
|
|
@@ -1,58 +1,105 @@
|
|
|
1
|
-
export const createAssetsSlice = (set, get) =>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
set({ statusMessage: `Imported ${files.length} file(s)` });
|
|
23
|
-
},
|
|
24
|
-
selectAsset(id) {
|
|
25
|
-
set({ selectedAssetId: id });
|
|
26
|
-
},
|
|
27
|
-
setThumbnail(id, url) {
|
|
28
|
-
set((state) => ({ thumbnails: { ...state.thumbnails, [id]: url } }));
|
|
29
|
-
},
|
|
30
|
-
async removeAsset(id) {
|
|
31
|
-
const { runtime } = get();
|
|
32
|
-
if (!runtime)
|
|
33
|
-
return;
|
|
34
|
-
await runtime.removeAsset(id);
|
|
35
|
-
await get().refreshAssets();
|
|
36
|
-
await get().refreshStorageUsage();
|
|
37
|
-
if (get().selectedAssetId === id)
|
|
38
|
-
set({ selectedAssetId: null });
|
|
39
|
-
// 修复 review 报告:原实现删除 asset 后未 revoke 缩略图 ObjectURL,导致
|
|
40
|
-
// 浏览器 Blob 引用泄漏(每删一张图就漏一个 blob 内存)。
|
|
41
|
-
// 同时从 thumbnails map 中删除该 entry,避免 stale ref
|
|
42
|
-
const oldUrl = get().thumbnails[id];
|
|
43
|
-
if (oldUrl) {
|
|
44
|
-
try {
|
|
45
|
-
URL.revokeObjectURL(oldUrl);
|
|
46
|
-
}
|
|
47
|
-
catch {
|
|
48
|
-
/* URL 已失效或非 ObjectURL,忽略 */
|
|
1
|
+
export const createAssetsSlice = (set, get) => {
|
|
2
|
+
// TD-5.1:per-store inflight 缩略图去重(闭包捕获,非响应式,不触发 re-render)
|
|
3
|
+
const inflightThumbnails = new Set();
|
|
4
|
+
return {
|
|
5
|
+
assets: [],
|
|
6
|
+
selectedAssetId: null,
|
|
7
|
+
thumbnails: {},
|
|
8
|
+
async refreshAssets() {
|
|
9
|
+
const { runtime } = get();
|
|
10
|
+
if (!runtime)
|
|
11
|
+
return;
|
|
12
|
+
const assets = await runtime.listAssets();
|
|
13
|
+
set({ assets });
|
|
14
|
+
},
|
|
15
|
+
async importFiles(files) {
|
|
16
|
+
const { runtime } = get();
|
|
17
|
+
if (!runtime)
|
|
18
|
+
return;
|
|
19
|
+
set({ statusMessage: `Importing ${files.length} file(s)...` });
|
|
20
|
+
for (const file of files) {
|
|
21
|
+
await runtime.importAsset({ kind: 'file', file });
|
|
49
22
|
}
|
|
23
|
+
await get().refreshAssets();
|
|
24
|
+
await get().refreshStorageUsage();
|
|
25
|
+
set({ statusMessage: `Imported ${files.length} file(s)` });
|
|
26
|
+
},
|
|
27
|
+
selectAsset(id) {
|
|
28
|
+
set({ selectedAssetId: id });
|
|
29
|
+
},
|
|
30
|
+
setThumbnail(id, url) {
|
|
31
|
+
// TD-5.1:替换时 revoke 旧 ObjectURL,集中管理释放,避免孤儿 URL
|
|
50
32
|
set((state) => {
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
33
|
+
const old = state.thumbnails[id];
|
|
34
|
+
if (old) {
|
|
35
|
+
try {
|
|
36
|
+
URL.revokeObjectURL(old);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
/* URL 已失效或非 ObjectURL,忽略 */
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return { thumbnails: { ...state.thumbnails, [id]: url } };
|
|
54
43
|
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
});
|
|
44
|
+
},
|
|
45
|
+
ensureThumbnails() {
|
|
46
|
+
const { runtime, assets, thumbnails } = get();
|
|
47
|
+
if (!runtime)
|
|
48
|
+
return;
|
|
49
|
+
for (const asset of assets) {
|
|
50
|
+
if (thumbnails[asset.id])
|
|
51
|
+
continue;
|
|
52
|
+
if (asset.type !== 'image')
|
|
53
|
+
continue;
|
|
54
|
+
if (inflightThumbnails.has(asset.id))
|
|
55
|
+
continue;
|
|
56
|
+
inflightThumbnails.add(asset.id);
|
|
57
|
+
void (async () => {
|
|
58
|
+
try {
|
|
59
|
+
const blob = await runtime.exportAsset(asset.id);
|
|
60
|
+
const url = URL.createObjectURL(blob);
|
|
61
|
+
// 资产可能在 await 期间被删除:若已不在 assets 中,revoke URL 不入 store
|
|
62
|
+
if (!get().assets.some((a) => a.id === asset.id)) {
|
|
63
|
+
URL.revokeObjectURL(url);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
get().setThumbnail(asset.id, url);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// export 失败,不留缩略图(下次 ensureThumbnails 会重试)
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
inflightThumbnails.delete(asset.id);
|
|
73
|
+
}
|
|
74
|
+
})();
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
async removeAsset(id) {
|
|
78
|
+
const { runtime } = get();
|
|
79
|
+
if (!runtime)
|
|
80
|
+
return;
|
|
81
|
+
await runtime.removeAsset(id);
|
|
82
|
+
await get().refreshAssets();
|
|
83
|
+
await get().refreshStorageUsage();
|
|
84
|
+
if (get().selectedAssetId === id)
|
|
85
|
+
set({ selectedAssetId: null });
|
|
86
|
+
// TD-5.1:删除资产时 revoke 缩略图 ObjectURL + 清理 entry(与 setThumbnail
|
|
87
|
+
// 的 replace-revoke 一起,构成"创建/替换/释放"全在 store 内的闭环)
|
|
88
|
+
const oldUrl = get().thumbnails[id];
|
|
89
|
+
if (oldUrl) {
|
|
90
|
+
try {
|
|
91
|
+
URL.revokeObjectURL(oldUrl);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
/* URL 已失效或非 ObjectURL,忽略 */
|
|
95
|
+
}
|
|
96
|
+
set((state) => {
|
|
97
|
+
const next = { ...state.thumbnails };
|
|
98
|
+
delete next[id];
|
|
99
|
+
return { thumbnails: next };
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
};
|
|
58
105
|
//# sourceMappingURL=assets-slice.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assets-slice.js","sourceRoot":"","sources":["../../src/store/assets-slice.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"assets-slice.js","sourceRoot":"","sources":["../../src/store/assets-slice.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { StateCreator } from 'zustand';
|
|
5
5
|
import type { WorkspaceStore, WorkspaceState, WorkspaceActions } from './types.js';
|
|
6
|
-
export interface CapabilitiesSlice extends Pick<WorkspaceState, 'capabilities' | 'capabilityMap'>, Pick<WorkspaceActions, 'refreshCapabilities'> {
|
|
6
|
+
export interface CapabilitiesSlice extends Pick<WorkspaceState, 'capabilities' | 'capabilityMap' | 'stubCapabilities'>, Pick<WorkspaceActions, 'refreshCapabilities'> {
|
|
7
7
|
}
|
|
8
8
|
export declare const createCapabilitiesSlice: StateCreator<WorkspaceStore, [
|
|
9
9
|
], [
|