infra: add linting and formatting for js projects (#230)

* wip

* wip

* wip

* format

* wip(mobile): lint and format

* cleanup

* nits

* nits

* idiomatic react

* nit

* format all root files
This commit was merged in pull request #230.
This commit is contained in:
Arjun Patel
2026-06-02 07:44:24 -07:00
committed by GitHub
parent 2fe562ce2b
commit a8a0b7db1b
258 changed files with 7822 additions and 5195 deletions
@@ -1,5 +1,5 @@
import { useEffect, useState } from "react";
import { Dialog as DialogPrimitive } from "radix-ui";
import { useCallback, useEffect } from 'react';
import { Dialog as DialogPrimitive } from 'radix-ui';
import {
ChevronLeft,
ChevronRight,
@@ -8,20 +8,19 @@ import {
Loader2,
Trash2,
X,
} from "lucide-react";
import { useDownloadUrl } from "@/hooks/use-download-url";
import { Button } from "@/components/ui/button";
import { useSuspendPlayback } from "@/hooks/use-suspend-playback";
import { platform } from "@/lib/platform";
} from 'lucide-react';
import { useDownloadUrl } from '@/hooks/use-download-url';
import { useObjectUrl } from '@/hooks/use-object-url';
import { Button } from '@/components/ui/button';
import { useSuspendPlayback } from '@/hooks/use-suspend-playback';
import { platform } from '@/lib/platform';
export interface AttachmentItem {
id: string;
filename: string;
mimeType: string;
sizeBytes?: number;
source:
| { kind: "remote"; objectId: string }
| { kind: "local"; file: File };
source: { kind: 'remote'; objectId: string } | { kind: 'local'; file: File };
}
interface AttachmentLightboxProps {
@@ -36,11 +35,13 @@ interface AttachmentLightboxProps {
* Return `"lightbox"` for mime types that preview in-app, `"external"` otherwise.
* Callers use this to decide whether to open the lightbox or hand off to the OS.
*/
export function getAttachmentHandler(mimeType: string): "lightbox" | "external" {
if (mimeType.startsWith("image/") || mimeType.startsWith("video/")) {
return "lightbox";
export function getAttachmentHandler(
mimeType: string,
): 'lightbox' | 'external' {
if (mimeType.startsWith('image/') || mimeType.startsWith('video/')) {
return 'lightbox';
}
return "external";
return 'external';
}
function formatSize(bytes?: number): string | null {
@@ -62,44 +63,39 @@ export function AttachmentLightbox({
: null;
const isOpen = current !== null;
const hasMultiple = items.length > 1;
const positionIndicator = openIndex !== null ? openIndex + 1 : null;
// Remote items resolve through the signed-URL cache; disabled when not remote.
const remoteObjectId =
current?.source.kind === "remote" ? current.source.objectId : undefined;
current?.source.kind === 'remote' ? current.source.objectId : undefined;
const { data: remoteUrl, isLoading: isRemoteLoading } =
useDownloadUrl(remoteObjectId);
// Local items get a fresh blob URL per item, revoked on change/close.
const [localUrl, setLocalUrl] = useState<string | null>(null);
useEffect(() => {
if (current?.source.kind !== "local") {
setLocalUrl(null);
return;
}
const url = URL.createObjectURL(current.source.file);
setLocalUrl(url);
return () => URL.revokeObjectURL(url);
}, [current?.id, current?.source.kind]);
// Local items resolve to a blob URL; remote items use the signed-URL cache.
const localFile =
current?.source.kind === 'local' ? current.source.file : null;
const localUrl = useObjectUrl(localFile);
const url =
current?.source.kind === "remote"
? remoteUrl ?? null
: localUrl;
current?.source.kind === 'remote' ? (remoteUrl ?? null) : localUrl;
const canDownload = current?.source.kind === "remote" && !!url;
const canDownload = current?.source.kind === 'remote' && !!url;
const goTo = (delta: number) => {
if (openIndex === null || items.length === 0) return;
const next = (openIndex + delta + items.length) % items.length;
onOpenChange(next);
};
const goTo = useCallback(
(delta: number) => {
if (openIndex === null || items.length === 0) return;
const next = (openIndex + delta + items.length) % items.length;
onOpenChange(next);
},
[openIndex, items.length, onOpenChange],
);
const handleDownload = () => {
if (!current || !url || current.source.kind !== "remote") return;
const handleDownload = useCallback(() => {
if (!current || !url || current.source.kind !== 'remote') return;
platform.attachment.download(url, current.filename);
};
}, [current, url]);
const handleRemove = () => {
const handleRemove = useCallback(() => {
if (!current || !onRemove) return;
const wasLast = items.length <= 1;
const wasAtEnd = openIndex === items.length - 1;
@@ -107,12 +103,12 @@ export function AttachmentLightbox({
if (wasLast) {
onOpenChange(null);
} else if (wasAtEnd) {
onOpenChange(openIndex! - 1);
onOpenChange(items.length - 2);
}
// Otherwise openIndex stays — the next item shifts into its place.
};
}, [current, onRemove, items.length, openIndex, onOpenChange]);
useSuspendPlayback(isOpen, "attachment-lightbox");
useSuspendPlayback(isOpen, 'attachment-lightbox');
// Keyboard handling — only listens while open. Registered in the capture
// phase with stopImmediatePropagation so we consume keys (arrows, D, ⌫)
@@ -123,8 +119,8 @@ export function AttachmentLightbox({
const target = e.target as HTMLElement | null;
if (
target &&
(target.tagName === "INPUT" ||
target.tagName === "TEXTAREA" ||
(target.tagName === 'INPUT' ||
target.tagName === 'TEXTAREA' ||
target.isContentEditable)
) {
return;
@@ -133,29 +129,38 @@ export function AttachmentLightbox({
e.preventDefault();
e.stopImmediatePropagation();
};
if (e.key === "Escape") {
if (e.key === 'Escape') {
consume();
onOpenChange(null);
} else if (e.key === "ArrowLeft" && hasMultiple) {
} else if (e.key === 'ArrowLeft' && hasMultiple) {
consume();
goTo(-1);
} else if (e.key === "ArrowRight" && hasMultiple) {
} else if (e.key === 'ArrowRight' && hasMultiple) {
consume();
goTo(1);
} else if ((e.key === "d" || e.key === "D") && canDownload) {
} else if ((e.key === 'd' || e.key === 'D') && canDownload) {
consume();
handleDownload();
} else if ((e.key === "Backspace" || e.key === "Delete") && onRemove) {
} else if ((e.key === 'Backspace' || e.key === 'Delete') && onRemove) {
consume();
handleRemove();
}
};
window.addEventListener("keydown", handle, true);
return () => window.removeEventListener("keydown", handle, true);
}, [isOpen, openIndex, items, url, onOpenChange, onRemove, hasMultiple, canDownload]);
window.addEventListener('keydown', handle, true);
return () => window.removeEventListener('keydown', handle, true);
}, [
isOpen,
onOpenChange,
onRemove,
hasMultiple,
canDownload,
goTo,
handleDownload,
handleRemove,
]);
const isImage = current?.mimeType.startsWith("image/");
const isVideo = current?.mimeType.startsWith("video/");
const isImage = current?.mimeType.startsWith('image/');
const isVideo = current?.mimeType.startsWith('video/');
const sizeLabel = formatSize(current?.sizeBytes);
return (
@@ -187,7 +192,7 @@ export function AttachmentLightbox({
)}
{hasMultiple && (
<span className="border-l border-white/10 pl-2 text-xs text-white/40">
{openIndex! + 1} / {items.length}
{positionIndicator} / {items.length}
</span>
)}
</div>
@@ -278,7 +283,9 @@ export function AttachmentLightbox({
{url && !isImage && !isVideo && (
<div className="flex flex-col items-center gap-3 rounded-2xl border border-white/10 bg-white/5 px-8 py-6 backdrop-blur-xl">
<FileIcon className="size-12 text-white/50" />
<span className="text-sm text-white/80">{current.filename}</span>
<span className="text-sm text-white/80">
{current.filename}
</span>
</div>
)}
</div>