mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-05-28 09:38:25 +01:00
Two presentational components, both player-agnostic: ChapterTicks — absolute overlay that draws tick marks on the progress slider, one per chapter start (skipping the leading 0ms marker). - Reads markers from a memoized prop computed by the caller so the filter/sort runs at most once per chapters change, not per render. - Snaps tick position AND width to the device pixel grid via PixelRatio.roundToNearestPixel(). Without this, fractional dp values land at different sub-pixel fractions on non-integer density displays (420dpi -> 2.625x ratio) and Android anti-aliases each tick differently, making some look visibly thicker than others. - Tick colour defaults to rgba(0,0,0,0.55), contrasting against both the filled progress (#fff) and the unfilled track so ticks stay visible as playback advances. - pointerEvents="none" so the slider underneath still receives touches. - overflow: "visible" so taller ticks can bleed past the parent track. ChapterList — bottom-sheet modal listing chapters with their timestamps. - Highlights the currently active row (purple primary tint). - Falls back to a localized "Chapter N" label when a chapter has no name. - Imperatively scrolls to the active row each time the sheet becomes visible. <Modal> keeps its children mounted across visible toggles, so FlatList.initialScrollIndex (which only fires at first mount) would only work on the very first open. Uses a ref + useEffect on `visible` + scrollToIndex inside requestAnimationFrame, with an onScrollToIndexFailed fallback for indices outside the render window. - All static styles in StyleSheet.create() — only dynamic backgroundColor / text colour stays inline. The list re-renders on every playback tick so cutting the per-render style allocations is worth it. - Colors from constants/Colors.ts (primary, background, text, icon), no hardcoded hex.