Release 0.5.9
This commit is contained in:
1 parent
2851c7d936
commit
c3033479b5
32 files changed
+1598
-50
No files matched your search
+110
-2
@@ -62,12 +62,20 @@ export type LiveView = {
|
||||
next: LiveUsage | null;
|
||||
completedCount: number;
|
||||
totalCount: number;
|
||||
sectionTimer: null | {
|
||||
sectionId: string;
|
||||
sectionName: string;
|
||||
plannedDurationSeconds: number;
|
||||
elapsedSeconds: number;
|
||||
runningSinceUtc: string | null;
|
||||
};
|
||||
};
|
||||
|
||||
export type PresentationView = {
|
||||
revision: number;
|
||||
content: null | {
|
||||
mode: PresentationContent['mode'];
|
||||
topics: string[];
|
||||
title: string;
|
||||
html: string;
|
||||
source: PresentationContent['source'];
|
||||
@@ -141,6 +149,59 @@ function closeActiveRun(database: Database.Database, showId: string, now: string
|
||||
.run(now, showId);
|
||||
}
|
||||
|
||||
function closeSectionTimer(database: Database.Database, showId: string, now: string) {
|
||||
const timer = database
|
||||
.prepare('SELECT id FROM live_section_timers WHERE show_id = ? AND ended_at_utc IS NULL')
|
||||
.get(showId) as { id: string } | undefined;
|
||||
if (!timer) return;
|
||||
database
|
||||
.prepare(
|
||||
'UPDATE live_section_timer_runs SET ended_at_utc = ? WHERE timer_id = ? AND ended_at_utc IS NULL'
|
||||
)
|
||||
.run(now, timer.id);
|
||||
database
|
||||
.prepare('UPDATE live_section_timers SET ended_at_utc = ? WHERE id = ?')
|
||||
.run(now, timer.id);
|
||||
}
|
||||
|
||||
function syncSectionTimer(
|
||||
database: Database.Database,
|
||||
showId: string,
|
||||
usageId: string,
|
||||
now: string
|
||||
) {
|
||||
const section = database
|
||||
.prepare(
|
||||
`SELECT s.id, s.explicit_duration_seconds FROM piece_usages u
|
||||
JOIN show_sections s ON s.id = u.show_section_id
|
||||
WHERE u.id = ? AND s.show_id = ? AND s.is_reserve_bank = 0`
|
||||
)
|
||||
.get(usageId, showId) as { id: string; explicit_duration_seconds: number | null } | undefined;
|
||||
if (!section) throw new Error('NOT_FOUND');
|
||||
const active = database
|
||||
.prepare(
|
||||
'SELECT id, section_id FROM live_section_timers WHERE show_id = ? AND ended_at_utc IS NULL'
|
||||
)
|
||||
.get(showId) as { id: string; section_id: string } | undefined;
|
||||
if (active?.section_id === section.id) return;
|
||||
if (active) closeSectionTimer(database, showId, now);
|
||||
if (!section.explicit_duration_seconds || section.explicit_duration_seconds <= 0) return;
|
||||
const timerId = randomUUID();
|
||||
database
|
||||
.prepare(
|
||||
`INSERT INTO live_section_timers
|
||||
(id, show_id, section_id, planned_duration_seconds, started_at_utc)
|
||||
VALUES (?, ?, ?, ?, ?)`
|
||||
)
|
||||
.run(timerId, showId, section.id, section.explicit_duration_seconds, now);
|
||||
database
|
||||
.prepare(
|
||||
`INSERT INTO live_section_timer_runs (id, timer_id, started_at_utc)
|
||||
VALUES (?, ?, ?)`
|
||||
)
|
||||
.run(randomUUID(), timerId, now);
|
||||
}
|
||||
|
||||
function activateUsage(database: Database.Database, showId: string, usageId: string, now: string) {
|
||||
usageBelongsToShow(database, showId, usageId);
|
||||
database
|
||||
@@ -164,6 +225,7 @@ function activateUsage(database: Database.Database, showId: string, usageId: str
|
||||
'UPDATE show_live_states SET current_usage_id = ?, ended_at_utc = NULL WHERE show_id = ?'
|
||||
)
|
||||
.run(usageId, showId);
|
||||
syncSectionTimer(database, showId, usageId, now);
|
||||
}
|
||||
|
||||
function executeCommand(
|
||||
@@ -268,6 +330,44 @@ export function getLiveView(showId: string, nowValue?: Date): LiveView {
|
||||
const next =
|
||||
usages.slice(currentIndex + 1).find((usage) => usage.status === 'open') ??
|
||||
(current ? null : (usages.find((usage) => usage.status === 'open') ?? null));
|
||||
const timer = database
|
||||
.prepare(
|
||||
`SELECT t.id, t.section_id, s.name AS section_name, t.planned_duration_seconds
|
||||
FROM live_section_timers t JOIN show_sections s ON s.id = t.section_id
|
||||
WHERE t.show_id = ? AND t.ended_at_utc IS NULL`
|
||||
)
|
||||
.get(showId) as
|
||||
| { id: string; section_id: string; section_name: string; planned_duration_seconds: number }
|
||||
| undefined;
|
||||
let sectionTimer: LiveView['sectionTimer'] = null;
|
||||
if (timer) {
|
||||
const runs = database
|
||||
.prepare(
|
||||
`SELECT started_at_utc, ended_at_utc FROM live_section_timer_runs
|
||||
WHERE timer_id = ? ORDER BY started_at_utc`
|
||||
)
|
||||
.all(timer.id) as { started_at_utc: string; ended_at_utc: string | null }[];
|
||||
const running = runs.find((run) => run.ended_at_utc === null) ?? null;
|
||||
const elapsedSeconds = runs.reduce(
|
||||
(total, run) =>
|
||||
total +
|
||||
Math.max(
|
||||
0,
|
||||
Math.floor(
|
||||
(new Date(run.ended_at_utc ?? now).getTime() - new Date(run.started_at_utc).getTime()) /
|
||||
1_000
|
||||
)
|
||||
),
|
||||
0
|
||||
);
|
||||
sectionTimer = {
|
||||
sectionId: timer.section_id,
|
||||
sectionName: timer.section_name,
|
||||
plannedDurationSeconds: timer.planned_duration_seconds,
|
||||
elapsedSeconds,
|
||||
runningSinceUtc: running?.started_at_utc ?? null
|
||||
};
|
||||
}
|
||||
return {
|
||||
show: {
|
||||
id: show.id,
|
||||
@@ -287,7 +387,8 @@ export function getLiveView(showId: string, nowValue?: Date): LiveView {
|
||||
next,
|
||||
completedCount: usages.filter((usage) => usage.status === 'done' || usage.status === 'skipped')
|
||||
.length,
|
||||
totalCount: usages.length
|
||||
totalCount: usages.length,
|
||||
sectionTimer
|
||||
};
|
||||
}
|
||||
|
||||
@@ -353,10 +454,12 @@ function advanceCurrent(
|
||||
.run(status, state.current_usage_id);
|
||||
const next = ordered.slice(currentIndex + 1).find((usage) => usage.status === 'open');
|
||||
if (next) activateUsage(database, showId, next.id, now);
|
||||
else
|
||||
else {
|
||||
closeSectionTimer(database, showId, now);
|
||||
database
|
||||
.prepare('UPDATE show_live_states SET current_usage_id = NULL WHERE show_id = ?')
|
||||
.run(showId);
|
||||
}
|
||||
},
|
||||
nowValue
|
||||
);
|
||||
@@ -655,6 +758,11 @@ function getPresentationViewForShow(showId: string): PresentationView {
|
||||
revision: state.presentation_revision,
|
||||
content: {
|
||||
mode: usage.presentation_mode_snapshot,
|
||||
topics: (
|
||||
database
|
||||
.prepare('SELECT name FROM usage_topic_snapshots WHERE usage_id = ? ORDER BY position')
|
||||
.all(state.presentation_usage_id) as { name: string }[]
|
||||
).map((topic) => topic.name),
|
||||
title: usage.output_title_snapshot || usage.title_snapshot,
|
||||
html: renderMarkdown(usage.presentation_snapshot),
|
||||
source: usage.presentation_source_url_snapshot
|
||||
|
||||
Reference in new issue
Block a user