fix(files): review round 1, the page — honest states, the keyboard, the tray's words
- A library past the list's cap is searched and sorted on the server; the count says "the newest". - Each folder and each search opens on its first page (DataTable pageScope, useCardPager scope). - A file dropped where the page takes none never reaches the browser (which would unload the app). - The viewer's arrows wait while a layer opened from it is on top, and scroll a wide text line; a text shows its first 5000 lines and says where the rest is. - Confirms name the file (no more "your downloads"); the asking menu rows end in "…". - The tray names a running step beside its bar, shows a pause mark for paused work, polls slowly while only paused work waits, and forgets a finished file that was deleted. - An unchanged rename sends nothing; a paste opens the download dialog only with nothing on top; the link box never replaces what was typed. - Honest states: folders that failed to load, a file no longer there, the storage figure; the rail says "nothing downloaded" only when there is nothing. - Focus after deleting the open folder and when the format form opens; the format name's label. - ui/Meter (one danger line for both quota bars) and ui/RenameField in the platform layer. - Copy fixes, stale comments and the speculative hub key; a contract test for the list's parameters; e2e: the Files page and the paste intake.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { Meter } from "./ui/Meter";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import clsx from "clsx";
|
||||
@@ -12,7 +13,7 @@ import { useLiveQuery } from "../lib/useLiveQuery";
|
||||
import FilterRail from "./FilterRail";
|
||||
import { folderIcon, folderLabel } from "./fileFolders";
|
||||
import { sameView, useFiles, useFilesActions, type FilesView } from "./filesContext";
|
||||
import { RenameField } from "./RenameField";
|
||||
import { RenameField } from "./ui/RenameField";
|
||||
import { useFolderActions } from "./useFolderActions";
|
||||
import { ContextMenu } from "./ui/ContextMenu";
|
||||
import { Pressable } from "./ui/Pressable";
|
||||
@@ -77,9 +78,13 @@ function StorageMeter() {
|
||||
intervalMs: (u) => (u?.running_jobs ? 2000 : 15000),
|
||||
});
|
||||
const u = usage.data;
|
||||
if (!u) return null;
|
||||
const pct =
|
||||
u.unlimited || !u.max_bytes ? 0 : Math.min(100, (u.footprint_bytes / u.max_bytes) * 100);
|
||||
// A failed read says so where the figures would be, rather than the meter quietly not being there.
|
||||
if (!u)
|
||||
return usage.isError ? (
|
||||
<p className="mt-3 px-2 text-xs text-muted" data-testid="storage-meter">
|
||||
{t("files.usage.failed")}
|
||||
</p>
|
||||
) : null;
|
||||
return (
|
||||
<div className="mt-3 flex flex-col gap-1 px-2 text-xs text-muted" data-testid="storage-meter">
|
||||
<span className="flex justify-between gap-2">
|
||||
@@ -90,12 +95,7 @@ function StorageMeter() {
|
||||
</span>
|
||||
</span>
|
||||
{!u.unlimited && (
|
||||
<span className="h-1 overflow-hidden rounded-full bg-fg/10">
|
||||
<span
|
||||
className={clsx("block h-full rounded-full", pct > 90 ? "bg-danger" : "bg-accent")}
|
||||
style={{ width: `${pct}%` }}
|
||||
/>
|
||||
</span>
|
||||
<Meter value={u.footprint_bytes} max={u.max_bytes} label={t("files.usage.title")} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
@@ -202,7 +202,8 @@ export default function FilesRail({
|
||||
<div className="flex flex-col gap-0.5">
|
||||
{failed}
|
||||
{sources.map(entry)}
|
||||
{foldersQ.data && sources.length === 0 && (
|
||||
{/* Only when there is nothing at all: files moved into own folders were still downloaded. */}
|
||||
{foldersQ.data && sources.length === 0 && total === 0 && (
|
||||
<span className="px-2 py-1 text-xs text-muted">{t("files.rail.noSources")}</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user