simple-fs-server/islands/DirList.tsx

125 lines
3.3 KiB
TypeScript
Raw Permalink Normal View History

2023-01-06 18:24:27 +09:00
import { asset, Head } from "$fresh/runtime.ts";
2023-01-05 18:18:07 +09:00
import { useState } from "preact/hooks";
import { extname, join } from "path/posix.ts";
import { ComponentChild } from "preact";
import UpList from "./UpList.tsx";
2023-01-06 18:24:27 +09:00
import { extToIcon } from "../src/media.ts";
2023-02-07 23:31:01 +09:00
import natsort from "../src/natsort.ts";
2023-01-06 18:17:36 +09:00
import { encodePath } from "../util/util.ts";
2023-01-05 18:18:07 +09:00
2023-01-06 18:24:27 +09:00
function ListItem(props: {
href: string;
icon: string;
children: ComponentChild;
}) {
return (
<li class="p-1 hover:bg-gray-400 transition-colors">
<a class="flex gap-2" href={props.href}>
2023-02-08 01:33:54 +09:00
<div class="bg-black dark:bg-white w-4 h-4" style={`mask: url(${asset(props.icon)})`}></div>
2023-01-06 18:24:27 +09:00
<p class="">{props.children}</p>
</a>
</li>
);
2023-01-05 18:18:07 +09:00
}
2023-01-06 18:24:27 +09:00
export interface EntryInfo {
name: string;
isFile: boolean;
isDirectory: boolean;
isSymlink: boolean;
size: number;
lastModified?: Date;
2023-01-05 18:18:07 +09:00
}
interface DirListProps {
2023-01-06 18:24:27 +09:00
path: string;
files: EntryInfo[];
2023-01-05 18:18:07 +09:00
}
2023-02-07 23:31:01 +09:00
const natsortCompare = natsort();
2023-01-05 18:18:07 +09:00
2023-02-14 21:42:56 +09:00
function toSorted<T>(arr: T[], compareFn: (a:T,b:T) => number): T[]{
const ret = Array.from(arr);
ret.sort(compareFn);
return ret;
}
2023-01-05 18:18:07 +09:00
export function DirList(props: DirListProps) {
2023-01-06 18:24:27 +09:00
const data = props;
2023-02-07 23:31:01 +09:00
const [files, setFiles] = useState(
2023-02-14 21:42:56 +09:00
toSorted(data.files,(
2023-02-07 23:31:01 +09:00
(a,b)=> natsortCompare(a.name,b.name)
2023-02-14 21:42:56 +09:00
))
2023-02-07 23:31:01 +09:00
);
2023-01-05 18:18:07 +09:00
2023-01-06 18:24:27 +09:00
return (
<div>
<UpList path={data.path}></UpList>
<ul class="border-2 rounded-md">
<li class="p-1 flex gap-2">
<button class="flex" onClick={sortDir}>
<img src={asset("/icon/sort-down.svg")} /> Sort Directory
</button>
<button class="flex" onClick={sortAlpha}>
<img src={asset("/icon/sort-alpha-down.svg")} /> Sort Alphabet
</button>
</li>
<ListItem
key=".."
2023-01-14 03:03:22 +09:00
href={`/dir/${encodePath(join(data.path, ".."))}/?pretty`}
2023-01-06 18:24:27 +09:00
icon="/icon/back.svg"
>
...
</ListItem>
{files.map((file) => (
<ListItem
key={file.name}
2023-01-14 03:03:58 +09:00
href={`/dir/${
encodePath(join(data.path, file.name))
}${(file.isDirectory ? "/" : "")}?pretty`}
2023-01-06 18:24:27 +09:00
icon={file.isDirectory
? "/icon/folder.svg"
: extToIcon(extname(file.name))}
>
{file.name}
</ListItem>
))}
</ul>
</div>
);
function sortDir() {
// sort by directory first then by index
const sorted_files = files.map((x, i) => ([x, i] as [EntryInfo, number]))
.sort(
([a, ai], [b, bi]) => {
if (a.isDirectory && !b.isDirectory) {
return -1;
} else if (!a.isDirectory && b.isDirectory) {
return 1;
} else {
return ai - bi;
}
},
);
setFiles(sorted_files.map(([x, _]) => x));
}
function sortAlpha() {
// sort by alphabet first then by index
const sorted_files = files.map((x, i) => ([x, i] as [EntryInfo, number]))
.sort(
([a, ai], [b, bi]) => {
2023-02-07 23:31:01 +09:00
const ret = natsortCompare(a.name, b.name);
2023-01-06 18:24:27 +09:00
if (ret === 0) {
return ai - bi;
} else {
return ret;
}
},
);
setFiles(sorted_files.map(([x, _]) => x));
}
2023-01-05 18:18:07 +09:00
}
2023-02-07 23:31:01 +09:00
export default function DirListIsland(props: DirListProps){
return <DirList {...props}/>
}