Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"lucide-react": "^0.460.0",
"next": "16.2.6",
"react": "19.2.4",
"react-dom": "19.2.4"
"react-dom": "19.2.4",
"sonner": "^2.0.7"
},
"devDependencies": {
"@biomejs/biome": "^2.5.0",
Expand Down
3 changes: 2 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Button, ThemeProvider } from "@mind-studio/ui";
import { Button, ThemeProvider, Toaster } from "@mind-studio/ui";
import { mind } from "@mind-studio/ui/themes";
import type { Metadata } from "next";
import { Fraunces, Hanken_Grotesk, JetBrains_Mono } from "next/font/google";
Expand Down Expand Up @@ -56,6 +56,7 @@ export default function RootLayout({ children }: Readonly<{ children: React.Reac
<Colophon />
<FeedbackLauncher />
</StandaloneOnly>
<Toaster position="bottom-right" />
</ThemeProvider>
</body>
</html>
Expand Down
13 changes: 7 additions & 6 deletions src/components/DriveBrowser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { toast } from "sonner";
import { ConfirmDialog } from "@/components/ConfirmDialog";
import PassphraseDialog from "@/components/PassphraseDialog";
import { ImageThumbnail, isImageName } from "@/components/Thumbnail";
Expand Down Expand Up @@ -107,7 +108,7 @@
const containerUrl =
pathSegments.length === 0
? driveRoot
: driveRoot + pathSegments.map(normalizeSegment).join("/") + "/";

Check notice on line 111 in src/components/DriveBrowser.tsx

View workflow job for this annotation

GitHub Actions / build

lint/style/useTemplate

Template literals are preferred over string concatenation.
try {
const entries = await readdir(containerUrl);
setState({
Expand Down Expand Up @@ -171,7 +172,7 @@
}

const startProgress = files.map((f) => ({
name: encryptUploads ? f.name + ".enc" : f.name,

Check notice on line 175 in src/components/DriveBrowser.tsx

View workflow job for this annotation

GitHub Actions / build

lint/style/useTemplate

Template literals are preferred over string concatenation.
done: 0,
total: f.size,
}));
Expand All @@ -185,7 +186,7 @@
const passphrase = getSessionPassphrase();
if (!passphrase) throw new Error("Missing session passphrase");
const { ciphertext, sidecar } = await encryptFile(passphrase, f, f.name);
const encUrl = state.containerUrl + encodeURIComponent(f.name) + ".enc";

Check notice on line 189 in src/components/DriveBrowser.tsx

View workflow job for this annotation

GitHub Actions / build

lint/style/useTemplate

Template literals are preferred over string concatenation.
const metaUrl = sidecarUrlFor(encUrl);
await writeFileBlob(encUrl, ciphertext, "application/octet-stream");
const sidecarBlob = new Blob([JSON.stringify(sidecar)], {
Expand Down Expand Up @@ -393,7 +394,7 @@
const slice = pathSegments.slice(0, i + 1);
acc.push({
label: safeDecode(pathSegments[i]),
href: "/drive/" + slice.map(normalizeSegment).join("/"),

Check notice on line 397 in src/components/DriveBrowser.tsx

View workflow job for this annotation

GitHub Actions / build

lint/style/useTemplate

Template literals are preferred over string concatenation.
});
}
return acc;
Expand Down Expand Up @@ -457,12 +458,12 @@
if (!trimmed) return;
setBusy(true);
try {
await mkdir(containerUrl + encodeURIComponent(trimmed) + "/");

Check notice on line 461 in src/components/DriveBrowser.tsx

View workflow job for this annotation

GitHub Actions / build

lint/style/useTemplate

Template literals are preferred over string concatenation.
setFolderName("");
setCreatingFolder(false);
onChanged();
} catch (err) {
alert(`Failed to create folder: ${String(err)}`);
toast.error(`Failed to create folder: ${String(err)}`);
} finally {
setBusy(false);
}
Expand Down Expand Up @@ -522,14 +523,14 @@
<FolderPlus className="size-4" /> New folder
</Button>
)}
<label className="flex cursor-pointer items-center gap-1.5 text-xs text-muted-foreground">
<Checkbox
checked={encryptUploads}
onCheckedChange={(v) => onEncryptUploadsChange(v === true)}
data-testid="encrypt-toggle"
/>
<span>🔒 Encrypt uploads</span>
</label>

Check warning on line 533 in src/components/DriveBrowser.tsx

View workflow job for this annotation

GitHub Actions / build

lint/a11y/noLabelWithoutControl

A form label must be associated with an input.
<div className="ml-auto flex items-center gap-2">
<Input
type="search"
Expand Down Expand Up @@ -590,12 +591,12 @@
}
}
return (
<div
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
className={`mt-2 rounded-md transition-all ${over ? "dropzone-active" : ""}`}
>

Check warning on line 599 in src/components/DriveBrowser.tsx

View workflow job for this annotation

GitHub Actions / build

lint/a11y/noStaticElementInteractions

Unexpected event handler on static element.
{children}
</div>
);
Expand Down Expand Up @@ -711,7 +712,7 @@
}) {
const relPath = entry.url.slice(driveRoot.length);
const href =
entry.kind === "container" ? "/drive/" + relPath.replace(/\/$/, "") : "/drive/file/" + relPath;

Check notice on line 715 in src/components/DriveBrowser.tsx

View workflow job for this annotation

GitHub Actions / build

lint/style/useTemplate

Template literals are preferred over string concatenation.

Check notice on line 715 in src/components/DriveBrowser.tsx

View workflow job for this annotation

GitHub Actions / build

lint/style/useTemplate

Template literals are preferred over string concatenation.
const [busy, setBusy] = useState(false);
const [confirmOpen, setConfirmOpen] = useState(false);
async function doDelete() {
Expand All @@ -725,7 +726,7 @@
}
onChanged();
} catch (err) {
alert(`Delete failed: ${String(err)}`);
toast.error(`Delete failed: ${String(err)}`);
} finally {
setBusy(false);
}
Expand Down Expand Up @@ -804,7 +805,7 @@
}) {
const relPath = entry.url.slice(driveRoot.length);
const href =
entry.kind === "container" ? "/drive/" + relPath.replace(/\/$/, "") : "/drive/file/" + relPath;

Check notice on line 808 in src/components/DriveBrowser.tsx

View workflow job for this annotation

GitHub Actions / build

lint/style/useTemplate

Template literals are preferred over string concatenation.

Check notice on line 808 in src/components/DriveBrowser.tsx

View workflow job for this annotation

GitHub Actions / build

lint/style/useTemplate

Template literals are preferred over string concatenation.
const [busy, setBusy] = useState(false);
const [renaming, setRenaming] = useState(false);
const [newName, setNewName] = useState(entry.name);
Expand All @@ -822,7 +823,7 @@
}
onChanged();
} catch (err) {
alert(`Delete failed: ${String(err)}`);
toast.error(`Delete failed: ${String(err)}`);
} finally {
setBusy(false);
}
Expand All @@ -843,7 +844,7 @@
a.remove();
setTimeout(() => URL.revokeObjectURL(url), 1000);
} catch (err) {
alert(`Download failed: ${String(err)}`);
toast.error(`Download failed: ${String(err)}`);
} finally {
setBusy(false);
}
Expand All @@ -858,7 +859,7 @@
return;
}
if (entry.kind === "container") {
alert("Container rename is not supported in M2 — copy/recreate manually.");
toast.error("Container rename is not supported in M2 — copy/recreate manually.");
setRenaming(false);
return;
}
Expand All @@ -870,7 +871,7 @@
setRenaming(false);
onChanged();
} catch (err) {
alert(`Rename failed: ${String(err)}`);
toast.error(`Rename failed: ${String(err)}`);
} finally {
setBusy(false);
}
Expand Down
5 changes: 3 additions & 2 deletions src/components/FilePreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useCallback, useEffect, useMemo, useState } from "react";
import { toast } from "sonner";
import { ConfirmDialog } from "@/components/ConfirmDialog";
import PassphraseDialog from "@/components/PassphraseDialog";
import ShareDialog from "@/components/ShareDialog";
Expand Down Expand Up @@ -299,7 +300,7 @@
: "/drive/" + parentSegments.map(normalizeSegment).join("/");
router.replace(parentHref);
} catch (e) {
alert(`Delete failed: ${String(e)}`);
toast.error(`Delete failed: ${String(e)}`);
setBusy(false);
}
}
Expand All @@ -323,7 +324,7 @@
[...parentSegments.map(normalizeSegment), encodeURIComponent(trimmed)].join("/");
router.replace(href);
} catch (err) {
alert(`Rename failed: ${String(err)}`);
toast.error(`Rename failed: ${String(err)}`);
setBusy(false);
}
}
Expand Down Expand Up @@ -485,12 +486,12 @@
return (
<div className="mt-6 flex justify-center rounded-lg border bg-muted/40 p-6">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={objectUrl}
alt=""
className="max-h-[70vh] max-w-full rounded-sm"
data-testid="preview-image"
/>

Check warning on line 494 in src/components/FilePreview.tsx

View workflow job for this annotation

GitHub Actions / build

lint/performance/noImgElement

Don't use <img> element.
</div>
);
}
Expand Down
Loading