8e3d9991fa
实现资源卡本体化与图片视频音频预览播放 实现四个资源分区独立高度与内外滚动 实现依赖视图确定性聚类与拓扑变化重排 补齐布局、SVG、AppSurface、性能和媒体回归 同步工作台PRD、技术方案与项目共享记忆 --------- Co-authored-by: kdletters <kdletters@qq.com> Co-authored-by: 段舒康 <kdletters@qq.com> Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/154 Co-authored-by: menghao <mh18530625731@163.com> Co-committed-by: menghao <mh18530625731@163.com>
52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
const PROJECT_RESOURCE_PREVIEW_CANCELLED_ERROR =
|
|
'project-resource-preview-scope-cancelled';
|
|
|
|
let projectResourcePreviewOpaqueIdSequence = 0;
|
|
|
|
function createProjectResourcePreviewOpaqueId(prefix: 'scope' | 'request') {
|
|
projectResourcePreviewOpaqueIdSequence += 1;
|
|
const cryptoApi = globalThis.crypto;
|
|
const randomId = cryptoApi?.randomUUID?.();
|
|
if (randomId) {
|
|
return `${prefix}:${randomId}`;
|
|
}
|
|
if (cryptoApi?.getRandomValues) {
|
|
const randomWords = cryptoApi.getRandomValues(new Uint32Array(4));
|
|
return `${prefix}:${Array.from(randomWords, (word) => word.toString(36)).join('-')}`;
|
|
}
|
|
return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}:${projectResourcePreviewOpaqueIdSequence.toString(36)}`;
|
|
}
|
|
|
|
export function createProjectResourcePreviewScopeId() {
|
|
return createProjectResourcePreviewOpaqueId('scope');
|
|
}
|
|
|
|
export function createProjectResourcePreviewRequestId() {
|
|
return createProjectResourcePreviewOpaqueId('request');
|
|
}
|
|
|
|
export function isProjectResourcePreviewCancellation(error: unknown) {
|
|
const message =
|
|
error instanceof Error
|
|
? error.message
|
|
: typeof error === 'string'
|
|
? error
|
|
: null;
|
|
return message === PROJECT_RESOURCE_PREVIEW_CANCELLED_ERROR;
|
|
}
|
|
|
|
export function cancelLocalProjectResourcePreviewScope(scopeId: string) {
|
|
const invoke = window.__TAURI__?.core?.invoke;
|
|
if (!invoke) {
|
|
return;
|
|
}
|
|
try {
|
|
void Promise.resolve(
|
|
invoke('cancel_local_project_resource_preview_scope', { scopeId }),
|
|
).catch(() => undefined);
|
|
} catch {
|
|
// The epoch/owner fence remains authoritative if the WebView is already
|
|
// tearing down and can no longer deliver the best-effort cancellation.
|
|
}
|
|
}
|