pstream is dead; long live pstream taciturnaxolotl.github.io/pstream-ng/
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix playbacksettingsview settigns not working correctly

didnt save to backend or apply thumbails. Also hid them when performance mode is enabled

Pas 55b68c52 71a3d91b

+91 -28
+8 -2
src/components/buttons/Toggle.tsx
··· 1 1 import classNames from "classnames"; 2 2 3 - export function Toggle(props: { onClick?: () => void; enabled?: boolean }) { 3 + export function Toggle(props: { 4 + onClick?: () => void; 5 + enabled?: boolean; 6 + disabled?: boolean; 7 + }) { 4 8 return ( 5 9 <button 6 10 type="button" 7 - onClick={props.onClick} 11 + onClick={props.disabled ? undefined : props.onClick} 12 + disabled={props.disabled} 8 13 className={classNames( 9 14 "w-11 h-6 p-1 rounded-full grid transition-colors duration-100 group/toggle tabbable", 10 15 props.enabled ? "bg-buttons-toggle" : "bg-buttons-toggleDisabled", 16 + props.disabled ? "opacity-50 cursor-not-allowed" : null, 11 17 )} 12 18 > 13 19 <div className="relative w-full h-full">
+63 -11
src/components/player/atoms/settings/PlaybackSettingsView.tsx
··· 2 2 import { useCallback, useEffect, useMemo, useState } from "react"; 3 3 import { useTranslation } from "react-i18next"; 4 4 5 + import { updateSettings } from "@/backend/accounts/settings"; 5 6 import { Toggle } from "@/components/buttons/Toggle"; 6 7 import { Icon, Icons } from "@/components/Icon"; 7 8 import { Menu } from "@/components/player/internals/ContextMenu"; 9 + import { useBackendUrl } from "@/hooks/auth/useBackendUrl"; 8 10 import { useOverlayRouter } from "@/hooks/useOverlayRouter"; 11 + import { useAuthStore } from "@/stores/auth"; 9 12 import { usePlayerStore } from "@/stores/player/store"; 10 13 import { usePreferencesStore } from "@/stores/preferences"; 11 14 import { useWatchPartyStore } from "@/stores/watchParty"; ··· 188 191 ); 189 192 const isInWatchParty = useWatchPartyStore((s) => s.enabled); 190 193 194 + const account = useAuthStore((s) => s.account); 195 + const backendUrl = useBackendUrl(); 191 196 const allowAutoplay = useMemo(() => isAutoplayAllowed(), []); 192 197 const canShowAutoplay = 193 198 !isInWatchParty && allowAutoplay && !enableLowPerformanceMode; 194 199 200 + // Save settings to backend 201 + const saveThumbnailSetting = useCallback( 202 + async (value: boolean) => { 203 + if (!account || !backendUrl) return; 204 + 205 + try { 206 + await updateSettings(backendUrl, account, { 207 + enableThumbnails: value, 208 + }); 209 + } catch (error) { 210 + console.error("Failed to save thumbnail setting:", error); 211 + } 212 + }, 213 + [account, backendUrl], 214 + ); 215 + 216 + const saveAutoplaySetting = useCallback( 217 + async (value: boolean) => { 218 + if (!account || !backendUrl) return; 219 + 220 + try { 221 + await updateSettings(backendUrl, account, { 222 + enableAutoplay: value, 223 + }); 224 + } catch (error) { 225 + console.error("Failed to save autoplay setting:", error); 226 + } 227 + }, 228 + [account, backendUrl], 229 + ); 230 + 195 231 const setPlaybackRate = useCallback( 196 232 (v: number) => { 197 233 if (isInWatchParty) return; // Don't allow changes in watch party ··· 200 236 [display, isInWatchParty], 201 237 ); 202 238 239 + // Handle thumbnail toggle with backend save 240 + const handleThumbnailToggle = useCallback(() => { 241 + const newValue = !enableThumbnails; 242 + setEnableThumbnails(newValue); 243 + saveThumbnailSetting(newValue); 244 + }, [enableThumbnails, setEnableThumbnails, saveThumbnailSetting]); 245 + 246 + // Handle autoplay toggle with backend save 247 + const handleAutoplayToggle = useCallback(() => { 248 + const newValue = !enableAutoplay; 249 + setEnableAutoplay(newValue); 250 + saveAutoplaySetting(newValue); 251 + }, [enableAutoplay, setEnableAutoplay, saveAutoplaySetting]); 252 + 203 253 // Force 1x speed in watch party 204 254 useEffect(() => { 205 255 if (isInWatchParty && display && playbackRate !== 1) { ··· 239 289 rightSide={ 240 290 <Toggle 241 291 enabled={enableAutoplay} 242 - onClick={() => setEnableAutoplay(!enableAutoplay)} 292 + onClick={handleAutoplayToggle} 243 293 /> 244 294 } 245 295 > 246 296 {t("settings.preferences.autoplayLabel")} 247 297 </Menu.Link> 248 298 )} 249 - <Menu.Link 250 - rightSide={ 251 - <Toggle 252 - enabled={enableThumbnails} 253 - onClick={() => setEnableThumbnails(!enableThumbnails)} 254 - /> 255 - } 256 - > 257 - {t("settings.preferences.thumbnailLabel")} 258 - </Menu.Link> 299 + {!enableLowPerformanceMode && ( 300 + <Menu.Link 301 + rightSide={ 302 + <Toggle 303 + enabled={enableThumbnails} 304 + onClick={handleThumbnailToggle} 305 + /> 306 + } 307 + > 308 + {t("settings.preferences.thumbnailLabel")} 309 + </Menu.Link> 310 + )} 259 311 </div> 260 312 </Menu.Section> 261 313 </>
+14 -7
src/components/player/internals/ThumbnailScraper.tsx
··· 1 1 import Hls from "hls.js"; 2 2 import { useCallback, useEffect, useRef } from "react"; 3 3 4 - import { playerStatus } from "@/stores/player/slices/source"; 5 4 import { ThumbnailImage } from "@/stores/player/slices/thumbnails"; 6 5 import { usePlayerStore } from "@/stores/player/store"; 7 6 import { LoadableSource, selectQuality } from "@/stores/player/utils/qualities"; ··· 125 124 126 125 export function ThumbnailScraper() { 127 126 const addImage = usePlayerStore((s) => s.thumbnails.addImage); 128 - const status = usePlayerStore((s) => s.status); 129 127 const resetImages = usePlayerStore((s) => s.thumbnails.resetImages); 130 128 const meta = usePlayerStore((s) => s.meta); 131 129 const source = usePlayerStore((s) => s.source); 130 + const hasPlayedOnce = usePlayerStore((s) => s.mediaPlaying.hasPlayedOnce); 131 + const duration = usePlayerStore((s) => s.progress.duration); 132 132 const enableThumbnails = usePreferencesStore((s) => s.enableThumbnails); 133 133 const workerRef = useRef<ThumnbnailWorker | null>(null); 134 134 ··· 144 144 }); 145 145 // dont interrupt existing working 146 146 if (workerRef.current) return; 147 - if (status !== playerStatus.PLAYING) return; 147 + // Allow thumbnail generation when video is loaded and has duration 148 + if (!hasPlayedOnce || duration <= 0) return; 148 149 if (!inputStream) return; 149 150 resetImages(); 150 151 const ins = new ThumnbnailWorker({ ··· 152 153 }); 153 154 workerRef.current = ins; 154 155 ins.start(inputStream.stream); 155 - }, [source, addImage, resetImages, status]); 156 + }, [source, addImage, resetImages, hasPlayedOnce, duration]); 156 157 157 158 const startRef = useRef(start); 158 159 useEffect(() => { 159 160 startRef.current = start; 160 - }, [start, status]); 161 + }, [start]); 161 162 162 163 // start worker with the stream 163 164 useEffect(() => { 164 165 if (enableThumbnails) startRef.current(); 165 - }, [sourceSeralized, enableThumbnails]); 166 + }, [sourceSeralized, enableThumbnails, hasPlayedOnce, duration]); 166 167 167 168 // destroy worker on unmount 168 169 useEffect(() => { ··· 186 187 workerRef.current = null; 187 188 } 188 189 if (enableThumbnails) startRef.current(); 189 - }, [serializedMeta, sourceSeralized, status, enableThumbnails]); 190 + }, [ 191 + serializedMeta, 192 + sourceSeralized, 193 + enableThumbnails, 194 + hasPlayedOnce, 195 + duration, 196 + ]); 190 197 191 198 return null; 192 199 }
+1 -8
src/pages/parts/settings/PreferencesPart.tsx
··· 70 70 const navigate = useNavigate(); 71 71 72 72 const handleLowPerformanceModeToggle = () => { 73 - const newMode = !props.enableLowPerformanceMode; 74 - props.setEnableLowPerformanceMode(newMode); 75 - 76 - // When enabling low performance mode, disable bandwidth-heavy features 77 - if (newMode) { 78 - props.setEnableThumbnails(false); 79 - props.setEnableAutoplay(false); 80 - } 73 + props.setEnableLowPerformanceMode(!props.enableLowPerformanceMode); 81 74 }; 82 75 83 76 const handleSourceToggle = (sourceId: string) => {
+5
src/stores/preferences/index.tsx
··· 174 174 setEnableLowPerformanceMode(v) { 175 175 set((s) => { 176 176 s.enableLowPerformanceMode = v; 177 + // When enabling performance mode, disable bandwidth-heavy features 178 + if (v) { 179 + s.enableThumbnails = false; 180 + s.enableAutoplay = false; 181 + } 177 182 }); 178 183 }, 179 184 setEnableNativeSubtitles(v) {