feat: show recipe source link, keep screen awake while viewing a recipe

- sourceUrl was already saved on URL import but never displayed —
  render it as a link (hostname only) under the description.
- Extract cook-mode's wake lock into a reusable useWakeLock hook, add
  visibility-change re-acquisition (a wake lock releases when the tab
  goes background and won't come back on its own), and use it on the
  regular recipe view too, not just cook mode.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Arnaud
2026-07-04 10:32:23 +02:00
parent c3776238c7
commit ee7946316c
6 changed files with 70 additions and 6 deletions
@@ -7,6 +7,7 @@ import { cn } from "@/lib/utils";
import { useTranslations } from "next-intl";
import { useLocale } from "@/lib/i18n/provider";
import { hasQuantity } from "@/lib/fractions";
import { useWakeLock } from "@/lib/hooks/use-wake-lock";
type Step = { id: string; instruction: string; timerSeconds: number | null };
type Ingredient = { rawName: string; quantity: string | null; unit: string | null };
@@ -85,7 +86,6 @@ export function CookingMode({
// Parallel timers: keyed by step index
const [timers, setTimers] = useState<Map<number, TimerState>>(() => new Map());
const wakeLockRef = useRef<WakeLockSentinel | null>(null);
const recognitionRef = useRef<InstanceType<typeof window.SpeechRecognition> | null>(null);
const step = steps[current]!;
@@ -95,11 +95,7 @@ export function CookingMode({
const currentTimer = timers.get(current);
const otherRunningTimers = [...timers.entries()].filter(([idx, t]) => idx !== current && t.running);
// Wake Lock
useEffect(() => {
navigator.wakeLock?.request("screen").then((lock) => { wakeLockRef.current = lock; }).catch(() => {});
return () => { wakeLockRef.current?.release().catch(() => {}); };
}, []);
useWakeLock();
// Master tick: decrement all running timers once per second
useEffect(() => {