Skip to content

Commit

Permalink
Progress on library component
Browse files Browse the repository at this point in the history
  • Loading branch information
Joery committed Apr 3, 2024
1 parent 7af9d8d commit a247378
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 98 deletions.
2 changes: 2 additions & 0 deletions packages/safelight/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"change-case": "^5.4.3",
"dexie": "^3.2.7",
"ffprobe-wasm": "^0.3.1",
"fuzzysearch": "^1.0.3",
"hash-wasm": "^4.11.0",
"lodash": "^4.17.21",
"luxon": "^3.4.4",
Expand All @@ -50,6 +51,7 @@
"@iconify-json/ph": "^1.1.11",
"@tsconfig/node20": "^20.1.2",
"@types/dom-webcodecs": "^0.1.11",
"@types/fuzzysearch": "^1.0.2",
"@types/luxon": "^3.4.2",
"@types/node": "^20.11.30",
"@types/uuid": "^9.0.8",
Expand Down
178 changes: 142 additions & 36 deletions packages/safelight/src/components/Editor/Library/Library.vue
Original file line number Diff line number Diff line change
@@ -1,50 +1,156 @@
<template>
<SLCard>
<DataView
:value="media"
scrollable
scroll-height="400px"
data-key="id"
class="m-4 resize-x"
>
<template #header>
<Toolbar class="p-1">
<template #center>
<IconField iconPosition="left">
<InputIcon> <PhMagnifyingGlass /> </InputIcon>
<InputText size="small" placeholder="Search"> </InputText>
</IconField>
</template>
</Toolbar>
</template>
<template #list="{ items }: { items: UnwrapRef<Media>[] }">
<DataView :value="sortedAndFiltered" scrollable scroll-height="400px" data-key="id">
<template #header>
<Toolbar class="border-none p-0">
<template #start>
<InputGroup class="mr-2">
<InputGroupAddon class="p-0">
<PhMagnifyingGlass size="14" />
</InputGroupAddon>
<InputText v-model="search" placeholder="Search"> </InputText>
</InputGroup>
<InputGroup>
<Button
size="small"
class="p-0"
outlined
severity="secondary"
:aria-label="'Sort ' + (sortDescending ? 'ascending' : 'descending')"
@click="sortDescending = !sortDescending"
>
<template #icon>
<PhSortAscending v-if="!sortDescending" size="14" />
<PhSortDescending v-else size="14" />
</template>
</Button>
<Dropdown
v-model="sortBy"
style="line-height: 1.2"
aria-label="Sort by"
:options="['Name', 'Duration', 'File type']"
/>
</InputGroup>
</template>
</Toolbar>
</template>
<template #list="{ items }: { items: UnwrapRef<Media>[] }">
<div
class="grid-nogutter grid"
role="grid"
style="grid-template-columns: repeat(auto-fill, minmax(150px, 1fr))"
>
<div
class="grid-nogutter grid"
style="grid-template-columns: repeat(auto-fill, minmax(150px, 1fr))"
v-for="item in items"
:key="item.id"
role="gridcell"
class="border-round m-1 flex min-h-32 flex-col rounded-md border-solid border-white/10"
style="border-width: 1px"
:aria-label="item.name"
>
<div
v-for="(item, index) in items"
:key="item.id"
class="border-round m-2 flex min-h-32 flex-col rounded-md border-solid border-white/10"
style="border-width: 1px"
class="bg-checkerboard flex aspect-video w-full items-center justify-center"
>
<div class="flex aspect-video w-full items-center justify-center">
<img class="max-h-full max-w-full rounded-t" :src="item.previewImage" />
</div>
<p class="text-sm">
{{ item.name }}
</p>
<img
v-if="item.previewImage"
class="max-h-full max-w-full rounded-t-md"
:aria-label="'Preview image for ' + item.name"
:src="item.previewImage"
/>
<Skeleton
v-else
class="max-h-full max-w-full rounded-none rounded-t-md"
height="100%"
width="100%"
/>
</div>
<p
v-tooltip.bottom="{ value: item.name, showDelay: 1000 }"
class="m-0 mt-1 max-w-full overflow-x-hidden overflow-ellipsis text-base"
>
{{ item.name }}
</p>
<p v-if="item.duration > 0">
{{ item.duration }}
</p>
</div>
</template>
</DataView>
</SLCard>
</div>
</template>
</DataView>
</template>

<script setup lang="ts">
import type Media from '@/controllers/Media/Media';
import { PhFileSearch } from '@phosphor-icons/vue';
import { PhMagnifyingGlass, PhSortDescending } from '@phosphor-icons/vue';
import fuzzysearch from 'fuzzysearch';
import InputGroup from 'primevue/inputgroup';
import InputGroupAddon from 'primevue/inputgroupaddon';
import type { UnwrapRef } from 'vue';
const media = defineModel<(Media | UnwrapRef<Media>)[]>({ default: [] });
const props = defineProps<{
media: UnwrapRef<Media[]>;
}>();
const emit = defineEmits<{
'update:modelValue': any[];
}>();
const media = useVModel(props, 'media', emit);
const search = ref('');
const sortBy = ref<sortOptions>('Name');
const sortDescending = ref(false);
const sortedAndFiltered = ref<Media[]>([]);
watchDebounced([props.media, search, sortBy, sortDescending], sortAndFilter, {
deep: true,
debounce: 100,
maxWait: 1000,
immediate: true
});
function sortAndFilter() {
const filtered = media.value.filter((elem) => {
if (search.value.length == 0) {
return true;
}
return fuzzysearch(search.value.toLowerCase(), elem.name.toLowerCase());
});
filtered.sort((a, b) => {
const item1 = sortDescending.value ? b : a;
const item2 = sortDescending.value ? a : b;
switch (sortBy.value) {
case 'Duration':
return item1.duration - item2.duration;
case 'File type':
return (item1.name.split('.').at(-1) ?? 'ZZZ').localeCompare(
item2.name.split('.').at(-1) ?? 'ZZZZZ'
);
default:
return item1.name.localeCompare(item2.name, undefined, {
numeric: true,
sensitivity: 'base'
});
}
});
sortedAndFiltered.value = filtered;
}
type sortOptions = 'Name' | 'Duration' | 'File type';
</script>

<style lang="scss" scoped>
.bg-checkerboard {
/* This is beautifully simple
https://stackoverflow.com/a/65129916 */
background: repeating-conic-gradient(#ffffff0a 0% 25%, transparent 0% 50%) 50% / 20px 20px;
}
:deep(.p-dataview-header) {
@apply p-1;
}
</style>
9 changes: 3 additions & 6 deletions packages/safelight/src/controllers/Media/Media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ export default class Media {
* @description The duration of this media item. By default it is set to 5 seconds, which will apply to images
* @default 5000
*/
public duration = ref(5000);
public duration = ref(0);
public fileInfo = ref<FileInfo>();

constructor(public mediaId: string) {
constructor(mediaId: string) {
this.id.value = mediaId;
db.media.get({ id: mediaId }).then((med) => {
if (med) {
this.name.value = med.name;
Expand All @@ -25,10 +26,6 @@ export default class Media {

this.id.value = med.id;
this.loaded.value = true;

setInterval(() => {
this.duration.value += 100;
}, 1000);
}
});
}
Expand Down
6 changes: 3 additions & 3 deletions packages/safelight/src/controllers/Project/SimpleProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ export default class SimpleProject extends BaseProject {
public name = 'Untitled';
public type: ProjectType = 'Simple';

public media: Media[] = [];
public media: Media[] = reactive([]);
public timelines: SimpleTimeline[] = [];
public activeTimeline: number;
public activeTimeline: SimpleTimeline;

constructor() {
super();

const tl = new SimpleTimeline();

this.timelines = [tl];
this.activeTimeline = 0;
this.activeTimeline = tl;
}
}
6 changes: 5 additions & 1 deletion packages/safelight/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { createRouter, createWebHistory } from 'vue-router/auto';
import App from './App.vue';

import PrimeVue, { type PrimeVueConfiguration } from 'primevue/config';
import 'primevue/resources/themes/aura-dark-amber/theme.css';
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';
Expand All @@ -28,4 +29,7 @@ app.use(PrimeVue, {
ripple: false
} as PrimeVueConfiguration);

// Directives
app.directive('tooltip', Tooltip);

app.mount('#app');
44 changes: 4 additions & 40 deletions packages/safelight/src/style.scss
Original file line number Diff line number Diff line change
@@ -1,46 +1,7 @@
@tailwind components;
@tailwind utilities;

// body {
// @apply m-0 h-screen w-screen text-white bg-surface-900 overflow-hidden;

// #app {
// @apply overflow-auto;
// }
// }

// #app {
// @apply w-full h-full
// }

// h1 {
// @apply text-3xl mb-4;
// }

// h2 {
// @apply text-2xl mb-4;
// }

// h3 {
// @apply text-xl;
// }

// h4 {
// @apply text-lg;
// }

// h5 {
// @apply text-sm;
// }

// h6 {
// @apply text-xs;
// }


// input {
// @apply text-black
// }
/* color palette from <https://github.com/vuejs/theme> */
:root {
--vt-c-white: #ffffff;
Expand Down Expand Up @@ -100,8 +61,11 @@ body {
line-height: 1.6;
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

html {
font-size: 14px;
}
Loading

0 comments on commit a247378

Please sign in to comment.