chore: format

This commit is contained in:
2026-05-26 22:49:00 +02:00
parent 95ca4dd892
commit a5fdd8b999
4 changed files with 149 additions and 101 deletions

View File

@@ -166,34 +166,56 @@ const initPlayer = (): void => {
onLoadedMetadata();
}
state.video.addEventListener('waiting', () => {
state.video.addEventListener(
'waiting',
() => {
if (loading) {
loading.style.display = 'flex';
}
}, { signal });
state.video.addEventListener('playing', () => {
},
{ signal }
);
state.video.addEventListener(
'playing',
() => {
if (loading) {
loading.style.display = 'none';
}
}, { signal });
},
{ signal }
);
// update progress bar during buffering
state.video.addEventListener('progress', () => {
state.video.addEventListener(
'progress',
() => {
updateTimeline(state.video.currentTime);
}, { signal });
},
{ signal }
);
// main loop: update progress, subtitles, skip buttons
state.video.addEventListener('timeupdate', () => {
state.video.addEventListener(
'timeupdate',
() => {
updateTimeline(state.video.currentTime);
updateSubtitleRender(displayTimeFromAbsolute(state.video.currentTime));
updateSkipButton(state.video.currentTime);
}, { signal });
},
{ signal }
);
state.video.addEventListener('ended', () => {
state.video.addEventListener(
'ended',
() => {
goToNextEpisode();
}, { signal });
},
{ signal }
);
// click/drag to seek (pointer events are more consistent across fullscreen/mobile)
progressWrap?.addEventListener('pointerdown', e => {
progressWrap?.addEventListener(
'pointerdown',
e => {
// ignore right/middle click
if ('button' in e && e.button !== 0) return;
state.isScrubbing = true;
@@ -207,23 +229,35 @@ const initPlayer = (): void => {
updateTimeline(state.video.currentTime);
updateSkipButton(state.video.currentTime);
showControls();
}, { signal });
},
{ signal }
);
// hover to preview time
progressWrap?.addEventListener('pointermove', e => {
progressWrap?.addEventListener(
'pointermove',
e => {
const rect = progressWrap.getBoundingClientRect();
updatePreviewUI(Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width)));
}, { signal });
},
{ signal }
);
progressWrap?.addEventListener('pointerleave', hidePreviewPopover, { signal });
progressWrap?.addEventListener('pointerup', () => {
progressWrap?.addEventListener(
'pointerup',
() => {
// ensure we finish the seek even if no window mousemove fired
if (!progressWrap) return;
state.isScrubbing = false;
}, { signal });
},
{ signal }
);
// dragging outside progress bar while scrubbing
window.addEventListener('pointermove', e => {
window.addEventListener(
'pointermove',
e => {
if (!state.isScrubbing || !progressWrap) return;
const rect = progressWrap.getBoundingClientRect();
state.video.currentTime = absoluteTimeFromRatio(
@@ -231,10 +265,14 @@ const initPlayer = (): void => {
);
updateTimeline(state.video.currentTime);
updateSkipButton(state.video.currentTime);
}, { signal });
},
{ signal }
);
// track next-episode links outside the player so they start fresh after finishing an episode
document.addEventListener('click', e => {
document.addEventListener(
'click',
e => {
const target = e.target;
if (!(target instanceof Element)) return;
const anchor = target.closest('a[href]');
@@ -247,7 +285,9 @@ const initPlayer = (): void => {
const nextEpisode = Number.parseInt(url.searchParams.get('ep') ?? '1', 10);
const currentEpisode = Number.parseInt(state.currentEpisode, 10);
if (nextEpisode === currentEpisode + 1) markEpisodeTransition(nextEpisode);
}, { signal });
},
{ signal }
);
state.video.addEventListener('click', showControls, { signal });
@@ -256,7 +296,9 @@ const initPlayer = (): void => {
let searchDebounce: number | undefined;
if (searchInput) {
searchInput.addEventListener('input', () => {
searchInput.addEventListener(
'input',
() => {
clearTimeout(searchDebounce);
// debounce to avoid excessive range switches while typing
searchDebounce = window.setTimeout(() => {
@@ -278,18 +320,24 @@ const initPlayer = (): void => {
updateEpisodeHighlight(clamped);
}
}, 300);
}, { signal });
},
{ signal }
);
}
// range buttons (100s of episodes)
if (dropdown) {
dropdown.querySelectorAll('.episode-range-btn').forEach(btn => {
btn.addEventListener('click', () => {
btn.addEventListener(
'click',
() => {
const idx = Number.parseInt((btn as HTMLElement).dataset.rangeIndex ?? '0', 10);
switchEpisodeRange(idx);
const dd = btn.closest('ui-dropdown');
if (isClosableDropdown(dd)) dd.close();
}, { signal });
},
{ signal }
);
});
}

View File

@@ -172,8 +172,7 @@ export const initState = (c: HTMLElement): boolean => {
const isSubtitleItemArray = (v: unknown): v is { lang: string; token: string }[] =>
Array.isArray(v) &&
v.every(
item =>
isRecord(item) && typeof item.lang === 'string' && typeof item.token === 'string'
item => isRecord(item) && typeof item.lang === 'string' && typeof item.token === 'string'
);
const parseModeSources = (v: unknown): Record<string, ModeSource> => {

View File

@@ -37,4 +37,3 @@ export const safeLocalStorage = {
}
},
};

View File

@@ -190,7 +190,9 @@ const sortVisibleWatchlistItems = (sortBy: WatchlistSort, desc: boolean): void =
grids.push(singleGrid);
}
document.querySelectorAll<HTMLElement>('.watchlist-section .grid').forEach(grid => grids.push(grid));
document
.querySelectorAll<HTMLElement>('.watchlist-section .grid')
.forEach(grid => grids.push(grid));
const sortItemsInGrid = (grid: HTMLElement): void => {
const items = Array.from(grid.querySelectorAll<HTMLElement>('.watchlist-item'));