Allow watching and bookmark section to be reordered

This commit is contained in:
Pas 2025-09-29 16:13:37 -06:00
parent e9af26b917
commit 565e93fa73
6 changed files with 117 additions and 27 deletions

View file

@ -970,7 +970,13 @@
"carouselViewLabel": "Carousel view",
"forceCompactEpisodeView": "Force compact episode view",
"forceCompactEpisodeViewDescription": "Force the episode carousel in the player to use the \"classic\" compact vertical view. Disabled by default.",
"homeSectionOrder": "Home section order",
"homeSectionOrderDescription": "Drag and drop to reorder the watching and bookmarks sections on your homepage. Group order can be editied from the home page.",
"forceCompactEpisodeViewLabel": "Compact episodes"
},
"sections": {
"watching": "Currently Watching",
"bookmarks": "Bookmarks"
}
},
"connections": {

View file

@ -66,6 +66,7 @@ export function useSettingsState(
forceCompactEpisodeView: boolean,
enableLowPerformanceMode: boolean,
enableHoldToBoost: boolean,
homeSectionOrder: string[],
) {
const [proxyUrlsState, setProxyUrls, resetProxyUrls, proxyUrlsChanged] =
useDerived(proxyUrls);
@ -181,6 +182,12 @@ export function useSettingsState(
resetEnableHoldToBoost,
enableHoldToBoostChanged,
] = useDerived(enableHoldToBoost);
const [
homeSectionOrderState,
setHomeSectionOrderState,
resetHomeSectionOrder,
homeSectionOrderChanged,
] = useDerived(homeSectionOrder);
function reset() {
resetTheme();
@ -207,6 +214,7 @@ export function useSettingsState(
resetForceCompactEpisodeView();
resetEnableLowPerformanceMode();
resetEnableHoldToBoost();
resetHomeSectionOrder();
}
const changed =
@ -232,7 +240,8 @@ export function useSettingsState(
enableCarouselViewChanged ||
forceCompactEpisodeViewChanged ||
enableLowPerformanceModeChanged ||
enableHoldToBoostChanged;
enableHoldToBoostChanged ||
homeSectionOrderChanged;
return {
reset,
@ -352,5 +361,10 @@ export function useSettingsState(
set: setEnableHoldToBoostState,
changed: enableHoldToBoostChanged,
},
homeSectionOrder: {
state: homeSectionOrderState,
set: setHomeSectionOrderState,
changed: homeSectionOrderChanged,
},
};
}

View file

@ -73,6 +73,9 @@ export function HomePage() {
const enableLowPerformanceMode = usePreferencesStore(
(state) => state.enableLowPerformanceMode,
);
const homeSectionOrder = usePreferencesStore(
(state) => state.homeSectionOrder,
);
const handleClick = (path: To) => {
window.scrollTo(0, 0);
@ -87,6 +90,56 @@ export function HomePage() {
showModal("details");
};
const renderHomeSections = () => {
const sections = homeSectionOrder.map((section) => {
switch (section) {
case "watching":
return enableCarouselView ? (
<WatchingCarousel
key="watching"
carouselRefs={carouselRefs}
onShowDetails={handleShowDetails}
/>
) : (
<WatchingPart
key="watching"
onItemsChange={setShowWatching}
onShowDetails={handleShowDetails}
/>
);
case "bookmarks":
return enableCarouselView ? (
<BookmarksCarousel
key="bookmarks"
carouselRefs={carouselRefs}
onShowDetails={handleShowDetails}
/>
) : (
<BookmarksPart
key="bookmarks"
onItemsChange={setShowBookmarks}
onShowDetails={handleShowDetails}
/>
);
default:
return null;
}
});
if (enableCarouselView) {
return (
<WideContainer ultraWide classNames="!px-3 md:!px-9">
{sections}
</WideContainer>
);
}
return (
<WideContainer>
<div className="flex flex-col gap-8">{sections}</div>
</WideContainer>
);
};
return (
<HomeLayout showBg={showBg}>
<div className="mb-2">
@ -141,32 +194,7 @@ export function HomePage() {
)}
{/* User Content */}
{!search &&
(enableCarouselView ? (
<WideContainer ultraWide classNames="!px-3 md:!px-9">
<WatchingCarousel
carouselRefs={carouselRefs}
onShowDetails={handleShowDetails}
/>
<BookmarksCarousel
carouselRefs={carouselRefs}
onShowDetails={handleShowDetails}
/>
</WideContainer>
) : (
<WideContainer>
<div className="flex flex-col gap-8">
<WatchingPart
onItemsChange={setShowWatching}
onShowDetails={handleShowDetails}
/>
<BookmarksPart
onItemsChange={setShowBookmarks}
onShowDetails={handleShowDetails}
/>
</div>
</WideContainer>
))}
{!search && renderHomeSections()}
{/* Under user content */}
<WideContainer ultraWide classNames="!px-3 md:!px-9">

View file

@ -197,6 +197,9 @@ export function SettingsPage() {
(s) => s.setEnableHoldToBoost,
);
const homeSectionOrder = usePreferencesStore((s) => s.homeSectionOrder);
const setHomeSectionOrder = usePreferencesStore((s) => s.setHomeSectionOrder);
const account = useAuthStore((s) => s.account);
const updateProfile = useAuthStore((s) => s.setAccountProfile);
const updateDeviceName = useAuthStore((s) => s.updateDeviceName);
@ -249,6 +252,7 @@ export function SettingsPage() {
forceCompactEpisodeView,
enableLowPerformanceMode,
enableHoldToBoost,
homeSectionOrder,
);
const availableSources = useMemo(() => {
@ -369,6 +373,7 @@ export function SettingsPage() {
setForceCompactEpisodeView(state.forceCompactEpisodeView.state);
setEnableLowPerformanceMode(state.enableLowPerformanceMode.state);
setEnableHoldToBoost(state.enableHoldToBoost.state);
setHomeSectionOrder(state.homeSectionOrder.state);
if (state.profile.state) {
updateProfile(state.profile.state);
@ -413,6 +418,7 @@ export function SettingsPage() {
setForceCompactEpisodeView,
setEnableLowPerformanceMode,
setEnableHoldToBoost,
setHomeSectionOrder,
]);
return (
<SubPageLayout>
@ -484,6 +490,8 @@ export function SettingsPage() {
setEnableCarouselView={state.enableCarouselView.set}
forceCompactEpisodeView={state.forceCompactEpisodeView.state}
setForceCompactEpisodeView={state.forceCompactEpisodeView.set}
homeSectionOrder={state.homeSectionOrder.state}
setHomeSectionOrder={state.homeSectionOrder.set}
enableLowPerformanceMode={state.enableLowPerformanceMode.state}
/>
</div>

View file

@ -3,6 +3,7 @@ import { useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { Toggle } from "@/components/buttons/Toggle";
import { SortableList } from "@/components/form/SortableList";
import { Icon, Icons } from "@/components/Icon";
import { Heading1 } from "@/components/utils/Text";
@ -225,6 +226,9 @@ export function AppearancePart(props: {
forceCompactEpisodeView: boolean;
setForceCompactEpisodeView: (v: boolean) => void;
homeSectionOrder: string[];
setHomeSectionOrder: (v: string[]) => void;
enableLowPerformanceMode: boolean;
}) {
const { t } = useTranslation();
@ -470,6 +474,28 @@ export function AppearancePart(props: {
</p>
</div>
</div>
{/* Home Section Order */}
<div>
<p className="text-white font-bold mb-3">
{t("settings.appearance.options.homeSectionOrder")}
</p>
<p className="max-w-[25rem] font-medium">
{t("settings.appearance.options.homeSectionOrderDescription")}
</p>
<div className="my-4 max-w-[25rem]">
<SortableList
items={props.homeSectionOrder.map((section) => ({
id: section,
name: t(`settings.appearance.sections.${section}`),
}))}
setItems={(items) => {
const newOrder = items.map((item) => item.id);
props.setHomeSectionOrder(newOrder);
}}
/>
</div>
</div>
</div>
{/* Second Column - Themes */}

View file

@ -22,6 +22,7 @@ export interface PreferencesStore {
enableLowPerformanceMode: boolean;
enableNativeSubtitles: boolean;
enableHoldToBoost: boolean;
homeSectionOrder: string[];
setEnableThumbnails(v: boolean): void;
setEnableAutoplay(v: boolean): void;
@ -42,6 +43,7 @@ export interface PreferencesStore {
setEnableLowPerformanceMode(v: boolean): void;
setEnableNativeSubtitles(v: boolean): void;
setEnableHoldToBoost(v: boolean): void;
setHomeSectionOrder(v: string[]): void;
}
export const usePreferencesStore = create(
@ -66,6 +68,7 @@ export const usePreferencesStore = create(
enableLowPerformanceMode: false,
enableNativeSubtitles: false,
enableHoldToBoost: true,
homeSectionOrder: ["watching", "bookmarks"],
setEnableThumbnails(v) {
set((s) => {
s.enableThumbnails = v;
@ -161,6 +164,11 @@ export const usePreferencesStore = create(
s.enableHoldToBoost = v;
});
},
setHomeSectionOrder(v) {
set((s) => {
s.homeSectionOrder = v;
});
},
})),
{
name: "__MW::preferences",