authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2025-10-12 10:03:32-07:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2025-10-14 02:40:48-07:00
log5fde9a0d10e1f190f9994c0f3673777365c27902
treef22400b7dde1c780e6945c5ad9897bb8fb0c39b6
parentf171c7f1cd5249ccd190aa99587fe7c3cbb4f209
signature Commit is signed but in an unrecognized format.

feat(site/file-viewer): special case project dates

projects like waterfalls and in the summer now do not show file mtimes, except for on the project itself. this also fixes a bug regarding deleting folders.

7 files changed, 48 insertions(+), 10 deletions(-)

src/file-viewer/bin/scan3.ts+25-4
......@@ -123,6 +123,8 @@ export async function main() {
123123 dimensions: mediaFile?.dimensions ?? "",
124124 contents: mediaFile?.contents ?? "",
125125 });
126 const parent = mediaFile.getParent();
127 if (parent) parent.setProcessed(0);
126128
127129 node.text = `${label}`;
128130 await queueProcessors({
......@@ -263,7 +265,12 @@ export async function main() {
263265 }
264266 }
265267 }
266 if (node.estimate > 0) errorHandler.move();
268 if (node.estimate > 0) {
269 errorHandler.move();
270
271 const parent = mediaFile.getParent();
272 if (parent) parent.setProcessed(0);
273 }
267274 }
268275
269276 // Add the root & recursively iterate!
......@@ -322,6 +329,19 @@ export async function main() {
322329 }
323330 }
324331
332 // Project Date
333 const dateFile = children.find((x) => x.basename === ".date");
334 if (dateFile) {
335 const date = new Date(dateFile.contents);
336 newestDate = date;
337 dir.setProcessors(
338 0,
339 JSON.stringify({ hideChildrenDates: true }),
340 );
341 } else {
342 dir.setProcessors(0, "");
343 }
344
325345 const dirHash = crypto
326346 .createHash("sha1")
327347 .update(dir.path + allHashes)
......@@ -846,12 +866,13 @@ function skipBasename(basename: string): boolean {
846866 // dot files must be incrementally tracked
847867 if (basename === ".dirsort") return false;
848868 if (basename === ".friends") return false;
869 if (basename === ".date") return false;
849870
850871 return (
851872 basename.startsWith(".") ||
852 basename.startsWith("._") ||
853 basename.startsWith(".tmp") ||
854 basename === ".DS_Store" ||
873 // basename.startsWith("._") ||
874 // basename.startsWith(".tmp") ||
875 // basename === ".DS_Store" ||
855876 basename.toLowerCase() === "thumbs.db" ||
856877 basename.toLowerCase() === "desktop.ini"
857878 );
src/file-viewer/models/MediaFile.ts+1-1
......@@ -440,7 +440,7 @@ const deleteCascadeQuery = db.prepare<[{ id: number }]>(/* SQL */ `
440440 )
441441 )
442442 delete from media_files
443 where id in (select id from items)
443 where id in (select id from items order by parent_id nulls last)
444444`);
445445const getDirectoriesToReindexQuery = db.prepare(`
446446 with recursive directory_chain as (
src/file-viewer/rsync.ts+1-1
......@@ -25,7 +25,7 @@ export interface SpawnOptions {
2525 args: string[];
2626 rsync?: string;
2727 progress: progress.Node;
28 cwd: string;
28 cwd?: string;
2929}
3030
3131export async function spawn(options: SpawnOptions) {
src/file-viewer/rules.ts+1-1
......@@ -73,7 +73,7 @@ export const extsDuration = new Set([...extsAudio, ...extsVideo]);
7373export const extsDimensions = new Set([...extsImage, ...extsVideo, ".gif"]);
7474
7575/** These files read file contents into `contents`, as-is */
76export const extsReadContents = new Set([".txt", ".chat", ".dirsort"]);
76export const extsReadContents = new Set([".txt", ".chat", ".dirsort", ".date"]);
7777
7878export const extsArchive = new Set([
7979 ".zip",
src/file-viewer/transcode-rules.ts+2-1
......@@ -98,7 +98,8 @@ export const imagePresets = [
9898];
9999
100100export async function getVideoInputArgs(path: Path): Promise<InputArgs> {
101 const config = await path.replaceExt(".json").readIfExists<any>("json");
101 const config = await path.parent!.join("." + path.replaceExt(".json").base)
102 .readIfExists<any>("json");
102103 if (config) {
103104 if (config.encoder && typeof config.encoder.videoSrc === "string") {
104105 const { videoSrc, audioSrc, rate } = config.encoder;
src/file-viewer/views/clofi.css+3
......@@ -695,6 +695,9 @@ h3 {
695695 text-decoration: underline;
696696 }
697697}
698.nodate {
699 padding-left: 0.5rem;
700}
698701
699702/* MOBILE */
700703@media (max-width: 1000px) {
src/file-viewer/views/clofi.tsx+15-2
......@@ -330,6 +330,10 @@ const sortOverrides: Record<string, (a: MediaFile, b: MediaFile) => number> = {
330330 "/2017": sortChronologicalStartToEnd,
331331};
332332
333interface DirConfig {
334 hideChildrenDates?: boolean;
335}
336
333337function DirView({
334338 dir,
335339 activeFilename,
......@@ -363,12 +367,21 @@ function DirView({
363367 const sortedFiles = unsortedFiles.sort(sorter);
364368 const readme = sortedFiles.find((f) => f.basename === readmeFile);
365369 if (readme && isLast) activeFilename ||= readmeFile;
370
371 const extraConfig: DirConfig = dir.processors
372 ? JSON.parse(dir.processors)
373 : {};
374
366375 const main = (
367376 <div class="content primary">
368377 <ul>
369378 {sortedFiles.map((file) => {
370379 return (
371 <ListItem file={file} active={activeFilename === file.basename} />
380 <ListItem
381 file={file}
382 active={activeFilename === file.basename}
383 noDate={extraConfig.hideChildrenDates ?? false}
384 />
372385 );
373386 })}
374387 </ul>
......@@ -434,7 +447,7 @@ function ListItem({
434447 <li>
435448 <a
436449 class={(active ? "active " : "") + (isReadme ? "readme " : "") +
437 "li custom"}
450 "li custom" + (noDate ? " nodate" : "")}
438451 href={file.extension === ".lnk"
439452 ? file.contents
440453 : isReadme