Files is the one library: every done file, the ones shared with me, or one folder's, picked in a side rail (sources, own folders, the storage meter) and mirrored to ?folder=. One table with every kind of value in its own column; Copy link, Share and Save in sight, every action on a right click: play, cut, rename in the row, move to an own folder or back home, keep, details, re-download, delete. The Downloads page keeps only the queue until the tray replaces it. The old /api/downloads library routes are gone: list shared, upload, the details PATCH, delete, the file and the usage now live under /api/files, and a listed file says which source it came from. The job's "expired" flag is gone with the state it described.
48 lines
1.7 KiB
TypeScript
48 lines
1.7 KiB
TypeScript
import { createContext, useContext } from "react";
|
|
|
|
// The Files module's contexts + hooks, split out of FilesProvider so that file exports only
|
|
// components (Fast Refresh).
|
|
|
|
/** What the Files page lists: every file of mine, the ones shared with me, or one folder's. */
|
|
export type FilesView = { kind: "all" } | { kind: "shared" } | { kind: "folder"; id: number };
|
|
|
|
export const ALL_FILES: FilesView = { kind: "all" };
|
|
|
|
/** The view as one string — the `?folder=` bookmark and the remembered view share it. */
|
|
export function viewParam(view: FilesView): string {
|
|
return view.kind === "folder" ? String(view.id) : view.kind;
|
|
}
|
|
|
|
/** The view a stored or bookmarked string names; anything else is the whole library. */
|
|
export function parseView(raw: string | null | undefined): FilesView | null {
|
|
if (raw === "all") return ALL_FILES;
|
|
if (raw === "shared") return { kind: "shared" };
|
|
const id = raw && /^[1-9]\d*$/.test(raw) ? Number(raw) : null;
|
|
return id !== null && Number.isSafeInteger(id) ? { kind: "folder", id } : null;
|
|
}
|
|
|
|
export const sameView = (a: FilesView, b: FilesView): boolean => viewParam(a) === viewParam(b);
|
|
|
|
export type FilesState = {
|
|
search: string;
|
|
view: FilesView;
|
|
};
|
|
|
|
export interface FilesActions {
|
|
setSearch: (q: string) => void;
|
|
setView: (view: FilesView) => void;
|
|
}
|
|
|
|
export const FilesStateContext = createContext<FilesState>({ search: "", view: ALL_FILES });
|
|
export const FilesActionsContext = createContext<FilesActions>({
|
|
setSearch: () => {},
|
|
setView: () => {},
|
|
});
|
|
|
|
export function useFiles(): FilesState {
|
|
return useContext(FilesStateContext);
|
|
}
|
|
export function useFilesActions(): FilesActions {
|
|
return useContext(FilesActionsContext);
|
|
}
|