Skip to content

Commit 1f86e40

Browse files
authored
Merge pull request #23 from jrafaaael/fix/sort-descending
fix: keep latest videos on top of recording list
2 parents 6eb64e9 + 18da492 commit 1f86e40

File tree

6 files changed

+76
-18
lines changed

6 files changed

+76
-18
lines changed

src/lib/utils/opfs.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export async function rename(oldHandle: FileSystemDirectoryHandle, newName: string) {
2+
const root = await navigator.storage.getDirectory();
3+
const newFolder = await root.getDirectoryHandle(newName, {
4+
create: true
5+
});
6+
7+
for await (const [filename] of oldHandle) {
8+
const oldFile = await (await oldHandle.getFileHandle(filename)).getFile();
9+
const newFile = await newFolder.getFileHandle(filename, { create: true });
10+
const writable = await newFile.createWritable();
11+
12+
await writable.write(oldFile);
13+
14+
await writable.close();
15+
}
16+
17+
await oldHandle.remove({ recursive: true });
18+
}

src/routes/(recorder)/+page.svelte

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,14 @@
1313
if (!file) return;
1414
if (!file.type.includes('video')) return;
1515
16+
const folderName = new Date().getTime().toString();
1617
const filename = file.name;
17-
const folderName = file.name.split('.').slice(0, -1).join('.');
18+
const filenameWithoutExtension = filename.split('.').slice(0, -1).join('.');
19+
const info = {
20+
name: filenameWithoutExtension
21+
};
22+
23+
localStorage.setItem(folderName, JSON.stringify(info));
1824
1925
await saveFile(file, `${folderName}/${filename}`);
2026
await goto(folderName);

src/routes/(recorder)/components/recording-list.svelte

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script lang="ts">
22
import { onMount } from 'svelte';
3+
import { rename } from '$lib/utils/opfs';
34
import Trash from '$lib/components/icons/trash.svelte';
45
56
let recordings: string[] = [];
@@ -22,12 +23,46 @@
2223
}
2324
2425
onMount(async () => {
25-
recordings = await getRecordings();
26+
const root = await navigator.storage.getDirectory();
27+
const folders: string[] = await getRecordings();
28+
29+
recordings = await Promise.all(
30+
folders.map(async (name) => {
31+
/**
32+
* Previously, recordings that were drag-n-drop'd in Videmo were saved with their original filename (can be alphanumeric). However, when users record directly from Chrome,
33+
* their filename is the recording date in UTC (is a number). This is a problem because OPFS sort files alphabetically, so:
34+
* 1. some recordings that were drag-n-drop'd are listed at top of recording list, even if the last user video was recorded directly from Chrome.
35+
* 2. some recordings that were drag-n-drop'd are listed at bottom of recording list, even if this was the latest video in Videmo.
36+
* With this conditional, I rename folders with original filename from drag-n-drop'd recordings and save it with the current date in UTC as filename
37+
* to keep compatibility with the old behavior. However, this create a new problem: users will search their recordings with original name because
38+
* those recordings were saved with this behavior. To solve this, in their associated object value in localStorage, I create a new key called `name` to save the original name.
39+
* This allows me to develop some new features:
40+
* 1. rename recordings
41+
* 2. sort recordings alphabetically and by date
42+
*/
43+
if (isNaN(Number(name))) {
44+
const folder = await root.getDirectoryHandle(name);
45+
const newFolderName = new Date().getTime().toString();
46+
const info = JSON.parse(localStorage.getItem(name) ?? '{}');
47+
const updated = { ...info, name };
48+
49+
await rename(folder, newFolderName);
50+
51+
localStorage.removeItem(name);
52+
localStorage.setItem(newFolderName, JSON.stringify(updated));
53+
54+
return newFolderName;
55+
}
56+
57+
return name;
58+
})
59+
);
2660
});
2761
</script>
2862

2963
{#each recordings as record}
30-
{@const folderName = isNaN(Number(record)) ? record : new Date(+record).toLocaleString()}
64+
{@const recordingInfo = JSON.parse(localStorage.getItem(record) ?? '{}')}
65+
{@const folderName = recordingInfo.name ?? new Date(+record).toLocaleString()}
3166
<article class="flex flex-col gap-2">
3267
<a href="/{record}">
3368
<span class="w-full aspect-video bg-white/5 border border-white/5 rounded-md inline-block" />

src/routes/[id]/+page.svelte

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
import { edits } from './stores/edits.store';
88
import { videoStatus } from './stores/video-status.store';
99
import { DEFAULT_VALUE as DEFAULT_BACKGROUND, background } from './stores/background.store';
10-
import { appearence } from './stores/general-appearance.store';
10+
import {
11+
DEFAULT_VALUE as DEFAULT_APPEARENCE,
12+
appearence
13+
} from './stores/general-appearance.store';
1114
import { zooms } from './stores/zooms.store';
1215
import Header from './components/header.svelte';
1316
import Toolbox from './components/toolbox/toolbox.svelte';
@@ -29,15 +32,11 @@
2932
? JSON.parse(localStorage.getItem(folderName)!)
3033
: null;
3134
32-
if (values !== null) {
33-
zooms.load(values.zooms);
34-
$background = values.background;
35-
$appearence = values.appearence;
36-
$edits = values.trimmings;
37-
} else {
38-
zooms.reset();
39-
$background = DEFAULT_BACKGROUND!;
40-
appearence.reset();
35+
zooms.load(values?.zooms ?? []);
36+
$background = values?.background ?? DEFAULT_BACKGROUND;
37+
$appearence = values?.appearence ?? DEFAULT_APPEARENCE;
38+
if (values?.trimmings) {
39+
$edits = values?.trimmings;
4140
}
4241
4342
const root = await navigator.storage.getDirectory();
@@ -50,7 +49,7 @@
5049
const duration = await getBlobDuration(mp4);
5150
5251
recording.set({ id: '1', url: mp4, duration });
53-
if (!values) {
52+
if ($edits.endAt > duration) {
5453
edits.set({ startAt: 0, endAt: duration });
5554
}
5655
}

src/routes/[id]/components/header.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
1313
export let getFrameAsImage: () => string;
1414
export let getMP4: () => Promise<string>;
15-
const folderName = isNaN(Number(+$page.params.id))
16-
? $page.params.id
17-
: new Date(+$page.params.id).toLocaleString();
15+
const folderId = $page.params.id;
16+
const recordingInfo = JSON.parse(localStorage.getItem(folderId) ?? '{}');
17+
const folderName = recordingInfo.name ?? new Date(+folderId).toLocaleString();
1818
let extension = writable(EXPORT_OPTIONS.at(0));
1919
let isExporting = false;
2020

src/routes/[id]/stores/general-appearance.store.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { writable } from 'svelte/store';
22

3-
const DEFAULT_VALUE = {
3+
export const DEFAULT_VALUE = {
44
padding: 24,
55
cornerRadius: 12,
66
shadow: {

0 commit comments

Comments
 (0)