feat(playlists): библиотека плейлистов приложения
CRUD в редакторе, read-only окно на пульте, отдельный аудиоканал, экспорт/импорт и маппинг из Foundry. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -20,6 +20,12 @@ import type {
|
||||
AppToken,
|
||||
AppPlayer,
|
||||
AppPlayerTeam,
|
||||
AppPlaylist,
|
||||
PlaylistAudio,
|
||||
PlaylistAudioId,
|
||||
PlaylistId,
|
||||
PlaylistTrackId,
|
||||
PlaylistsState,
|
||||
PlayerId,
|
||||
PlayerTeamId,
|
||||
PlayerImageOffset,
|
||||
@@ -149,6 +155,8 @@ export const ipcChannels = {
|
||||
sceneDescriptionContent: 'windows.sceneDescriptionContent',
|
||||
openMaterials: 'windows.openMaterials',
|
||||
closeMaterials: 'windows.closeMaterials',
|
||||
openPlaylists: 'windows.openPlaylists',
|
||||
closePlaylists: 'windows.closePlaylists',
|
||||
openNpcsEditor: 'windows.openNpcsEditor',
|
||||
closeNpcsEditor: 'windows.closeNpcsEditor',
|
||||
openNpcs: 'windows.openNpcs',
|
||||
@@ -243,6 +251,21 @@ export const ipcChannels = {
|
||||
upsertProgress: 'players.upsertProgress',
|
||||
stateChanged: 'players.stateChanged',
|
||||
},
|
||||
playlists: {
|
||||
getState: 'playlists.getState',
|
||||
create: 'playlists.create',
|
||||
rename: 'playlists.rename',
|
||||
duplicate: 'playlists.duplicate',
|
||||
delete: 'playlists.delete',
|
||||
setOrder: 'playlists.setOrder',
|
||||
setTracksOrder: 'playlists.setTracksOrder',
|
||||
addAudioFiles: 'playlists.addAudioFiles',
|
||||
pickAudioFiles: 'playlists.pickAudioFiles',
|
||||
removeTrack: 'playlists.removeTrack',
|
||||
renameAudio: 'playlists.renameAudio',
|
||||
audioUrl: 'playlists.audioUrl',
|
||||
stateChanged: 'playlists.stateChanged',
|
||||
},
|
||||
sceneNpcTokensSession: {
|
||||
getState: 'sceneNpcTokensSession.getState',
|
||||
dispatch: 'sceneNpcTokensSession.dispatch',
|
||||
@@ -342,6 +365,7 @@ export type IpcEventMap = {
|
||||
[ipcChannels.tokenGridSnap.stateChanged]: { enabled: boolean };
|
||||
[ipcChannels.players.stateChanged]: { players: AppPlayer[]; teams: AppPlayerTeam[] };
|
||||
[ipcChannels.players.upsertProgress]: PlayersUpsertProgressEvent;
|
||||
[ipcChannels.playlists.stateChanged]: PlaylistsState;
|
||||
[ipcChannels.sceneNpcTokensSession.stateChanged]: { state: SceneNpcTokensSessionState };
|
||||
[ipcChannels.npcMapSpawn.stateChanged]: { state: NpcMapSpawnDragState };
|
||||
[ipcChannels.scenePlayerTokensSession.stateChanged]: { state: ScenePlayerTokensSessionState };
|
||||
@@ -667,6 +691,7 @@ export type IpcInvokeMap = {
|
||||
storylineSelections: StorylineSelection[];
|
||||
npcIds: string[];
|
||||
labels: StorylineLabels;
|
||||
playlistIds?: string[];
|
||||
};
|
||||
res: { canceled: true } | { canceled: false };
|
||||
};
|
||||
@@ -726,6 +751,14 @@ export type IpcInvokeMap = {
|
||||
req: Record<string, never>;
|
||||
res: { ok: true };
|
||||
};
|
||||
[ipcChannels.windows.openPlaylists]: {
|
||||
req: Record<string, never>;
|
||||
res: { ok: true };
|
||||
};
|
||||
[ipcChannels.windows.closePlaylists]: {
|
||||
req: Record<string, never>;
|
||||
res: { ok: true };
|
||||
};
|
||||
[ipcChannels.windows.openNpcsEditor]: {
|
||||
req: Record<string, never>;
|
||||
res: { ok: true };
|
||||
@@ -914,6 +947,54 @@ export type IpcInvokeMap = {
|
||||
req: { id: PlayerId };
|
||||
res: { url: string | null };
|
||||
};
|
||||
[ipcChannels.playlists.getState]: {
|
||||
req: Record<string, never>;
|
||||
res: PlaylistsState;
|
||||
};
|
||||
[ipcChannels.playlists.create]: {
|
||||
req: { name?: string };
|
||||
res: { playlist: AppPlaylist; state: PlaylistsState };
|
||||
};
|
||||
[ipcChannels.playlists.rename]: {
|
||||
req: { id: PlaylistId; name: string };
|
||||
res: { playlist: AppPlaylist; state: PlaylistsState };
|
||||
};
|
||||
[ipcChannels.playlists.duplicate]: {
|
||||
req: { id: PlaylistId };
|
||||
res: { playlist: AppPlaylist; state: PlaylistsState };
|
||||
};
|
||||
[ipcChannels.playlists.delete]: {
|
||||
req: { id: PlaylistId };
|
||||
res: { state: PlaylistsState };
|
||||
};
|
||||
[ipcChannels.playlists.setOrder]: {
|
||||
req: { playlistIds: PlaylistId[] };
|
||||
res: { state: PlaylistsState };
|
||||
};
|
||||
[ipcChannels.playlists.setTracksOrder]: {
|
||||
req: { playlistId: PlaylistId; trackIds: PlaylistTrackId[] };
|
||||
res: { playlist: AppPlaylist; state: PlaylistsState };
|
||||
};
|
||||
[ipcChannels.playlists.addAudioFiles]: {
|
||||
req: { playlistId: PlaylistId; filePaths: string[] };
|
||||
res: { playlist: AppPlaylist; state: PlaylistsState };
|
||||
};
|
||||
[ipcChannels.playlists.pickAudioFiles]: {
|
||||
req: Record<string, never>;
|
||||
res: { filePaths: string[] };
|
||||
};
|
||||
[ipcChannels.playlists.removeTrack]: {
|
||||
req: { playlistId: PlaylistId; trackId: PlaylistTrackId };
|
||||
res: { playlist: AppPlaylist; state: PlaylistsState };
|
||||
};
|
||||
[ipcChannels.playlists.renameAudio]: {
|
||||
req: { audioId: PlaylistAudioId; title: string };
|
||||
res: { audio: PlaylistAudio; state: PlaylistsState };
|
||||
};
|
||||
[ipcChannels.playlists.audioUrl]: {
|
||||
req: { id: PlaylistAudioId };
|
||||
res: { url: string | null };
|
||||
};
|
||||
[ipcChannels.sceneNpcTokensSession.getState]: {
|
||||
req: Record<string, never>;
|
||||
res: { state: SceneNpcTokensSessionState };
|
||||
@@ -996,6 +1077,7 @@ export type LegacyIpcEventMap = {
|
||||
[ipcChannels.tokenGridSnap.stateChanged]: { enabled: boolean };
|
||||
[ipcChannels.players.stateChanged]: { players: AppPlayer[]; teams: AppPlayerTeam[] };
|
||||
[ipcChannels.players.upsertProgress]: PlayersUpsertProgressEvent;
|
||||
[ipcChannels.playlists.stateChanged]: PlaylistsState;
|
||||
[ipcChannels.sceneNpcTokensSession.stateChanged]: { state: SceneNpcTokensSessionState };
|
||||
[ipcChannels.npcMapSpawn.stateChanged]: { state: NpcMapSpawnDragState };
|
||||
[ipcChannels.scenePlayerTokensSession.stateChanged]: { state: ScenePlayerTokensSessionState };
|
||||
|
||||
Reference in New Issue
Block a user