Skip to content

Commit

Permalink
Made projects page work.
Browse files Browse the repository at this point in the history
Fixed media loading after loading file.
Changed setStorage to not throw when storage already set
Separated out tests in package.json
  • Loading branch information
Joery-M committed Apr 15, 2024
1 parent ec52f5e commit 682ab82
Show file tree
Hide file tree
Showing 15 changed files with 242 additions and 119 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
10 changes: 8 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
91 changes: 46 additions & 45 deletions packages/safelight/src/components/Editor/Library/Library.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
<template>
<DataView :value="sortedAndFiltered" scrollable scroll-height="400px" data-key="id">
<DataView
:value="sortedAndFiltered"
scrollable
scroll-height="400px"
class="flex h-full flex-col"
data-key="id"
@dblclick="fileDialog.open()"
>
<template #header>
<Toolbar class="border-none p-0">
<template #start>
Expand Down Expand Up @@ -64,95 +71,83 @@
/>
</div>
<p
v-tooltip.bottom="{ value: item.name, showDelay: 1000 }"
v-tooltip.bottom="{ value: item.name.value, showDelay: 1000 }"
class="m-0 mt-1 max-w-full overflow-x-hidden overflow-ellipsis text-base"
>
{{ item.name }}
{{ item.name.value }}
</p>
<p v-if="item.duration > 0">
{{ item.duration }}
</p>
</div>
</div>
</template>
<template #empty>
<div class="grid h-full place-items-center" @dblclick="fileDialog.open()">
<label class="select-none opacity-60">No media imported</label>
</div>
</template>
</DataView>
</template>

<script setup lang="ts">
import { PhMagnifyingGlass, PhSortDescending } from '@phosphor-icons/vue';
import type BaseProject from '@safelight/shared/base/Project';
import type Media from '@safelight/shared/Media/Media';
import MediaManager from '@safelight/shared/Storage/MediaManager';
import Media from '@safelight/shared/Media/Media';
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 emit = defineEmits<{
'update:modelValue': any[];
}>();
const dropZone = useDropZone(document.body, {
useDropZone(document.body, {
onDrop(files) {
files?.forEach(project);
files?.forEach(project.loadFile);
},
dataTypes(types) {
return !types.some((val) => {
return !new MimeMatcher('image/*', 'video/*').match(val);
});
}
});
const fileDialog = useFileDialog({
accept: 'image/*,video/*'
});
function loadFile(file: File) {
return new Promise<void>((resolve) => {
const storingProcessing = useObservable(MediaManager.StoreMedia(file));
watch(storingProcessing, (s) => {
console.log(s?.type, s?.hashProgress);
});
watch(storingProcessing, () => {
if (storingProcessing.value && storingProcessing.value.type == 'done') {
const existingMedia = project.media.some(
(m) => m.id.value == storingProcessing.value!.id
);
if (!existingMedia) {
const media = new Media(storingProcessing.value.id!);
fileDialog.onChange((fileList) => {
if (!fileList) return;
project.media.push(media);
project.activeTimeline.createTimelineItem(media);
}
for (let i = 0; i < fileList.length; i++) {
const item = fileList.item(i);
resolve();
}
});
});
}
if (item) {
project.loadFile(item);
}
}
});
const project = inject<BaseProject>('currentProject');
const media = useVModel(props, 'media', emit);
const project = useProject();
const media = project.project!.media;
const search = ref('');
const sortBy = ref<sortOptions>('Name');
const sortDescending = ref(false);
const sortedAndFiltered = ref<Media[]>([]);
const sortedAndFiltered = shallowRef<Media[]>([]);
watchDebounced([props.media, search, sortBy, sortDescending], sortAndFilter, {
watchDebounced([media, search, sortBy, sortDescending], sortAndFilter, {
deep: true,
debounce: 100,
maxWait: 1000,
immediate: true
});
function sortAndFilter() {
const filtered = media.value.filter((elem) => {
const filtered = media.filter((elem) => {
if (search.value.length == 0) {
return true;
}
return fuzzysearch(search.value.toLowerCase(), elem.name.toLowerCase());
return fuzzysearch(search.value.toLowerCase(), elem.name.value.toLowerCase());
});
const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });
Expand All @@ -161,16 +156,16 @@ function sortAndFilter() {
const item1 = sortDescending.value ? b : a;
const item2 = sortDescending.value ? a : b;
const ext1 = item1.name.split('.').at(-1) ?? 'ZZZ';
const ext2 = item2.name.split('.').at(-1) ?? 'ZZZ';
const ext1 = item1.name.value.split('.').at(-1) ?? 'ZZZ';
const ext2 = item2.name.value.split('.').at(-1) ?? 'ZZZ';
switch (sortBy.value) {
case 'Duration':
return item1.duration - item2.duration;
return item1.duration.value - item2.duration.value;
case 'File type':
return collator.compare(ext1, ext2);
default:
return collator.compare(item1.name, item2.name);
return collator.compare(item1.name.value, item2.name.value);
}
});
Expand All @@ -190,4 +185,10 @@ type sortOptions = 'Name' | 'Duration' | 'File type';
:deep(.p-dataview-header) {
@apply p-1;
}
:deep(.p-dataview-content) {
@apply flex-1;
}
:deep(.p-dataview-emptymessage) {
@apply h-full;
}
</style>
2 changes: 1 addition & 1 deletion packages/safelight/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Tooltip from 'primevue/tooltip';

import './style.scss';

const router = createRouter({
export const router = createRouter({
history: createWebHistory()
});

Expand Down
53 changes: 49 additions & 4 deletions packages/safelight/src/stores/useProject.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,61 @@
import SimpleProject from '@safelight/shared/Project/SimpleProject';
import type BaseProject from '@safelight/shared/base/Project';
import { Storage } from '@safelight/shared/base/Storage';
import MediaManager from '@safelight/shared/Storage/MediaManager';

export const useProject = defineStore('Project', () => {
const activeTimelineIndex = ref(0);
const cursor = ref(0);
const timelineViewStart = ref(0);
const timelineViewEnd = ref(0);

const project = new SimpleProject();
const project = shallowRef<BaseProject>();

function setProject(newProject: BaseProject) {
project.value = newProject;
}

function loadFile(file: File) {
return new Promise<void>((resolve) => {
const storingProcessing = useObservable(MediaManager.StoreMedia(file));
watch(storingProcessing, (s) => {
console.log(s?.type, s?.hashProgress);
});

watch(storingProcessing, async () => {
if (storingProcessing.value && storingProcessing.value.type == 'done') {
const existingMedia = project.value!.media.some(
(m) => m.id == storingProcessing.value!.id
);

console.log(existingMedia);
if (!existingMedia) {
const media = await Storage.getStorage().LoadMedia(
storingProcessing.value.id!
);

if (media) {
project.value!.media.push(media);
save();
}
// project.activeTimeline.createTimelineItem(media);
}

resolve();
}
});
});
}

function save() {
if (project.value) Storage.getStorage().SaveProject(project.value);
}

return {
project,
setProject,
loadFile,
cursor,
timelineViewStart,
timelineViewEnd
timelineViewEnd,
save
};
});
54 changes: 19 additions & 35 deletions packages/safelight/src/views/Editor/Editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<SplitterPanel>
<Splitter>
<SplitterPanel>
<TabView>
<TabView class="flex h-full flex-col">
<TabPanel>
<template #header>
<div class="flex items-center gap-2">
Expand All @@ -14,14 +14,14 @@
<!-- Dont break highlighting -->
<!-- eslint-disable-next-line prettier/prettier -->
<!-- prettier-ignore -->
<Library :media="(project.media as any)" />
<Library />
</TabPanel>
</TabView>
</SplitterPanel>
<SplitterPanel>
<Monitor
v-if="project.activeTimeline"
:timeline="project.activeTimeline"
v-if="project.project?.timeline"
:timeline="project.project?.timeline"
class="min-h-100 w-full"
/>
</SplitterPanel>
Expand All @@ -35,18 +35,16 @@

<script setup lang="ts">
import { Storage } from '@safelight/shared/base/Storage';
import MediaManager from '@safelight/shared/Storage/MediaManager';
import { useObservable } from '@vueuse/rxjs';
import SplitterPanel from 'primevue/splitterpanel';
const fileDialog = useFileDialog({
accept: 'image/*,video/*'
});
// const fileDialog = useFileDialog({
// accept: 'image/*,video/*'
// });
const project = new SimpleProject();
const loading = ref(false);
const project = useProject();
// const loading = ref(false);
fileDialog.onChange((fileList) => {
/* fileDialog.onChange((fileList) => {
if (!fileList) return;
loading.value = true;
Expand All @@ -59,40 +57,26 @@ fileDialog.onChange((fileList) => {
Promise.all(promises).finally(() => {
loading.value = false;
});
});
function loadFile(file: File) {
return new Promise<void>((resolve) => {
const storingProcessing = useObservable(MediaManager.StoreMedia(file));
watch(storingProcessing, (s) => {
console.log(s?.type, s?.hashProgress);
});
watch(storingProcessing, async () => {
if (storingProcessing.value && storingProcessing.value.type == 'done') {
const media = await Storage.getStorage().LoadMedia(storingProcessing.value.id!);
if (media) {
project.media.push(media);
project.activeTimeline.createTimelineItem(media);
}
resolve();
}
});
});
}
}); */
onBeforeUnmount(() => {
// reset store, which currently tries to call 'this', trying to reference the store
// project.$dispose();
if (project.project) Storage.getStorage().SaveProject(project.project);
});
</script>

<style lang="scss" scoped>
.vertSlitter {
height: 100vh;
}
:deep(.p-tabview-panels) {
@apply flex-1;
}
:deep(.p-tabview-panel) {
@apply h-full;
}
</style>

<route lang="json">
Expand Down
Loading

0 comments on commit 682ab82

Please sign in to comment.