From 856e1e89f95c029f3a75eeb14c42eb579bb1112f Mon Sep 17 00:00:00 2001 From: Joery <44531907+Joery-M@users.noreply.github.com> Date: Tue, 16 Apr 2024 21:44:51 +0200 Subject: [PATCH] Separated out project list to other component. Opened project is saved using session storage. Added a message for when no project could be loaded when going into /editor route. Fixed library not showing images correctly and a type error. Moved creating and opening projects to project store. Fixed projects not being able to load when a media item associated with it is unavailable. Added more functionality to library items. --- .../src/components/Editor/Library/Library.vue | 69 +++++----- .../components/Editor/Library/LibraryItem.vue | 113 ++++++++++++++++ .../Menu/ProjectList/ProjectList.vue | 74 +++++++++++ packages/safelight/src/main.ts | 6 +- packages/safelight/src/stores/useProject.ts | 51 +++++++- packages/safelight/src/style.scss | 10 ++ .../safelight/src/views/Editor/Editor.vue | 123 +++++++++++------- packages/safelight/src/views/projects.vue | 108 +-------------- .../shared/src/Storage/IndexedDbStorage.ts | 37 ++++-- .../helpers/Video/GenerateMediaThumbnail.ts | 1 + 10 files changed, 382 insertions(+), 210 deletions(-) create mode 100644 packages/safelight/src/components/Editor/Library/LibraryItem.vue create mode 100644 packages/safelight/src/components/Menu/ProjectList/ProjectList.vue diff --git a/packages/safelight/src/components/Editor/Library/Library.vue b/packages/safelight/src/components/Editor/Library/Library.vue index 0680745c..20baf034 100644 --- a/packages/safelight/src/components/Editor/Library/Library.vue +++ b/packages/safelight/src/components/Editor/Library/Library.vue @@ -5,7 +5,6 @@ scroll-height="400px" class="flex h-full flex-col" data-key="id" - @dblclick="fileDialog.open()" > + - diff --git a/packages/safelight/src/components/Menu/ProjectList/ProjectList.vue b/packages/safelight/src/components/Menu/ProjectList/ProjectList.vue new file mode 100644 index 00000000..38a154ae --- /dev/null +++ b/packages/safelight/src/components/Menu/ProjectList/ProjectList.vue @@ -0,0 +1,74 @@ + + + diff --git a/packages/safelight/src/main.ts b/packages/safelight/src/main.ts index 2a37149a..fb68d4c8 100644 --- a/packages/safelight/src/main.ts +++ b/packages/safelight/src/main.ts @@ -4,12 +4,10 @@ import { createRouter, createWebHistory } from 'vue-router/auto'; import App from './App.vue'; import PrimeVue, { type PrimeVueConfiguration } from 'primevue/config'; +import ConfirmationService from 'primevue/confirmationservice'; import 'primevue/resources/primevue.min.css'; import 'primevue/resources/themes/aura-dark-amber/theme.css'; import Tooltip from 'primevue/tooltip'; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -//@ts-ignore -// import SafelightTheme from '@/@core/Safelight'; import './style.scss'; @@ -24,10 +22,10 @@ export const pinia = createPinia(); app.use(pinia); app.use(router); app.use(PrimeVue, { - // pt: SafelightTheme, inputStyle: 'outlined', ripple: false } as PrimeVueConfiguration); +app.use(ConfirmationService); // Directives app.directive('tooltip', Tooltip); diff --git a/packages/safelight/src/stores/useProject.ts b/packages/safelight/src/stores/useProject.ts index 8b4e2e68..9a1d9b20 100644 --- a/packages/safelight/src/stores/useProject.ts +++ b/packages/safelight/src/stores/useProject.ts @@ -1,5 +1,6 @@ +import { router } from '@/main'; import type BaseProject from '@safelight/shared/base/Project'; -import { Storage } from '@safelight/shared/base/Storage'; +import { Storage, type StoredProject } from '@safelight/shared/base/Storage'; import MediaManager from '@safelight/shared/Storage/MediaManager'; export const useProject = defineStore('Project', () => { @@ -8,9 +9,13 @@ export const useProject = defineStore('Project', () => { const timelineViewEnd = ref(0); const project = shallowRef(); + const isLoaded = ref(false); function setProject(newProject: BaseProject) { project.value = newProject; + isLoaded.value = true; + + useSessionStorage('project', '').value = newProject.id; } function loadFile(file: File) { @@ -26,7 +31,6 @@ export const useProject = defineStore('Project', () => { (m) => m.id == storingProcessing.value!.id ); - console.log(existingMedia); if (!existingMedia) { const media = await Storage.getStorage().LoadMedia( storingProcessing.value.id! @@ -36,7 +40,6 @@ export const useProject = defineStore('Project', () => { project.value!.media.push(media); save(); } - // project.activeTimeline.createTimelineItem(media); } resolve(); @@ -53,9 +56,49 @@ export const useProject = defineStore('Project', () => { project, setProject, loadFile, + isLoaded, cursor, timelineViewStart, timelineViewEnd, - save + save, + openProject, + new: { + newSimpleProject + } }; }); + +async function newSimpleProject() { + const IndexedDbStorageController = (await import('@safelight/shared/Storage/IndexedDbStorage')) + .default; + Storage.setStorage(new IndexedDbStorageController()); + const projectStore = useProject(); + const SimpleProject = (await import('@safelight/shared/Project/SimpleProject')).default; + projectStore.setProject(new SimpleProject()); +} + +async function openProject(selectedProject: StoredProject) { + if (selectedProject.type == 'Simple') { + const IndexedDbStorageController = ( + await import('@safelight/shared/Storage/IndexedDbStorage') + ).default; + + const projectStore = useProject(); + Storage.setStorage(new IndexedDbStorageController()); + + const project = await Storage.getStorage().LoadProject(selectedProject.id); + + if (project) { + projectStore.setProject(project); + await toEditor(); + } else { + console.error('Could not load project'); + } + } else { + console.error('Project type not supported'); + } +} + +async function toEditor() { + await router.push('/editor'); +} diff --git a/packages/safelight/src/style.scss b/packages/safelight/src/style.scss index cf60635c..238997d0 100644 --- a/packages/safelight/src/style.scss +++ b/packages/safelight/src/style.scss @@ -65,8 +65,18 @@ body { text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + + // Might wanna change this in the future + display: flex; + min-height: 100vh; + + #app { + flex-grow: 1; + min-height: 100%; + } } html { font-size: 14px; + min-height: 100%; } \ No newline at end of file diff --git a/packages/safelight/src/views/Editor/Editor.vue b/packages/safelight/src/views/Editor/Editor.vue index 9b959113..7a9e4c23 100644 --- a/packages/safelight/src/views/Editor/Editor.vue +++ b/packages/safelight/src/views/Editor/Editor.vue @@ -1,68 +1,97 @@ diff --git a/packages/safelight/src/views/projects.vue b/packages/safelight/src/views/projects.vue index 3cbcd63b..e731ce6f 100644 --- a/packages/safelight/src/views/projects.vue +++ b/packages/safelight/src/views/projects.vue @@ -1,113 +1,9 @@ - + diff --git a/packages/shared/src/Storage/IndexedDbStorage.ts b/packages/shared/src/Storage/IndexedDbStorage.ts index 2ad0653e..34c294b5 100644 --- a/packages/shared/src/Storage/IndexedDbStorage.ts +++ b/packages/shared/src/Storage/IndexedDbStorage.ts @@ -48,16 +48,29 @@ export default class IndexedDbStorageController extends BaseStorageController { 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(t) - ); - proj.media.push( - ...(await Promise.all(mediaFetches)).filter((m) => m !== undefined) - ); - proj.timelines.push( - ...(await Promise.all(timelineFetches)).filter((t) => t !== undefined) - ); + const mediaFetches = project.media.map(async (m) => { + const media = await this.LoadMedia(m).catch((reason) => { + console.error('Error loading media file for project', reason); + }); + if (media) { + proj.media.push(media); + } else { + // TODO: Add a way for media to be marked as missing + } + }); + const timelineFetches = project.timelines.map(async (t) => { + const timeline = await this.LoadTimeline(t).catch( + (reason) => { + console.error('Error loading timeline for project', reason); + } + ); + if (timeline) { + proj.timelines.push(timeline); + } + }); + + // Load all timelines and media + await Promise.allSettled([...timelineFetches, ...mediaFetches]); proj.name = project.name; return proj; } else { @@ -107,9 +120,7 @@ export default class IndexedDbStorageController extends BaseStorageController { this.db.media .get({ id: mediaId }) .then((storedMedia) => { - if (storedMedia) { - resolve(this.storedMediaToMedia(storedMedia)); - } + resolve(storedMedia ? this.storedMediaToMedia(storedMedia) : undefined); }) .catch(reject); }); diff --git a/packages/shared/src/helpers/Video/GenerateMediaThumbnail.ts b/packages/shared/src/helpers/Video/GenerateMediaThumbnail.ts index 079331bf..1d9ac180 100644 --- a/packages/shared/src/helpers/Video/GenerateMediaThumbnail.ts +++ b/packages/shared/src/helpers/Video/GenerateMediaThumbnail.ts @@ -1,6 +1,7 @@ import MimeMatcher from 'mime-matcher'; import MissingThumbnail from '../../../assets/missing_thumbnail.png?url'; +// TODO: Fix video not working for my HDR test video (HDR RGB lights.MOV) export function generateMediaThumbnail(file: File, percent = 0.1, maxWidth = 427, maxHeight = 240) { return new Promise((resolve) => { const isVideo = new MimeMatcher('video/*').match(file.type);