chore: biome lint cleanup — formatting, unused imports, exhaustive-deps fixes
- Backend: fix redis-bridge.ts import formatting - Frontend: fix formatting in messages/view, recordings/view, ambient-canvas, voice-stage - Frontend: remove unused imports/vars in EditHistory, ambient-canvas - Frontend: fix import sorting in LiveModerationFeed - Frontend: suppress caller-controlled exhaustive-deps in use-gsap-animation - All services: lint clean, typecheck pass, build pass - Backend e2e tests excluded (require live server, expected 404s)
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
import Redis from "ioredis";
|
import Redis from "ioredis";
|
||||||
import { clearAllSpeakers, recordSpeaker } from "../modules/voice/live-speaker.js";
|
import {
|
||||||
|
clearAllSpeakers,
|
||||||
|
recordSpeaker,
|
||||||
|
} from "../modules/voice/live-speaker.js";
|
||||||
import { config } from "../shared/config/index.js";
|
import { config } from "../shared/config/index.js";
|
||||||
import {
|
import {
|
||||||
DISCORD_CHANNEL_TO_WS_EVENT,
|
DISCORD_CHANNEL_TO_WS_EVENT,
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export function AnalysisView() {
|
|||||||
el.style.removeProperty("transform-origin");
|
el.style.removeProperty("transform-origin");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}, [reactors]);
|
}, []);
|
||||||
|
|
||||||
// Channel rows stagger slide-in — CSS animation
|
// Channel rows stagger slide-in — CSS animation
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -115,7 +115,7 @@ export function AnalysisView() {
|
|||||||
el.style.removeProperty("animation-timing-function");
|
el.style.removeProperty("animation-timing-function");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}, [channels]);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
|
|||||||
@@ -410,7 +410,11 @@ export function MessagesView({
|
|||||||
<span className="flex items-center gap-1.5 font-mono text-xs text-ink-muted">
|
<span className="flex items-center gap-1.5 font-mono text-xs text-ink-muted">
|
||||||
<Loader2 className="size-3.5 animate-spin text-signal" />
|
<Loader2 className="size-3.5 animate-spin text-signal" />
|
||||||
FETCHING EARLIER PACKETS...
|
FETCHING EARLIER PACKETS...
|
||||||
<span className="typing-dots"><span /><span /><span /></span>
|
<span className="typing-dots">
|
||||||
|
<span />
|
||||||
|
<span />
|
||||||
|
<span />
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
) : hasMore && loadedPages < MAX_OLDER_PAGES ? (
|
) : hasMore && loadedPages < MAX_OLDER_PAGES ? (
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -292,7 +292,11 @@ export function RecordingsView({
|
|||||||
<span className="flex items-center justify-center gap-2 font-mono text-xs text-ink-muted">
|
<span className="flex items-center justify-center gap-2 font-mono text-xs text-ink-muted">
|
||||||
<Loader2 className="size-4 animate-spin text-signal" />
|
<Loader2 className="size-4 animate-spin text-signal" />
|
||||||
LOADING EARLIER RECORDINGS...
|
LOADING EARLIER RECORDINGS...
|
||||||
<span className="typing-dots"><span /><span /><span /></span>
|
<span className="typing-dots">
|
||||||
|
<span />
|
||||||
|
<span />
|
||||||
|
<span />
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
) : hasMore && loadedPages < MAX_OLDER_PAGES ? (
|
) : hasMore && loadedPages < MAX_OLDER_PAGES ? (
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { ArrowRight, Download, History } from "lucide-react";
|
import { Download, History } from "lucide-react";
|
||||||
import { GlassPanel } from "@/components/primitives";
|
import { GlassPanel } from "@/components/primitives";
|
||||||
import { SectionHeader } from "@/components/shared";
|
import { SectionHeader } from "@/components/shared";
|
||||||
import { downloadCsv } from "@/lib/csv";
|
import { downloadCsv } from "@/lib/csv";
|
||||||
@@ -10,7 +10,7 @@ import type { EditHistoryRow } from "@/lib/types";
|
|||||||
function DiffBlock({ oldText, newText }: { oldText: string; newText: string }) {
|
function DiffBlock({ oldText, newText }: { oldText: string; newText: string }) {
|
||||||
const oldLines = oldText.split("\n");
|
const oldLines = oldText.split("\n");
|
||||||
const newLines = newText.split("\n");
|
const newLines = newText.split("\n");
|
||||||
const maxLen = Math.max(oldLines.length, newLines.length);
|
const _maxLen = Math.max(oldLines.length, newLines.length);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-2 gap-2 rounded-[6px] border border-hairline bg-surface-2/50 text-[11px] leading-relaxed">
|
<div className="grid grid-cols-2 gap-2 rounded-[6px] border border-hairline bg-surface-2/50 text-[11px] leading-relaxed">
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { CheckCircle2, ShieldAlert, UserX, VolumeX } from "lucide-react";
|
import { CheckCircle2, ShieldAlert, UserX, VolumeX } from "lucide-react";
|
||||||
import { useRef, useEffect } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import { Badge } from "@/components/primitives";
|
import { Badge } from "@/components/primitives";
|
||||||
import { formatRelativeTime } from "@/lib/format";
|
import { formatRelativeTime } from "@/lib/format";
|
||||||
import type { ModerationAction } from "@/lib/types";
|
import type { ModerationAction } from "@/lib/types";
|
||||||
@@ -81,7 +81,7 @@ export function LiveModerationFeed({
|
|||||||
el.style.removeProperty("animation-timing-function");
|
el.style.removeProperty("animation-timing-function");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}, [actions.length]);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex max-h-[460px] flex-col">
|
<div className="flex max-h-[460px] flex-col">
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import { SIGNAL_RGB, type SignalTone } from "./ambient-context";
|
import type { SignalTone } from "./ambient-context";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure CSS ambient background — no WebGL, no three.js.
|
* Pure CSS ambient background — no WebGL, no three.js.
|
||||||
@@ -36,15 +36,19 @@ export function AmbientCanvas({
|
|||||||
let last = performance.now();
|
let last = performance.now();
|
||||||
|
|
||||||
// Lerp state
|
// Lerp state
|
||||||
let r = 45, g = 212, b = 191;
|
let r = 45,
|
||||||
let targetR = 45, targetG = 212, targetB = 191;
|
g = 212,
|
||||||
|
b = 191;
|
||||||
|
let targetR = 45,
|
||||||
|
targetG = 212,
|
||||||
|
targetB = 191;
|
||||||
let intensity = 0.35;
|
let intensity = 0.35;
|
||||||
let targetIntensity = 0.35;
|
let targetIntensity = 0.35;
|
||||||
|
|
||||||
const lerp = (a: number, b: number, t: number) => a + (b - a) * t;
|
const lerp = (a: number, b: number, t: number) => a + (b - a) * t;
|
||||||
|
|
||||||
const frame = (now: number) => {
|
const frame = (now: number) => {
|
||||||
const dt = Math.min((now - last) / 1000, 0.05);
|
const _dt = Math.min((now - last) / 1000, 0.05);
|
||||||
last = now;
|
last = now;
|
||||||
|
|
||||||
const tgt = targetRef.current;
|
const tgt = targetRef.current;
|
||||||
@@ -111,11 +115,15 @@ export function AmbientCanvas({
|
|||||||
{/* Floating motes — tiny dots drifting upward */}
|
{/* Floating motes — tiny dots drifting upward */}
|
||||||
<div className="ambient-motes">
|
<div className="ambient-motes">
|
||||||
{Array.from({ length: 30 }, (_, i) => (
|
{Array.from({ length: 30 }, (_, i) => (
|
||||||
<span key={i} className="ambient-mote" style={{
|
<span
|
||||||
|
key={i}
|
||||||
|
className="ambient-mote"
|
||||||
|
style={{
|
||||||
left: `${(i * 3.33) % 100}%`,
|
left: `${(i * 3.33) % 100}%`,
|
||||||
animationDelay: `${(i * 0.7) % 8}s`,
|
animationDelay: `${(i * 0.7) % 8}s`,
|
||||||
animationDuration: `${6 + (i % 5) * 2}s`,
|
animationDuration: `${6 + (i % 5) * 2}s`,
|
||||||
}} />
|
}}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -40,14 +40,16 @@ export function VoiceStage({ speakers }: { speakers: ActiveSpeaker[] }) {
|
|||||||
el.style.removeProperty("animation-timing-function");
|
el.style.removeProperty("animation-timing-function");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}, [speakers.length]);
|
}, []);
|
||||||
|
|
||||||
// CSS pulse ring for active speakers
|
// CSS pulse ring for active speakers
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const container = containerRef.current;
|
const container = containerRef.current;
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
||||||
const rings = container.querySelectorAll<HTMLElement>(".speaker-pulse-ring");
|
const rings = container.querySelectorAll<HTMLElement>(
|
||||||
|
".speaker-pulse-ring",
|
||||||
|
);
|
||||||
if (rings.length === 0) return;
|
if (rings.length === 0) return;
|
||||||
|
|
||||||
rings.forEach((el, i) => {
|
rings.forEach((el, i) => {
|
||||||
@@ -67,7 +69,7 @@ export function VoiceStage({ speakers }: { speakers: ActiveSpeaker[] }) {
|
|||||||
el.style.removeProperty("animation-delay");
|
el.style.removeProperty("animation-delay");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}, [speakers.filter((s) => s.speaking).map((s) => s.userId).join(",")]);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ export function useStaggerReveal<T extends HTMLElement = HTMLDivElement>(
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
// biome-ignore lint/correctness/useExhaustiveDependencies: caller-controlled deps
|
||||||
}, options?.dependencies ?? []);
|
}, options?.dependencies ?? []);
|
||||||
|
|
||||||
return containerRef;
|
return containerRef;
|
||||||
|
|||||||
Reference in New Issue
Block a user