feat(playlists): библиотека плейлистов приложения
CRUD в редакторе, read-only окно на пульте, отдельный аудиоканал, экспорт/импорт и маппинг из Foundry. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -411,6 +411,10 @@ export class ZipProjectStore {
|
||||
return this.openProject?.project ?? null;
|
||||
}
|
||||
|
||||
getOpenCacheDir(): string | null {
|
||||
return this.openProject?.cacheDir ?? null;
|
||||
}
|
||||
|
||||
/** Только указатель сессии в памяти — без записи project.json на диск. */
|
||||
setSessionPointer(currentGraphNodeId: GraphNodeId | null, currentSceneId: SceneId | null): Project {
|
||||
const open = this.openProject;
|
||||
@@ -2039,7 +2043,7 @@ export class ZipProjectStore {
|
||||
async importProjectFromFoundry(
|
||||
sourcePath: string,
|
||||
onProgress?: (p: FoundryImportProgress) => void,
|
||||
): Promise<Project> {
|
||||
): Promise<{ project: Project; pendingAppPlaylists: import('../foundry/foundryImport').FoundryPendingAppPlaylist[] }> {
|
||||
await this.ensureRoots();
|
||||
const loaded = await loadFoundryDocumentsForImport(sourcePath, onProgress);
|
||||
try {
|
||||
@@ -2049,7 +2053,7 @@ export class ZipProjectStore {
|
||||
await fs.rm(cacheDir, { recursive: true, force: true });
|
||||
await fs.mkdir(path.join(cacheDir, 'assets'), { recursive: true });
|
||||
|
||||
const { project } = await buildProjectFromFoundryDocuments(
|
||||
const { project, pendingAppPlaylists } = await buildProjectFromFoundryDocuments(
|
||||
loaded.manifest,
|
||||
loaded.docs,
|
||||
cacheDir,
|
||||
@@ -2070,7 +2074,7 @@ export class ZipProjectStore {
|
||||
onProgress?.({ stage: 'zip', percent: 90, detail: 'Сборка проекта…' });
|
||||
await this.enqueuePack(cacheDir, zipPath);
|
||||
onProgress?.({ stage: 'done', percent: 100, detail: 'Готово' });
|
||||
return this.openProject.project;
|
||||
return { project: this.openProject.project, pendingAppPlaylists };
|
||||
} finally {
|
||||
await loaded.cleanup();
|
||||
}
|
||||
@@ -2184,6 +2188,7 @@ export class ZipProjectStore {
|
||||
labels: StorylineLabels,
|
||||
onProgress?: (p: { stage: 'zip' | 'done'; percent: number; detail?: string }) => void,
|
||||
packAppTokens?: (tokenIds: string[], exportRoot: string) => Promise<void>,
|
||||
packAppPlaylists?: (exportRoot: string) => Promise<void>,
|
||||
): Promise<void> {
|
||||
if (selections.length === 0) throw new Error('Не выбрана ни одна сюжетная линия');
|
||||
await this.ensureRoots();
|
||||
@@ -2217,6 +2222,9 @@ export class ZipProjectStore {
|
||||
const tokenIds = collectTokenIdsFromProject(partial);
|
||||
await packAppTokens(tokenIds, exportCache);
|
||||
}
|
||||
if (packAppPlaylists) {
|
||||
await packAppPlaylists(exportCache);
|
||||
}
|
||||
const now = new Date().toISOString();
|
||||
const toWrite: Project = {
|
||||
...partial,
|
||||
|
||||
Reference in New Issue
Block a user