diff --git a/.eslintrc.json b/.eslintrc.json index 2869d819..c4428a8b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -36,6 +36,7 @@ "@typescript-eslint/no-explicit-any": "off", "vue/no-v-for-template-key": "off", "vue/no-v-model-argument": "off", + "no-async-promise-executor": "off", "no-undef": "off" } } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1f7d8fa..d871410f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,5 +56,11 @@ jobs: - name: Build safelight run: pnpm build:safelight - - name: Test - run: pnpm test + - name: Test darkroom + run: pnpm test:darkroom + + - name: Test shared + run: pnpm test:shared + + - name: Test timeline + run: pnpm test:timeline diff --git a/package.json b/package.json index 1b42fa9b..f887e52c 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,9 @@ "build:timeline": "cd packages/timeline && pnpm build", "build:safelight": "cd packages/safelight && pnpm build", "test": "pnpm run -r test:run", + "test:darkroom": "cd packages/darkroom && pnpm test:run", + "test:shared": "cd packages/shared && pnpm test:run", + "test:timeline": "cd packages/timeline && pnpm test:run", "dev": "pnpm build:packages && cd packages/safelight && pnpm dev", "dev:darkroom": "pnpm build:packages && cd packages/darkroom && pnpm dev:web" }, diff --git a/packages/safelight/src/components/Editor/Library/Library.vue b/packages/safelight/src/components/Editor/Library/Library.vue index 0919b65c..0680745c 100644 --- a/packages/safelight/src/components/Editor/Library/Library.vue +++ b/packages/safelight/src/components/Editor/Library/Library.vue @@ -1,5 +1,12 @@ - + @@ -64,10 +71,10 @@ /> - {{ item.name }} + {{ item.name.value }} {{ item.duration }} @@ -75,27 +82,26 @@ + + + No media imported + + @@ -93,6 +70,13 @@ onBeforeUnmount(() => { .vertSlitter { height: 100vh; } + +:deep(.p-tabview-panels) { + @apply flex-1; +} +:deep(.p-tabview-panel) { + @apply h-full; +} diff --git a/packages/safelight/src/views/projects.vue b/packages/safelight/src/views/projects.vue index 482036e0..3cbcd63b 100644 --- a/packages/safelight/src/views/projects.vue +++ b/packages/safelight/src/views/projects.vue @@ -1,7 +1,23 @@ - + + + + Projects + + + + + + + + @@ -9,6 +25,11 @@ {{ formatDateTime((slotProps.data as StoredProject).updated) }} + + + Open + + @@ -17,26 +38,76 @@ diff --git a/packages/shared/src/Project/SimpleProject.ts b/packages/shared/src/Project/SimpleProject.ts index 9b57cef9..b09ecb04 100644 --- a/packages/shared/src/Project/SimpleProject.ts +++ b/packages/shared/src/Project/SimpleProject.ts @@ -11,7 +11,7 @@ export default class SimpleProject extends BaseProject { public media = shallowReactive([]); - protected selectedTimelineIndex = ref(0); + public selectedTimelineIndex = ref(0); public timelines = shallowReactive([]); public timeline = computed(() => this.timelines.at(this.selectedTimelineIndex.value)!); } diff --git a/packages/shared/src/Storage/IndexedDbStorage.ts b/packages/shared/src/Storage/IndexedDbStorage.ts index 8246df4a..2ad0653e 100644 --- a/packages/shared/src/Storage/IndexedDbStorage.ts +++ b/packages/shared/src/Storage/IndexedDbStorage.ts @@ -65,8 +65,13 @@ export default class IndexedDbStorageController extends BaseStorageController { } }); } - getProjects(): Promise { - return this.db.project.toArray(); + static getProjects(): Promise { + return new Promise(async (resolve) => { + const db = new SafelightIndexedDB(); + await db.open(); + resolve(db.project.toArray()); + db.close(); + }); } async SaveMedia(media: Media | StoredMedia): Promise { diff --git a/packages/shared/src/Storage/db.ts b/packages/shared/src/Storage/db.ts index e33fe434..54c737c1 100644 --- a/packages/shared/src/Storage/db.ts +++ b/packages/shared/src/Storage/db.ts @@ -7,8 +7,10 @@ export class SafelightIndexedDB extends Dexie { constructor() { // Only during tests - if (global?.vitest) { - super('SafelightIdb', { indexedDB: global.indexedDB, IDBKeyRange: global.IDBKeyRange }); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + //@ts-ignore + if (window?.vitest) { + super('SafelightIdb', { indexedDB: window.indexedDB, IDBKeyRange: window.IDBKeyRange }); } else { super('SafelightIdb'); } diff --git a/packages/shared/src/base/Project.ts b/packages/shared/src/base/Project.ts index ac2620fc..2b953103 100644 --- a/packages/shared/src/base/Project.ts +++ b/packages/shared/src/base/Project.ts @@ -10,7 +10,7 @@ export default abstract class BaseProject { public abstract media: ShallowReactive; - protected abstract selectedTimelineIndex: Ref; + public abstract selectedTimelineIndex: Ref; public abstract timelines: ShallowReactive; public abstract timeline: ComputedRef; diff --git a/packages/shared/src/base/Storage.ts b/packages/shared/src/base/Storage.ts index f77f7147..a2cae9fc 100644 --- a/packages/shared/src/base/Storage.ts +++ b/packages/shared/src/base/Storage.ts @@ -18,7 +18,7 @@ export default abstract class BaseStorageController { abstract SaveProject(project: BaseProject): Promise; abstract LoadProject(projectId: string): Promise; - abstract getProjects(): Promise; + static getProjects: () => Promise; abstract SaveMedia(media: StoredMedia): Promise; abstract SaveMedia(media: Media): Promise; @@ -34,16 +34,22 @@ export default abstract class BaseStorageController { // isWebFileSystem = (): this is IndexedDbStorageController => this.type == 'WebFileSystem'; } -// Singleton pattern export class Storage { + public static async getProjects(): Promise { + const storageControllers = [(await import('../Storage/IndexedDbStorage')).default]; + + const getPromises = storageControllers.map((controller) => controller.getProjects()); + + const results = await Promise.all(getPromises); + + return results.flat(1); + } + + // Singleton pattern private static currentStorageController: BaseStorageController; static setStorage(storageController: BaseStorageController) { - if (!this.currentStorageController) { - this.currentStorageController = storageController; - } else { - throw new Error('Storage controller already defined'); - } + this.currentStorageController = storageController; } static getStorage() { if (this.currentStorageController) { diff --git a/packages/shared/src/helpers/Video/GetVideoInfo.ts b/packages/shared/src/helpers/Video/GetVideoInfo.ts index aafdff43..f0ffd6c6 100644 --- a/packages/shared/src/helpers/Video/GetVideoInfo.ts +++ b/packages/shared/src/helpers/Video/GetVideoInfo.ts @@ -1,4 +1,5 @@ import MediaInfoFactory, { type MediaInfoType, type ReadChunkFunc } from 'mediainfo.js'; +import MediaInfoWasmUrl from 'mediainfo.js/MediaInfoModule.wasm?url'; import MimeMatcher from 'mime-matcher'; export async function getVideoInfo(file: File) { @@ -22,7 +23,7 @@ export async function getVideoInfo(file: File) { MediaInfoFactory({ locateFile(url, scriptDirectory) { console.log(url, scriptDirectory); - return ''; + return MediaInfoWasmUrl; } }).then(async (mediaInfo) => { const data = await mediaInfo.analyzeData(() => file.size, readChunk); diff --git a/packages/shared/test/Storage/indexedDB/Project.spec.ts b/packages/shared/test/Storage/indexedDB/Project.spec.ts index 8df311d0..5b9ae38f 100644 --- a/packages/shared/test/Storage/indexedDB/Project.spec.ts +++ b/packages/shared/test/Storage/indexedDB/Project.spec.ts @@ -2,25 +2,23 @@ import { IDBKeyRange, indexedDB } from 'fake-indexeddb'; import { expect, test } from 'vitest'; import SimpleProject from '../../../src/Project/SimpleProject'; import IndexedDbStorageController from '../../../src/Storage/IndexedDbStorage'; +import { Storage } from '../../../src/base/Storage'; -test('List projects', async () => { - global.indexedDB = indexedDB; - global.IDBKeyRange = IDBKeyRange; +window.indexedDB = indexedDB; +window.IDBKeyRange = IDBKeyRange; +test('List project', async () => { const storage = new IndexedDbStorageController(); const project = new SimpleProject(); await storage.SaveProject(project); - const projects = await storage.getProjects(); + const projects = await Storage.getProjects(); - expect(projects[0].id).toBe(project.id); + expect(projects.some((p) => p.id == project.id)).toBeTruthy(); }); test('Retrieve project', async () => { - global.indexedDB = indexedDB; - global.IDBKeyRange = IDBKeyRange; - const storage = new IndexedDbStorageController(); const project = new SimpleProject();
- {{ item.name }} + {{ item.name.value }}
{{ item.duration }} @@ -75,27 +82,26 @@