initial commit
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
import type { Marker, SwitchType } from './types';
|
||||
import { ZOOM_DEFAULT } from './types';
|
||||
|
||||
export const app = $state({
|
||||
markers: [] as Marker[],
|
||||
selectedIds: new Set<string>(),
|
||||
isPlaying: false,
|
||||
currentTime: 0,
|
||||
duration: 0,
|
||||
fps: 30,
|
||||
pixelsPerSecond: ZOOM_DEFAULT,
|
||||
scrollLeft: 0,
|
||||
activeSwitch: 'cherry-mx-blue' as SwitchType,
|
||||
videoUrl: null as string | null,
|
||||
videoName: null as string | null,
|
||||
timelineWidth: 800,
|
||||
});
|
||||
|
||||
let markerCounter = 0;
|
||||
|
||||
export function createMarkerId(): string {
|
||||
markerCounter += 1;
|
||||
return `m${markerCounter}`;
|
||||
}
|
||||
|
||||
export function setMarkers(value: Marker[]) {
|
||||
app.markers = value;
|
||||
const maxId = value.reduce((max, m) => {
|
||||
const num = parseInt(m.id.replace(/\D/g, ''), 10);
|
||||
return Number.isFinite(num) ? Math.max(max, num) : max;
|
||||
}, 0);
|
||||
markerCounter = maxId;
|
||||
}
|
||||
|
||||
export function setSelectedIds(ids: Set<string>) {
|
||||
app.selectedIds = ids;
|
||||
}
|
||||
|
||||
export function setCurrentTime(value: number) {
|
||||
app.currentTime = value;
|
||||
}
|
||||
|
||||
export function setDuration(value: number) {
|
||||
app.duration = value;
|
||||
}
|
||||
|
||||
export function setIsPlaying(value: boolean) {
|
||||
app.isPlaying = value;
|
||||
}
|
||||
|
||||
export function setFps(value: number) {
|
||||
app.fps = value;
|
||||
}
|
||||
|
||||
export function setPixelsPerSecond(value: number) {
|
||||
app.pixelsPerSecond = value;
|
||||
}
|
||||
|
||||
export function setScrollLeft(value: number) {
|
||||
app.scrollLeft = value;
|
||||
}
|
||||
|
||||
export function setActiveSwitch(value: SwitchType) {
|
||||
app.activeSwitch = value;
|
||||
}
|
||||
|
||||
export function setTimelineWidth(value: number) {
|
||||
app.timelineWidth = value;
|
||||
}
|
||||
|
||||
export function addMarker(time: number, key: string): Marker {
|
||||
const marker: Marker = { id: createMarkerId(), time, key };
|
||||
app.markers = [...app.markers, marker].sort((a, b) => a.time - b.time);
|
||||
return marker;
|
||||
}
|
||||
|
||||
export function updateMarker(id: string, patch: Partial<Pick<Marker, 'time' | 'key'>>) {
|
||||
app.markers = app.markers
|
||||
.map((m) => (m.id === id ? { ...m, ...patch } : m))
|
||||
.sort((a, b) => a.time - b.time);
|
||||
}
|
||||
|
||||
export function setMarkerTimes(updates: Map<string, number>) {
|
||||
app.markers = app.markers
|
||||
.map((m) => {
|
||||
const time = updates.get(m.id);
|
||||
return time === undefined ? m : { ...m, time };
|
||||
})
|
||||
.sort((a, b) => a.time - b.time);
|
||||
}
|
||||
|
||||
export function deleteMarkers(ids: Set<string>) {
|
||||
app.markers = app.markers.filter((m) => !ids.has(m.id));
|
||||
const next = new Set(app.selectedIds);
|
||||
for (const id of ids) next.delete(id);
|
||||
app.selectedIds = next;
|
||||
}
|
||||
|
||||
export function selectAll() {
|
||||
app.selectedIds = new Set(app.markers.map((m) => m.id));
|
||||
}
|
||||
|
||||
export function toggleSelection(id: string, additive: boolean) {
|
||||
const next = additive ? new Set(app.selectedIds) : new Set<string>();
|
||||
if (next.has(id)) next.delete(id);
|
||||
else next.add(id);
|
||||
app.selectedIds = next;
|
||||
}
|
||||
|
||||
export function setVideoUrl(url: string | null, name: string | null = null) {
|
||||
if (app.videoUrl) URL.revokeObjectURL(app.videoUrl);
|
||||
app.videoUrl = url;
|
||||
app.videoName = name;
|
||||
}
|
||||
|
||||
export function snapToFrame(time: number): number {
|
||||
const frameDuration = 1 / app.fps;
|
||||
return Math.round(time / frameDuration) * frameDuration;
|
||||
}
|
||||
|
||||
export function nudgeSelected(deltaFrames: number) {
|
||||
if (app.selectedIds.size === 0) return;
|
||||
const frameDuration = 1 / app.fps;
|
||||
const delta = deltaFrames * frameDuration;
|
||||
app.markers = app.markers
|
||||
.map((m) => {
|
||||
if (!app.selectedIds.has(m.id)) return m;
|
||||
const next = Math.max(0, Math.min(app.duration || Infinity, m.time + delta));
|
||||
return { ...m, time: snapToFrame(next) };
|
||||
})
|
||||
.sort((a, b) => a.time - b.time);
|
||||
}
|
||||
Reference in New Issue
Block a user