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.

add minimal cards setting

Pas 342219b4 41947f8d

+122 -42
+3
src/assets/locales/en.json
··· 1104 1104 "carouselView": "Carousel view", 1105 1105 "carouselViewDescription": "Display your currently watching and bookmark sections as carousels instead of a grid. Disabled by default.", 1106 1106 "carouselViewLabel": "Carousel view", 1107 + "minimalCards": "Minimal cards", 1108 + "minimalCardsDescription": "Hide text content (title, type, year) on media cards, showing only the poster image.", 1109 + "minimalCardsLabel": "Minimal cards", 1107 1110 "forceCompactEpisodeView": "Force compact episode view", 1108 1111 "forceCompactEpisodeViewDescription": "Force the episode carousel in the player to use the \"classic\" compact vertical view. Disabled by default.", 1109 1112 "homeSectionOrder": "Home section order",
+2
src/backend/accounts/settings.ts
··· 20 20 enableDetailsModal?: boolean; 21 21 enableImageLogos?: boolean; 22 22 enableCarouselView?: boolean; 23 + enableMinimalCards?: boolean; 23 24 forceCompactEpisodeView?: boolean; 24 25 sourceOrder?: string[] | null; 25 26 enableSourceOrder?: boolean; ··· 56 57 enableDetailsModal?: boolean; 57 58 enableImageLogos?: boolean; 58 59 enableCarouselView?: boolean; 60 + enableMinimalCards?: boolean; 59 61 forceCompactEpisodeView?: boolean; 60 62 sourceOrder?: string[] | null; 61 63 enableSourceOrder?: boolean;
+48 -42
src/components/media/MediaCard.tsx
··· 136 136 const dotListContent = [t(`media.types.${media.type}`)]; 137 137 138 138 const [searchQuery] = useSearchQuery(); 139 + const enableMinimalCards = usePreferencesStore((s) => s.enableMinimalCards); 139 140 140 141 // Simple intersection observer for lazy loading images 141 142 const { targetRef, isIntersecting } = useIntersectionObserver({ ··· 185 186 > 186 187 <div 187 188 className={classNames( 188 - "relative mb-4 pb-[150%] w-full overflow-hidden rounded-xl bg-mediaCard-hoverBackground bg-cover bg-center transition-[border-radius] duration-300", 189 + "relative pb-[150%] w-full overflow-hidden rounded-xl bg-mediaCard-hoverBackground bg-cover bg-center transition-[border-radius] duration-300", 189 190 { 190 191 "group-hover:rounded-lg": canLink, 191 192 }, 193 + enableMinimalCards ? "" : "mb-4", 192 194 )} 193 195 style={{ 194 196 backgroundImage: isIntersecting ··· 272 274 </div> 273 275 </div> 274 276 275 - <h1 className="mb-1 line-clamp-3 max-h-[4.5rem] text-ellipsis break-words font-bold text-white"> 276 - <span>{media.title}</span> 277 - </h1> 278 - <div className="media-info-container justify-content-center flex flex-wrap"> 279 - <DotList className="text-xs" content={dotListContent} /> 280 - </div> 277 + {!enableMinimalCards && ( 278 + <> 279 + <h1 className="mb-1 line-clamp-3 max-h-[4.5rem] text-ellipsis break-words font-bold text-white"> 280 + <span>{media.title}</span> 281 + </h1> 282 + <div className="media-info-container justify-content-center flex flex-wrap"> 283 + <DotList className="text-xs" content={dotListContent} /> 284 + </div> 281 285 282 - {!closable && ( 283 - <div className="absolute bottom-0 translate-y-1 right-1"> 284 - <button 285 - className="media-more-button p-2" 286 - type="button" 287 - onClick={(e) => { 288 - e.preventDefault(); 289 - e.stopPropagation(); 290 - onShowDetails?.(media); 291 - }} 292 - > 293 - <Icon 294 - className="text-xs font-semibold text-type-secondary" 295 - icon={Icons.ELLIPSIS} 296 - /> 297 - </button> 298 - </div> 299 - )} 300 - {editable && closable && ( 301 - <div className="absolute bottom-0 translate-y-1 right-1"> 302 - <button 303 - className="media-more-button p-2" 304 - type="button" 305 - onClick={(e) => { 306 - e.preventDefault(); 307 - e.stopPropagation(); 308 - onEdit?.(); 309 - }} 310 - > 311 - <Icon 312 - className="text-xs font-semibold text-type-secondary" 313 - icon={Icons.EDIT} 314 - /> 315 - </button> 316 - </div> 286 + {!closable && ( 287 + <div className="absolute bottom-0 translate-y-1 right-1"> 288 + <button 289 + className="media-more-button p-2" 290 + type="button" 291 + onClick={(e) => { 292 + e.preventDefault(); 293 + e.stopPropagation(); 294 + onShowDetails?.(media); 295 + }} 296 + > 297 + <Icon 298 + className="text-xs font-semibold text-type-secondary" 299 + icon={Icons.ELLIPSIS} 300 + /> 301 + </button> 302 + </div> 303 + )} 304 + {editable && closable && ( 305 + <div className="absolute bottom-0 translate-y-1 right-1"> 306 + <button 307 + className="media-more-button p-2" 308 + type="button" 309 + onClick={(e) => { 310 + e.preventDefault(); 311 + e.stopPropagation(); 312 + onEdit?.(); 313 + }} 314 + > 315 + <Icon 316 + className="text-xs font-semibold text-type-secondary" 317 + icon={Icons.EDIT} 318 + /> 319 + </button> 320 + </div> 321 + )} 322 + </> 317 323 )} 318 324 </Flare.Child> 319 325 </Flare.Base>
+8
src/hooks/auth/useAuthData.ts
··· 94 94 const setKeyboardShortcuts = usePreferencesStore( 95 95 (s) => s.setKeyboardShortcuts, 96 96 ); 97 + const setEnableMinimalCards = usePreferencesStore( 98 + (s) => s.setEnableMinimalCards, 99 + ); 97 100 98 101 const login = useCallback( 99 102 async ( ··· 282 285 if (settings.keyboardShortcuts !== undefined) { 283 286 setKeyboardShortcuts(settings.keyboardShortcuts); 284 287 } 288 + 289 + if (settings.enableMinimalCards !== undefined) { 290 + setEnableMinimalCards(settings.enableMinimalCards); 291 + } 285 292 }, 286 293 [ 287 294 replaceBookmarks, ··· 319 326 setEnableDoubleClickToSeek, 320 327 setEnableAutoResumeOnPlaybackError, 321 328 setKeyboardShortcuts, 329 + setEnableMinimalCards, 322 330 ], 323 331 ); 324 332
+14
src/hooks/useSettingsState.ts
··· 72 72 enableSkipCredits: boolean, 73 73 enableImageLogos: boolean, 74 74 enableCarouselView: boolean, 75 + enableMinimalCards: boolean, 75 76 forceCompactEpisodeView: boolean, 76 77 enableLowPerformanceMode: boolean, 77 78 enableNativeSubtitles: boolean, ··· 221 222 resetEnableCarouselView, 222 223 enableCarouselViewChanged, 223 224 ] = useDerived(enableCarouselView); 225 + const [ 226 + enableMinimalCardsState, 227 + setEnableMinimalCardsState, 228 + resetEnableMinimalCards, 229 + enableMinimalCardsChanged, 230 + ] = useDerived(enableMinimalCards); 224 231 const [ 225 232 forceCompactEpisodeViewState, 226 233 setForceCompactEpisodeViewState, ··· 299 306 resetDisabledEmbeds(); 300 307 resetProxyTmdb(); 301 308 resetEnableCarouselView(); 309 + resetEnableMinimalCards(); 302 310 resetForceCompactEpisodeView(); 303 311 resetEnableLowPerformanceMode(); 304 312 resetEnableNativeSubtitles(); ··· 338 346 disabledEmbedsChanged || 339 347 proxyTmdbChanged || 340 348 enableCarouselViewChanged || 349 + enableMinimalCardsChanged || 341 350 forceCompactEpisodeViewChanged || 342 351 enableLowPerformanceModeChanged || 343 352 enableNativeSubtitlesChanged || ··· 489 498 state: enableCarouselViewState, 490 499 set: setEnableCarouselViewState, 491 500 changed: enableCarouselViewChanged, 501 + }, 502 + enableMinimalCards: { 503 + state: enableMinimalCardsState, 504 + set: setEnableMinimalCardsState, 505 + changed: enableMinimalCardsChanged, 492 506 }, 493 507 forceCompactEpisodeView: { 494 508 state: forceCompactEpisodeViewState,
+12
src/pages/Settings.tsx
··· 448 448 (s) => s.setEnableCarouselView, 449 449 ); 450 450 451 + const enableMinimalCards = usePreferencesStore((s) => s.enableMinimalCards); 452 + const setEnableMinimalCards = usePreferencesStore( 453 + (s) => s.setEnableMinimalCards, 454 + ); 455 + 451 456 const forceCompactEpisodeView = usePreferencesStore( 452 457 (s) => s.forceCompactEpisodeView, 453 458 ); ··· 563 568 enableSkipCredits, 564 569 enableImageLogos, 565 570 enableCarouselView, 571 + enableMinimalCards, 566 572 forceCompactEpisodeView, 567 573 enableLowPerformanceMode, 568 574 enableNativeSubtitles, ··· 631 637 state.disabledSources.changed || 632 638 state.proxyTmdb.changed || 633 639 state.enableCarouselView.changed || 640 + state.enableMinimalCards.changed || 634 641 state.forceCompactEpisodeView.changed || 635 642 state.enableLowPerformanceMode.changed || 636 643 state.enableHoldToBoost.changed || ··· 660 667 disabledSources: state.disabledSources.state, 661 668 proxyTmdb: state.proxyTmdb.state, 662 669 enableCarouselView: state.enableCarouselView.state, 670 + enableMinimalCards: state.enableMinimalCards.state, 663 671 forceCompactEpisodeView: state.forceCompactEpisodeView.state, 664 672 enableLowPerformanceMode: state.enableLowPerformanceMode.state, 665 673 enableHoldToBoost: state.enableHoldToBoost.state, ··· 716 724 setdebridService(state.debridService.state); 717 725 setProxyTmdb(state.proxyTmdb.state); 718 726 setEnableCarouselView(state.enableCarouselView.state); 727 + setEnableMinimalCards(state.enableMinimalCards.state); 719 728 setForceCompactEpisodeView(state.forceCompactEpisodeView.state); 720 729 setEnableLowPerformanceMode(state.enableLowPerformanceMode.state); 721 730 setEnableHoldToBoost(state.enableHoldToBoost.state); ··· 771 780 setBackendUrl, 772 781 setProxyTmdb, 773 782 setEnableCarouselView, 783 + setEnableMinimalCards, 774 784 setForceCompactEpisodeView, 775 785 setEnableLowPerformanceMode, 776 786 setEnableHoldToBoost, ··· 886 896 setEnableImageLogos={state.enableImageLogos.set} 887 897 enableCarouselView={state.enableCarouselView.state} 888 898 setEnableCarouselView={state.enableCarouselView.set} 899 + enableMinimalCards={state.enableMinimalCards.state} 900 + setEnableMinimalCards={state.enableMinimalCards.set} 889 901 forceCompactEpisodeView={state.forceCompactEpisodeView.state} 890 902 setForceCompactEpisodeView={state.forceCompactEpisodeView.set} 891 903 homeSectionOrder={state.homeSectionOrder.state}
+27
src/pages/parts/settings/AppearancePart.tsx
··· 245 245 enableCarouselView: boolean; 246 246 setEnableCarouselView: (v: boolean) => void; 247 247 248 + enableMinimalCards: boolean; 249 + setEnableMinimalCards: (v: boolean) => void; 250 + 248 251 forceCompactEpisodeView: boolean; 249 252 setForceCompactEpisodeView: (v: boolean) => void; 250 253 ··· 506 509 <Toggle enabled={props.enableCarouselView} /> 507 510 <p className="flex-1 text-white font-bold"> 508 511 {t("settings.appearance.options.carouselViewLabel")} 512 + </p> 513 + </div> 514 + </div> 515 + 516 + {/* Minimal Cards */} 517 + <div> 518 + <p className="text-white font-bold mb-3"> 519 + {t("settings.appearance.options.minimalCards")} 520 + </p> 521 + <p className="max-w-[25rem] font-medium"> 522 + {t("settings.appearance.options.minimalCardsDescription")} 523 + </p> 524 + <div 525 + onClick={() => 526 + props.setEnableMinimalCards(!props.enableMinimalCards) 527 + } 528 + className={classNames( 529 + "bg-dropdown-background hover:bg-dropdown-hoverBackground select-none my-4 cursor-pointer space-x-3 flex items-center max-w-[25rem] py-3 px-4 rounded-lg", 530 + "cursor-pointer opacity-100 pointer-events-auto", 531 + )} 532 + > 533 + <Toggle enabled={props.enableMinimalCards} /> 534 + <p className="flex-1 text-white font-bold"> 535 + {t("settings.appearance.options.minimalCardsLabel")} 509 536 </p> 510 537 </div> 511 538 </div>
+8
src/stores/preferences/index.tsx
··· 16 16 enableDetailsModal: boolean; 17 17 enableImageLogos: boolean; 18 18 enableCarouselView: boolean; 19 + enableMinimalCards: boolean; 19 20 forceCompactEpisodeView: boolean; 20 21 sourceOrder: string[]; 21 22 enableSourceOrder: boolean; ··· 46 47 setEnableDetailsModal(v: boolean): void; 47 48 setEnableImageLogos(v: boolean): void; 48 49 setEnableCarouselView(v: boolean): void; 50 + setEnableMinimalCards(v: boolean): void; 49 51 setForceCompactEpisodeView(v: boolean): void; 50 52 setSourceOrder(v: string[]): void; 51 53 setEnableSourceOrder(v: boolean): void; ··· 80 82 enableDetailsModal: false, 81 83 enableImageLogos: true, 82 84 enableCarouselView: false, 85 + enableMinimalCards: false, 83 86 forceCompactEpisodeView: false, 84 87 sourceOrder: [], 85 88 enableSourceOrder: false, ··· 139 142 setEnableCarouselView(v) { 140 143 set((s) => { 141 144 s.enableCarouselView = v; 145 + }); 146 + }, 147 + setEnableMinimalCards(v) { 148 + set((s) => { 149 + s.enableMinimalCards = v; 142 150 }); 143 151 }, 144 152 setForceCompactEpisodeView(v) {