Skip to content

Commit

Permalink
Landed on a structure that i can get behind, thanks to shallowRef and…
Browse files Browse the repository at this point in the history
… shallowReactive.

Changed a bunch of file locations
Changed timecode
Added tests for timecode
Split AVTimelineItem into VideoTimelineItem and AudioTimelineItem
  • Loading branch information
Joery-M committed Apr 7, 2024
1 parent 06f26b1 commit a71396d
Show file tree
Hide file tree
Showing 30 changed files with 378 additions and 207 deletions.
26 changes: 26 additions & 0 deletions packages/darkroom/tests/externalFunction.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,29 @@ test('External function', async () => {
expect(hitMe).toBeCalledWith('Ok');
expect(hitMe).toBeCalledWith('Sure');
});

test('External function with object', async () => {
const compiler = new Compiler(esbuild);

expect(compiler).toBeDefined();

await compiler.waitForReady();

const hitMe = vi.fn();

const result = await compiler.compileSingleScript(`
hitMe({1: 'A'})
hitMe({2: 'B'})
`);

const script = new Script(result);

script.defineGlobals({
hitMe
});

script.execute();

expect(hitMe).toBeCalledWith({ 1: 'A' });
expect(hitMe).toBeCalledWith({ 2: 'B' });
});
12 changes: 0 additions & 12 deletions packages/safelight/src/@core/components/SLLibrary.vue

This file was deleted.

7 changes: 2 additions & 5 deletions packages/safelight/src/components/Editor/Library/Library.vue
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,16 @@
</template>

<script setup lang="ts">
import { CURRENT_TIMELINE } from '@/injections';
import { PhMagnifyingGlass, PhSortDescending } from '@phosphor-icons/vue';
import type BaseProject from '@safelight/shared/base/Project';
import type Media from '@safelight/shared/Media/Media';
import { PhMagnifyingGlass, PhSortDescending } from '@phosphor-icons/vue';
import fuzzysearch from 'fuzzysearch';
import MimeMatcher from 'mime-matcher';
import InputGroup from 'primevue/inputgroup';
import InputGroupAddon from 'primevue/inputgroupaddon';
import type { UnwrapRef } from 'vue';
const props = defineProps<{
media: UnwrapRef<Media[]>;
}>();
const emit = defineEmits<{
'update:modelValue': any[];
}>();
Expand Down
15 changes: 0 additions & 15 deletions packages/safelight/src/helpers/Video/GetVideoInfo.ts

This file was deleted.

6 changes: 6 additions & 0 deletions packages/safelight/src/injections.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type BaseProject from '@safelight/shared/base/Project';
import type BaseTimeline from '@safelight/shared/base/Timeline';
import type { InjectionKey } from 'vue';

export const CURRENT_PROJECT: InjectionKey<BaseProject> = Symbol('current.project');
export const CURRENT_TIMELINE: InjectionKey<BaseTimeline> = Symbol('current.timeline');
26 changes: 6 additions & 20 deletions packages/safelight/src/stores/useProject.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,16 @@
import Media from '@/controllers/Media/Media';
import SimpleTimeline from '@/controllers/Timeline/SimpleTimeline';
import Timecode from '@safelight/shared/timecode';
import SimpleProject from '@safelight/shared/Project/SimpleProject';

export const useProject = defineStore('Project', () => {
const name = ref('Untitled');
const media = ref<Media[]>([]);
const timelines = ref<SimpleTimeline[]>([new SimpleTimeline()]);
const activeTimelineIndex = ref(0);
const cursor = Timecode.from(0);
const timelineViewStart = Timecode.from(0);
const timelineViewEnd = Timecode.from(0);
const cursor = ref(0);
const timelineViewStart = ref(0);
const timelineViewEnd = ref(0);

const activeTimeline = computed(() => timelines.value[activeTimelineIndex.value]);

function getMediaFromID(id: string) {
return useArrayFind(media, (m) => m.id == id);
}
const project = new SimpleProject();

return {
name,
media,
timelines,
cursor,
timelineViewStart,
timelineViewEnd,
activeTimeline,
getMediaFromID
timelineViewEnd
};
});
4 changes: 3 additions & 1 deletion packages/safelight/tsconfig.app.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
"*.d.ts",
"./types/**/*.d.ts",
"src/**/*",
"src/**/*.ts",
"src/**/*.vue",
"src/**/*.json",
"tsconfig.worker.json"
"tsconfig.worker.json",
"types/injections.ts"
],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
Expand Down
3 changes: 3 additions & 0 deletions packages/shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
"@vueuse/shared": "^10.9.0",
"dexie": "^3.2.7",
"ffprobe-wasm": "^0.3.1",
"hash-wasm": "^4.11.0",
"luxon": "^3.4.4",
"mediainfo.js": "^0.2.2",
"mime-matcher": "^1.0.5",
"rxjs": "^7.8.1",
"uuid": "^9.0.1",
"vue": "^3.4.21"
Expand Down
5 changes: 3 additions & 2 deletions packages/shared/src/Media/Media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ export default class Media {
public duration = ref(5000);
public fileInfo = ref<FileInfo>();

constructor(public mediaId: string) {
db.media.get({ id: mediaId }).then((med) => {
constructor(id: string) {
this.id.value = id;
db.media.get({ id }).then((med) => {
if (med) {
this.name.value = med.name;

Expand Down
20 changes: 8 additions & 12 deletions packages/shared/src/Project/SimpleProject.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import SimpleTimeline from '@/Timeline/SimpleTimeline';
import { computed, ref, shallowReactive } from 'vue';
import Media from '../Media/Media';
import SimpleTimeline from '../Timeline/SimpleTimeline';
import { v4 as uuidv4 } from 'uuid';
import BaseProject, { type ProjectType } from '../base/Project';

export default class SimpleProject extends BaseProject {
public id = uuidv4();
public name = 'Untitled';
public type: ProjectType = 'Simple';

public media: Media[] = [];
public timelines: SimpleTimeline[] = [];
public activeTimeline: number;
public media = shallowReactive<Media[]>([]);

constructor() {
super();

const tl = new SimpleTimeline();

this.timelines = [tl];
this.activeTimeline = 0;
}
protected selectedTimelineIndex = ref(0);
public timelines = shallowReactive<SimpleTimeline[]>([]);
public timeline = computed(() => this.timelines.at(this.selectedTimelineIndex.value)!);
}
61 changes: 56 additions & 5 deletions packages/shared/src/Storage/IndexDbStorage.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import BaseProject from '@/base/Project';
import Media from '@/Media/Media';
import SimpleProject from '@/Project/SimpleProject';
import { from, Observable, Subject, takeUntil } from 'rxjs';
import type {
SaveObservable,
Expand All @@ -8,16 +11,25 @@ import type {
} from '../base/Storage';
import BaseStorageController from '../base/Storage';
import { SafelightIndexedDB } from './db';
import type BaseTimeline from '@/base/Timeline';
import type SimpleTimeline from '@/Timeline/SimpleTimeline';

export default class IndexedDbStorageController extends BaseStorageController {
public type: StorageControllerType = 'IndexedDB';
public version = '0.0.1';

private db = new SafelightIndexedDB();

SaveProject(project: StoredProject): SaveObservable {
SaveProject(project: BaseProject): SaveObservable {
this.StopSaveProject = new Subject();
return new Observable((subscriber) => {
const storableProject: StoredProject = {
id: project.id,
name: project.name,
type: project.type,
media: project.media.map((m) => m.id.value).filter((id) => id !== undefined),
timelines: project.timelines.map((m) => m.id)
};
subscriber.next({
status: 'Waiting'
});
Expand All @@ -30,7 +42,7 @@ export default class IndexedDbStorageController extends BaseStorageController {
this.StopSaveProject.complete();
});

from(this.db.project.put(project, project.id))
from(this.db.project.put(storableProject, project.id))
.pipe(takeUntil(this.StopSaveProject))
.subscribe(() => {
subscriber.next({
Expand All @@ -41,14 +53,53 @@ export default class IndexedDbStorageController extends BaseStorageController {
});
});
}
async LoadProject(projectId: string): Promise<StoredProject> {
return await this.db.project.get(projectId);
async LoadProject(projectId: string): Promise<BaseProject | undefined> {
return this.db.project
.get(projectId)
.then<SimpleProject | undefined, never>(async (project) => {
if (!project) return;

if (project.type == 'Simple') {
const proj = new SimpleProject();
proj.id = project.id;
const mediaFetches = project.media.map((m) => this.LoadMedia(m));
const timelineFetches = project.timelines.map((t) =>
this.LoadTimeline<SimpleTimeline>(t)
);
proj.media.push(
...(await Promise.all(mediaFetches)).filter((m) => m !== undefined)
);
proj.timelines.push(
...(await Promise.all(timelineFetches)).filter((t) => t !== undefined)
);
proj.name = project.name;
return proj;
} else {
return;
}
});
}

SaveMedia(media: StoredMedia): SaveObservable {
throw new Error('Method not implemented.');
}
LoadMedia(mediaId: string): Promise<StoredMedia> {
LoadMedia(mediaId: string): Promise<Media | undefined> {
throw new Error('Method not implemented.');
}
async GetMediaFromHash(hash: string): Promise<Media | undefined> {
const m = await this.db.media.get({
contentHash: hash
});
const media = new Media(m?.id)
return ;
}

SaveTimeline(timeline: BaseTimeline): SaveObservable {
throw new Error('Method not implemented.');
}
LoadTimeline<Timeline extends BaseTimeline = BaseTimeline>(
timelineId: string
): Promise<Timeline | undefined> {
throw new Error('Method not implemented.');
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { Storage } from '@/base/Storage';
import { generateMediaThumbnail } from '@/helpers/Video/GenerateMediaThumbnail';
import { getVideoInfo } from '@/helpers/Video/GetVideoInfo';
import { createMD5 } from 'hash-wasm';
import { Observable } from 'rxjs';
import { v4 as uuidv4 } from 'uuid';
import type { StoredMedia } from '../db';

const chunkSize = 64 * 1024 * 1024;

export default class IdbMediaManager {
static storedMedia = shallowRef<StoredMedia[]>([]);

static storeMedia(file: File) {
return new Observable<LoadMediaProgress>((subscriber) => {
// Thanks RxJs, makes sense
Expand Down Expand Up @@ -47,10 +45,8 @@ export default class IdbMediaManager {

const hash = hasher.digest();

// Check if a file with the same has already is stored, if so, use it
const existingMedia = await db.media.get({
contentHash: hash
});
// Check if a file with the same hash is already stored, if so, use it
const existingMedia = await Storage.getStorage().HasMediaHash(hash);

if (existingMedia) {
subscriber.next({
Expand All @@ -77,12 +73,12 @@ export default class IdbMediaManager {

const uuid = uuidv4();

db.media.add({
Storage.getStorage().SaveMedia({
id: uuid,
name: file.name,
contentHash: hash,
data: file,
fileInfo: fileInfo,
fileInfo,
previewImage: thumbnail
});
subscriber.next({
Expand All @@ -103,19 +99,3 @@ interface LoadMediaProgress {
id?: string;
hashProgress: number;
}

db.media.hook.creating.subscribe(async () => {
IdbMediaManager.storedMedia.value = await db.media.toArray();
triggerRef(IdbMediaManager.storedMedia);
});
db.media.hook.deleting.subscribe(async () => {
IdbMediaManager.storedMedia.value = await db.media.toArray();
triggerRef(IdbMediaManager.storedMedia);
});
db.media.hook.updating.subscribe(async () => {
IdbMediaManager.storedMedia.value = await db.media.toArray();
triggerRef(IdbMediaManager.storedMedia);
});
db.media.toArray().then((media) => {
IdbMediaManager.storedMedia.value = media;
});
Loading

0 comments on commit a71396d

Please sign in to comment.