|
1 | 1 | "use client" |
2 | 2 |
|
3 | 3 | import { PanelHeader } from "@/components/panel/header" |
4 | | -import { useEffect, useRef, useState } from "react" |
| 4 | +import { useEffect, useMemo, useRef, useState } from "react" |
5 | 5 | import { apiFetch } from "@/lib/api-client" |
6 | 6 | import { API_ENDPOINTS } from "@/lib/panel-config" |
7 | 7 | import { useAuth } from "@/hooks/useAuth" |
@@ -1078,12 +1078,21 @@ export default function SettingsPage() { |
1078 | 1078 | const [videoDevices, setVideoDevices] = useState<MediaDeviceInfo[]>([]) |
1079 | 1079 | const [selectedCameraId, setSelectedCameraId] = useState<string | null>(null) |
1080 | 1080 | const [capturedSelfie, setCapturedSelfie] = useState<Blob | null>(null) |
1081 | | - const [capturedSelfieUrl, setCapturedSelfieUrl] = useState<string | null>(null) |
1082 | | - const safeCapturedSelfieUrl = |
1083 | | - capturedSelfieUrl && capturedSelfieUrl.startsWith("blob:") ? capturedSelfieUrl : "" |
| 1081 | + const previewSelfieUrl = useMemo(() => { |
| 1082 | + if (!capturedSelfie) return "" |
| 1083 | + return URL.createObjectURL(capturedSelfie) |
| 1084 | + }, [capturedSelfie]) |
1084 | 1085 | const [cameraError, setCameraError] = useState<string | null>(null) |
1085 | 1086 | const [selfieMessage, setSelfieMessage] = useState<string | null>(null) |
1086 | 1087 | const [selfieLoading, setSelfieLoading] = useState(false) |
| 1088 | + useEffect(() => { |
| 1089 | + return () => { |
| 1090 | + if (previewSelfieUrl) { |
| 1091 | + URL.revokeObjectURL(previewSelfieUrl) |
| 1092 | + } |
| 1093 | + } |
| 1094 | + }, [previewSelfieUrl]) |
| 1095 | + |
1087 | 1096 | const videoRef = useRef<HTMLVideoElement | null>(null) |
1088 | 1097 | const canvasRef = useRef<HTMLCanvasElement | null>(null) |
1089 | 1098 |
|
@@ -1964,15 +1973,10 @@ export default function SettingsPage() { |
1964 | 1973 | onChange={(e) => { |
1965 | 1974 | const file = e.target.files?.[0] |
1966 | 1975 | if (!file) return |
1967 | | - if (capturedSelfieUrl) { |
1968 | | - URL.revokeObjectURL(capturedSelfieUrl) |
1969 | | - } |
1970 | 1976 | if (cameraStream) { |
1971 | 1977 | stopCamera() |
1972 | 1978 | } |
1973 | | - const url = URL.createObjectURL(file) |
1974 | 1979 | setCapturedSelfie(file) |
1975 | | - setCapturedSelfieUrl(url) |
1976 | 1980 | setCameraError(null) |
1977 | 1981 | setCameraActive(false) |
1978 | 1982 | }} |
@@ -2016,7 +2020,7 @@ export default function SettingsPage() { |
2016 | 2020 | {capturedSelfie && ( |
2017 | 2021 | <div className="space-y-3"> |
2018 | 2022 | <img |
2019 | | - src={safeCapturedSelfieUrl} |
| 2023 | + src={previewSelfieUrl} |
2020 | 2024 | alt="Captured selfie preview" |
2021 | 2025 | className="h-64 w-full rounded-lg object-cover" |
2022 | 2026 | /> |
|
0 commit comments