Skip to content

Commit 34907e4

Browse files
committed
fix: reduce Jobs rerenders and harden redirect
1 parent 8295408 commit 34907e4

File tree

2 files changed

+12
-10
lines changed

2 files changed

+12
-10
lines changed

src/main.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ if (redirectPath) {
2424

2525
const hasScheme = pathPart.includes('://');
2626
const isProtocolRelative = pathPart.startsWith('//');
27+
const isSafePath = /^\/[0-9A-Za-z_\-./]*$/.test(pathPart);
2728

28-
if (!isProtocolRelative && !hasScheme && !hasTraversal) {
29+
if (!isProtocolRelative && !hasScheme && !hasTraversal && isSafePath) {
2930
window.history.replaceState(null, '', `${base}${target}`);
3031
}
3132
}

src/pages/JobsPage.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,14 @@ export function JobsPage(): JSX.Element {
6262
// oEmbed hydration is performed in a batched effect (cancellable + de-duplicated).
6363
const oembedInFlight = useRef(new Set<string>());
6464

65-
const [refreshTick, setRefreshTick] = useState(0);
6665
const [input, setInput] = useState('');
6766
const [error, setError] = useState<string | null>(null);
6867

6968
const [videos, setVideos] = useState(() => listLocalLibraryVideos());
7069

7170
useEffect(() => {
72-
setVideos(listLocalLibraryVideos());
73-
}, [refreshTick]);
71+
let active = true;
7472

75-
useEffect(() => {
7673
// One controller per effect run. Cleanup aborts the whole batch on unmount/list changes.
7774
const controller = new AbortController();
7875
const missing = videos.filter(
@@ -98,10 +95,14 @@ export function JobsPage(): JSX.Element {
9895
}),
9996
),
10097
).then((results) => {
101-
if (results.some(Boolean)) setRefreshTick((v) => v + 1);
98+
if (!active) return;
99+
if (results.some(Boolean)) setVideos(listLocalLibraryVideos());
102100
});
103101

104-
return () => controller.abort();
102+
return () => {
103+
active = false;
104+
controller.abort();
105+
};
105106
}, [videos]);
106107

107108
function addByInput(): void {
@@ -115,20 +116,20 @@ export function JobsPage(): JSX.Element {
115116
const platform: Platform = 'youtube';
116117
const videoUrl = `https://www.youtube.com/watch?v=${videoId}`;
117118
upsertLocalLibraryVideo({ platform, videoId, videoUrl });
119+
setVideos(listLocalLibraryVideos());
118120

119121
const key = `${platform}:${videoId}`;
120122
if (!oembedInFlight.current.has(key)) {
121123
oembedInFlight.current.add(key);
122124
void hydrateLocalLibraryVideoMetadata(platform, videoId)
123125
.then((updated) => {
124-
if (updated) setRefreshTick((v) => v + 1);
126+
if (updated) setVideos(listLocalLibraryVideos());
125127
})
126128
.finally(() => {
127129
oembedInFlight.current.delete(key);
128130
});
129131
}
130132

131-
setRefreshTick((v) => v + 1);
132133
setInput('');
133134
setSearchParams({ video: `${platform}:${videoId}` });
134135
}
@@ -254,7 +255,7 @@ export function JobsPage(): JSX.Element {
254255
variant="ghost"
255256
onClick={() => {
256257
removeLocalLibraryVideo(video.platform, video.videoId);
257-
setRefreshTick((v) => v + 1);
258+
setVideos(listLocalLibraryVideos());
258259
if (isFocused) setSearchParams({});
259260
}}
260261
>

0 commit comments

Comments
 (0)