93 lines
2.9 KiB
TypeScript
93 lines
2.9 KiB
TypeScript
import { Head, asset } from "$fresh/runtime.ts";
|
|
import { useState } from "preact/hooks";
|
|
import { extname, join } from "path/posix.ts";
|
|
import { ComponentChild } from "preact";
|
|
import UpList from "./UpList.tsx";
|
|
import {extToIcon} from "../src/media.ts";
|
|
|
|
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}>
|
|
<img src={asset(props.icon)}/><p class="">{props.children}</p></a>
|
|
</li>
|
|
);
|
|
}
|
|
|
|
export interface EntryInfo{
|
|
name: string;
|
|
isFile: boolean;
|
|
isDirectory: boolean;
|
|
isSymlink: boolean;
|
|
size: number;
|
|
lastModified?: Date;
|
|
}
|
|
|
|
interface DirListProps {
|
|
path: string;
|
|
files: EntryInfo[];
|
|
}
|
|
|
|
export function DirList(props: DirListProps) {
|
|
const data = props;
|
|
const [files, setFiles] = useState(data.files);
|
|
|
|
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=".." href={`/dir/${join(data.path,"..")}`}
|
|
icon="/icon/back.svg"
|
|
>...</ListItem>
|
|
{files.map((file) => (
|
|
<ListItem key={file.name} href={`/dir/${join(data.path,file.name)}`}
|
|
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]) => {
|
|
const ret = a.name.localeCompare(b.name);
|
|
if (ret === 0) {
|
|
return ai - bi;
|
|
} else {
|
|
return ret;
|
|
}
|
|
});
|
|
setFiles(sorted_files.map(([x,_])=>x));
|
|
}
|
|
}
|
|
|
|
export default DirList; |