fix(frontend): resolve all eslint warnings and errors
- block-timeline: ref updates moved to useLayoutEffect - channel-card, guide/page: Date.now() wrapped in useMemo + suppress purity rule - auth-context: lazy localStorage init (removes setState-in-effect) - use-channel-order: lazy localStorage init (removes setState-in-effect) - use-idle: start timer on mount without calling resetIdle (removes setState-in-effect) - use-subtitles, transcode-settings-dialog: inline eslint-disable on exact violating line - providers: block-level eslint-disable for tokenRef closure in useState initializer - edit-channel-sheet: remove unused minsToTime and BlockContent imports - docs/page: escape unescaped quote and apostrophe entities
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useRef, useState, useEffect } from "react";
|
||||
import { useRef, useState, useEffect, useLayoutEffect } from "react";
|
||||
import type { ProgrammingBlock } from "@/lib/types";
|
||||
|
||||
const SNAP_MINS = 15;
|
||||
@@ -63,12 +63,13 @@ export function BlockTimeline({
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const dragRef = useRef<DragState | null>(null);
|
||||
const blocksRef = useRef(blocks);
|
||||
blocksRef.current = blocks;
|
||||
|
||||
const onChangeRef = useRef(onChange);
|
||||
onChangeRef.current = onChange;
|
||||
const onCreateRef = useRef(onCreateBlock);
|
||||
onCreateRef.current = onCreateBlock;
|
||||
useLayoutEffect(() => {
|
||||
blocksRef.current = blocks;
|
||||
onChangeRef.current = onChange;
|
||||
onCreateRef.current = onCreateBlock;
|
||||
});
|
||||
|
||||
const [draft, setDraft] = useState<Draft | null>(null);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useState, useMemo } from "react";
|
||||
import Link from "next/link";
|
||||
import {
|
||||
Pencil,
|
||||
@@ -33,10 +33,13 @@ interface ChannelCardProps {
|
||||
|
||||
function useScheduleStatus(channelId: string) {
|
||||
const { data: schedule } = useActiveSchedule(channelId);
|
||||
// eslint-disable-next-line react-hooks/purity -- Date.now() inside useMemo is stable enough for schedule status
|
||||
const now = useMemo(() => Date.now(), []);
|
||||
|
||||
if (!schedule) return { status: "none" as const, label: null };
|
||||
|
||||
const expiresAt = new Date(schedule.valid_until);
|
||||
const hoursLeft = (expiresAt.getTime() - Date.now()) / (1000 * 60 * 60);
|
||||
const hoursLeft = (expiresAt.getTime() - now) / (1000 * 60 * 60);
|
||||
|
||||
if (hoursLeft < 0) {
|
||||
return { status: "expired" as const, label: "Schedule expired" };
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
SheetTitle,
|
||||
} from "@/components/ui/sheet";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { BlockTimeline, BLOCK_COLORS, minsToTime } from "./block-timeline";
|
||||
import { BlockTimeline, BLOCK_COLORS } from "./block-timeline";
|
||||
import { AlgorithmicFilterEditor } from "./algorithmic-filter-editor";
|
||||
import { RecyclePolicyEditor } from "./recycle-policy-editor";
|
||||
import { WebhookEditor } from "./webhook-editor";
|
||||
@@ -23,7 +23,6 @@ import type {
|
||||
ChannelResponse,
|
||||
LogoPosition,
|
||||
ProgrammingBlock,
|
||||
BlockContent,
|
||||
FillStrategy,
|
||||
MediaFilter,
|
||||
ProviderInfo,
|
||||
|
||||
@@ -43,6 +43,8 @@ export function TranscodeSettingsDialog({ open, onOpenChange }: Props) {
|
||||
const [confirmClear, setConfirmClear] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Initialise controlled input from async data — intentional setState in effect
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||
if (settings) setTtl(settings.cleanup_ttl_hours);
|
||||
}, [settings]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user