mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-20 14:37:43 +01:00
setup sources reordering
This commit is contained in:
parent
dad968ee0f
commit
9d796108a5
9 changed files with 235 additions and 28 deletions
|
@ -26,6 +26,9 @@
|
|||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@dnd-kit/core": "^6.1.0",
|
||||
"@dnd-kit/sortable": "^8.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@formkit/auto-animate": "^0.8.1",
|
||||
"@headlessui/react": "^1.7.17",
|
||||
"@ladjs/country-language": "^1.0.3",
|
||||
|
|
103
pnpm-lock.yaml
103
pnpm-lock.yaml
|
@ -12,6 +12,15 @@ overrides:
|
|||
rollup: npm:@rollup/wasm-node
|
||||
|
||||
dependencies:
|
||||
'@dnd-kit/core':
|
||||
specifier: ^6.1.0
|
||||
version: 6.1.0(react-dom@18.2.0)(react@18.2.0)
|
||||
'@dnd-kit/sortable':
|
||||
specifier: ^8.0.0
|
||||
version: 8.0.0(@dnd-kit/core@6.1.0)(react@18.2.0)
|
||||
'@dnd-kit/utilities':
|
||||
specifier: ^3.2.2
|
||||
version: 3.2.2(react@18.2.0)
|
||||
'@formkit/auto-animate':
|
||||
specifier: ^0.8.1
|
||||
version: 0.8.1
|
||||
|
@ -274,7 +283,7 @@ devDependencies:
|
|||
version: 0.5.9(prettier@3.1.1)
|
||||
rollup-plugin-visualizer:
|
||||
specifier: ^5.11.0
|
||||
version: 5.11.0(@rollup/wasm-node@4.14.2)
|
||||
version: 5.11.0(@rollup/wasm-node@4.14.3)
|
||||
tailwind-scrollbar:
|
||||
specifier: ^3.0.5
|
||||
version: 3.0.5(tailwindcss@3.4.0)
|
||||
|
@ -2688,6 +2697,49 @@ packages:
|
|||
to-fast-properties: 2.0.0
|
||||
dev: true
|
||||
|
||||
/@dnd-kit/accessibility@3.1.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-ea7IkhKvlJUv9iSHJOnxinBcoOI3ppGnnL+VDJ75O45Nss6HtZd8IdN8touXPDtASfeI2T2LImb8VOZcL47wjQ==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.0'
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
tslib: 2.6.2
|
||||
dev: false
|
||||
|
||||
/@dnd-kit/core@6.1.0(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-J3cQBClB4TVxwGo3KEjssGEXNJqGVWx17aRTZ1ob0FliR5IjYgTxl5YJbKTzA6IzrtelotH19v6y7uoIRUZPSg==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.0'
|
||||
react-dom: '>=16.8.0'
|
||||
dependencies:
|
||||
'@dnd-kit/accessibility': 3.1.0(react@18.2.0)
|
||||
'@dnd-kit/utilities': 3.2.2(react@18.2.0)
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
tslib: 2.6.2
|
||||
dev: false
|
||||
|
||||
/@dnd-kit/sortable@8.0.0(@dnd-kit/core@6.1.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-U3jk5ebVXe1Lr7c2wU7SBZjcWdQP+j7peHJfCspnA81enlu88Mgd7CC8Q+pub9ubP7eKVETzJW+IBAhsqbSu/g==}
|
||||
peerDependencies:
|
||||
'@dnd-kit/core': ^6.1.0
|
||||
react: '>=16.8.0'
|
||||
dependencies:
|
||||
'@dnd-kit/core': 6.1.0(react-dom@18.2.0)(react@18.2.0)
|
||||
'@dnd-kit/utilities': 3.2.2(react@18.2.0)
|
||||
react: 18.2.0
|
||||
tslib: 2.6.2
|
||||
dev: false
|
||||
|
||||
/@dnd-kit/utilities@3.2.2(react@18.2.0):
|
||||
resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.0'
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
tslib: 2.6.2
|
||||
dev: false
|
||||
|
||||
/@esbuild/aix-ppc64@0.19.10:
|
||||
resolution: {integrity: sha512-Q+mk96KJ+FZ30h9fsJl+67IjNJm3x2eX+GBWGmocAKgzp27cowCOOqSdscX80s0SpdFXZnIv/+1xD1EctFx96Q==}
|
||||
engines: {node: '>=12'}
|
||||
|
@ -3175,7 +3227,7 @@ packages:
|
|||
engines: {node: '>=14.0.0'}
|
||||
dev: false
|
||||
|
||||
/@rollup/plugin-babel@5.3.1(@babel/core@7.24.3)(@rollup/wasm-node@4.14.2):
|
||||
/@rollup/plugin-babel@5.3.1(@babel/core@7.24.3)(@rollup/wasm-node@4.14.3):
|
||||
resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
peerDependencies:
|
||||
|
@ -3188,36 +3240,36 @@ packages:
|
|||
dependencies:
|
||||
'@babel/core': 7.24.3
|
||||
'@babel/helper-module-imports': 7.24.3
|
||||
'@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.14.2)
|
||||
rollup: /@rollup/wasm-node@4.14.2
|
||||
'@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.14.3)
|
||||
rollup: /@rollup/wasm-node@4.14.3
|
||||
dev: true
|
||||
|
||||
/@rollup/plugin-node-resolve@11.2.1(@rollup/wasm-node@4.14.2):
|
||||
/@rollup/plugin-node-resolve@11.2.1(@rollup/wasm-node@4.14.3):
|
||||
resolution: {integrity: sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
peerDependencies:
|
||||
rollup: npm:@rollup/wasm-node
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.14.2)
|
||||
'@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.14.3)
|
||||
'@types/resolve': 1.17.1
|
||||
builtin-modules: 3.3.0
|
||||
deepmerge: 4.3.1
|
||||
is-module: 1.0.0
|
||||
resolve: 1.22.8
|
||||
rollup: /@rollup/wasm-node@4.14.2
|
||||
rollup: /@rollup/wasm-node@4.14.3
|
||||
dev: true
|
||||
|
||||
/@rollup/plugin-replace@2.4.2(@rollup/wasm-node@4.14.2):
|
||||
/@rollup/plugin-replace@2.4.2(@rollup/wasm-node@4.14.3):
|
||||
resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==}
|
||||
peerDependencies:
|
||||
rollup: npm:@rollup/wasm-node
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.14.2)
|
||||
'@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.14.3)
|
||||
magic-string: 0.25.9
|
||||
rollup: /@rollup/wasm-node@4.14.2
|
||||
rollup: /@rollup/wasm-node@4.14.3
|
||||
dev: true
|
||||
|
||||
/@rollup/pluginutils@3.1.0(@rollup/wasm-node@4.14.2):
|
||||
/@rollup/pluginutils@3.1.0(@rollup/wasm-node@4.14.3):
|
||||
resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==}
|
||||
engines: {node: '>= 8.0.0'}
|
||||
peerDependencies:
|
||||
|
@ -3226,11 +3278,11 @@ packages:
|
|||
'@types/estree': 0.0.39
|
||||
estree-walker: 1.0.1
|
||||
picomatch: 2.3.1
|
||||
rollup: /@rollup/wasm-node@4.14.2
|
||||
rollup: /@rollup/wasm-node@4.14.3
|
||||
dev: true
|
||||
|
||||
/@rollup/wasm-node@4.14.2:
|
||||
resolution: {integrity: sha512-iwZbxtvP/0icwPWExUZWfA3A2jqQkDY38E8R5onRY2ALFmom0k7e37n9WDcJMMRcx/pdenfN8NaSohzX9LiDEQ==}
|
||||
/@rollup/wasm-node@4.14.3:
|
||||
resolution: {integrity: sha512-UyFUQV/iAu/Wt6rY6uQMYBQlfTMsynzYVIz6i7s9ySwjoG9WDNgtkK1TrazCSrUFbmuPZi2gbJm6VWdJCVw2yA==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
|
@ -6557,7 +6609,7 @@ packages:
|
|||
'@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.6)
|
||||
'@babel/types': 7.23.6
|
||||
kleur: 4.1.5
|
||||
rollup: /@rollup/wasm-node@4.14.2
|
||||
rollup: /@rollup/wasm-node@4.14.3
|
||||
unplugin: 1.5.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
@ -7529,7 +7581,7 @@ packages:
|
|||
glob: 7.2.3
|
||||
dev: true
|
||||
|
||||
/rollup-plugin-terser@7.0.2(@rollup/wasm-node@4.14.2):
|
||||
/rollup-plugin-terser@7.0.2(@rollup/wasm-node@4.14.3):
|
||||
resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==}
|
||||
deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser
|
||||
peerDependencies:
|
||||
|
@ -7537,12 +7589,12 @@ packages:
|
|||
dependencies:
|
||||
'@babel/code-frame': 7.24.2
|
||||
jest-worker: 26.6.2
|
||||
rollup: /@rollup/wasm-node@4.14.2
|
||||
rollup: /@rollup/wasm-node@4.14.3
|
||||
serialize-javascript: 4.0.0
|
||||
terser: 5.30.0
|
||||
dev: true
|
||||
|
||||
/rollup-plugin-visualizer@5.11.0(@rollup/wasm-node@4.14.2):
|
||||
/rollup-plugin-visualizer@5.11.0(@rollup/wasm-node@4.14.3):
|
||||
resolution: {integrity: sha512-exM0Ms2SN3AgTzMeW7y46neZQcyLY7eKwWAop1ZoRTCZwyrIRdMMJ6JjToAJbML77X/9N8ZEpmXG4Z/Clb9k8g==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
|
@ -7554,7 +7606,7 @@ packages:
|
|||
dependencies:
|
||||
open: 8.4.2
|
||||
picomatch: 2.3.1
|
||||
rollup: /@rollup/wasm-node@4.14.2
|
||||
rollup: /@rollup/wasm-node@4.14.3
|
||||
source-map: 0.7.4
|
||||
yargs: 17.7.2
|
||||
dev: true
|
||||
|
@ -8692,7 +8744,7 @@ packages:
|
|||
'@types/node': 20.10.5
|
||||
esbuild: 0.19.10
|
||||
postcss: 8.4.32
|
||||
rollup: /@rollup/wasm-node@4.14.2
|
||||
rollup: /@rollup/wasm-node@4.14.3
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
dev: true
|
||||
|
@ -8959,9 +9011,9 @@ packages:
|
|||
'@babel/core': 7.24.3
|
||||
'@babel/preset-env': 7.24.3(@babel/core@7.24.3)
|
||||
'@babel/runtime': 7.24.1
|
||||
'@rollup/plugin-babel': 5.3.1(@babel/core@7.24.3)(@rollup/wasm-node@4.14.2)
|
||||
'@rollup/plugin-node-resolve': 11.2.1(@rollup/wasm-node@4.14.2)
|
||||
'@rollup/plugin-replace': 2.4.2(@rollup/wasm-node@4.14.2)
|
||||
'@rollup/plugin-babel': 5.3.1(@babel/core@7.24.3)(@rollup/wasm-node@4.14.3)
|
||||
'@rollup/plugin-node-resolve': 11.2.1(@rollup/wasm-node@4.14.3)
|
||||
'@rollup/plugin-replace': 2.4.2(@rollup/wasm-node@4.14.3)
|
||||
'@surma/rollup-plugin-off-main-thread': 2.2.3
|
||||
ajv: 8.12.0
|
||||
common-tags: 1.8.2
|
||||
|
@ -8970,8 +9022,8 @@ packages:
|
|||
glob: 7.2.3
|
||||
lodash: 4.17.21
|
||||
pretty-bytes: 5.6.0
|
||||
rollup: /@rollup/wasm-node@4.14.2
|
||||
rollup-plugin-terser: 7.0.2(@rollup/wasm-node@4.14.2)
|
||||
rollup: /@rollup/wasm-node@4.14.3
|
||||
rollup-plugin-terser: 7.0.2(@rollup/wasm-node@4.14.3)
|
||||
source-map: 0.8.0-beta.0
|
||||
stringify-object: 3.3.0
|
||||
strip-comments: 2.0.1
|
||||
|
@ -9016,6 +9068,7 @@ packages:
|
|||
|
||||
/workbox-google-analytics@7.0.0:
|
||||
resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==}
|
||||
deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained
|
||||
dependencies:
|
||||
workbox-background-sync: 7.0.0
|
||||
workbox-core: 7.0.0
|
||||
|
|
|
@ -527,6 +527,8 @@
|
|||
"autoplay": "Autoplay",
|
||||
"autoplayDescription": "Automatically play the next episode in a series after reaching the end. Can be enabled by users with the browser extension, a custom proxy, or with the default setup if allowed by the host.",
|
||||
"autoplayLabel": "Autoplay",
|
||||
"sourceOrder": "Reordering sources",
|
||||
"sourceOrderDescription": "Drag and drop to reorder sources. This will determine the order in which sources are checked for the media you are trying to watch.",
|
||||
"title": "Preferences"
|
||||
},
|
||||
"reset": "Reset",
|
||||
|
|
89
src/components/form/SortableList.tsx
Normal file
89
src/components/form/SortableList.tsx
Normal file
|
@ -0,0 +1,89 @@
|
|||
import {
|
||||
DndContext,
|
||||
DragEndEvent,
|
||||
KeyboardSensor,
|
||||
PointerSensor,
|
||||
closestCenter,
|
||||
useSensor,
|
||||
useSensors,
|
||||
} from "@dnd-kit/core";
|
||||
import {
|
||||
SortableContext,
|
||||
arrayMove,
|
||||
sortableKeyboardCoordinates,
|
||||
useSortable,
|
||||
verticalListSortingStrategy,
|
||||
} from "@dnd-kit/sortable";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
import classNames from "classnames";
|
||||
|
||||
import { Icon, Icons } from "../Icon";
|
||||
|
||||
function SortableItem(props: { id: string }) {
|
||||
const { attributes, listeners, setNodeRef, transform, transition } =
|
||||
useSortable({ id: props.id });
|
||||
|
||||
const style = {
|
||||
transform: CSS.Transform.toString(transform),
|
||||
transition,
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={setNodeRef}
|
||||
style={style}
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
className={classNames(
|
||||
"bg-dropdown-background hover:bg-dropdown-hoverBackground select-none cursor-pointer space-x-3 flex items-center max-w-[25rem] py-3 px-4 rounded-lg",
|
||||
transform && "cursor-grabbing",
|
||||
)}
|
||||
>
|
||||
<span className="flex-1 text-white font-bold">{props.id}</span>
|
||||
<Icon icon={Icons.MENU} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function DraggableList(props: {
|
||||
items: string[];
|
||||
setItems: (items: string[]) => void;
|
||||
}) {
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor),
|
||||
useSensor(KeyboardSensor, {
|
||||
coordinateGetter: sortableKeyboardCoordinates,
|
||||
}),
|
||||
);
|
||||
|
||||
const handleDragEnd = (event: DragEndEvent) => {
|
||||
const { active, over } = event;
|
||||
if (!over) return;
|
||||
if (active.id !== over.id) {
|
||||
const currentItems = props.items;
|
||||
const oldIndex = currentItems.indexOf(active.id as string);
|
||||
const newIndex = currentItems.indexOf(over.id as string);
|
||||
const newItems = arrayMove(currentItems, oldIndex, newIndex);
|
||||
props.setItems(newItems);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
onDragEnd={handleDragEnd}
|
||||
>
|
||||
<SortableContext
|
||||
items={props.items}
|
||||
strategy={verticalListSortingStrategy}
|
||||
>
|
||||
<div className="flex flex-col gap-2">
|
||||
{props.items.map((id) => (
|
||||
<SortableItem key={id} id={id} />
|
||||
))}
|
||||
</div>
|
||||
</SortableContext>
|
||||
</DndContext>
|
||||
);
|
||||
}
|
|
@ -14,6 +14,7 @@ import {
|
|||
} from "@/backend/helpers/providerApi";
|
||||
import { getLoadbalancedProviderApiUrl } from "@/backend/providers/fetchers";
|
||||
import { getProviders } from "@/backend/providers/providers";
|
||||
import { usePreferencesStore } from "@/stores/preferences";
|
||||
|
||||
export interface ScrapingItems {
|
||||
id: string;
|
||||
|
@ -156,6 +157,8 @@ export function useScrape() {
|
|||
startScrape,
|
||||
} = useBaseScrape();
|
||||
|
||||
const preferredSourceOrder = usePreferencesStore((s) => s.sourceOrder);
|
||||
|
||||
const startScraping = useCallback(
|
||||
async (media: ScrapeMedia) => {
|
||||
const providerApiUrl = getLoadbalancedProviderApiUrl();
|
||||
|
@ -181,6 +184,7 @@ export function useScrape() {
|
|||
const providers = getProviders();
|
||||
const output = await providers.runAll({
|
||||
media,
|
||||
sourceOrder: preferredSourceOrder,
|
||||
events: {
|
||||
init: initEvent,
|
||||
start: startEvent,
|
||||
|
@ -199,6 +203,7 @@ export function useScrape() {
|
|||
discoverEmbedsEvent,
|
||||
getResult,
|
||||
startScrape,
|
||||
preferredSourceOrder,
|
||||
],
|
||||
);
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ export function useSettingsState(
|
|||
| undefined,
|
||||
enableThumbnails: boolean,
|
||||
enableAutoplay: boolean,
|
||||
sourceOrder: string[],
|
||||
) {
|
||||
const [proxyUrlsState, setProxyUrls, resetProxyUrls, proxyUrlsChanged] =
|
||||
useDerived(proxyUrls);
|
||||
|
@ -91,6 +92,12 @@ export function useSettingsState(
|
|||
resetEnableAutoplay,
|
||||
enableAutoplayChanged,
|
||||
] = useDerived(enableAutoplay);
|
||||
const [
|
||||
sourceOrderState,
|
||||
setSourceOrderState,
|
||||
resetSourceOrder,
|
||||
sourceOrderChanged,
|
||||
] = useDerived(sourceOrder);
|
||||
|
||||
function reset() {
|
||||
resetTheme();
|
||||
|
@ -103,6 +110,7 @@ export function useSettingsState(
|
|||
resetProfile();
|
||||
resetEnableThumbnails();
|
||||
resetEnableAutoplay();
|
||||
resetSourceOrder();
|
||||
}
|
||||
|
||||
const changed =
|
||||
|
@ -114,7 +122,8 @@ export function useSettingsState(
|
|||
proxyUrlsChanged ||
|
||||
profileChanged ||
|
||||
enableThumbnailsChanged ||
|
||||
enableAutoplayChanged;
|
||||
enableAutoplayChanged ||
|
||||
sourceOrderChanged;
|
||||
|
||||
return {
|
||||
reset,
|
||||
|
@ -164,5 +173,10 @@ export function useSettingsState(
|
|||
set: setEnableAutoplayState,
|
||||
changed: enableAutoplayChanged,
|
||||
},
|
||||
sourceOrder: {
|
||||
state: sourceOrderState,
|
||||
set: setSourceOrderState,
|
||||
changed: sourceOrderChanged,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
import { getSessions, updateSession } from "@/backend/accounts/sessions";
|
||||
import { updateSettings } from "@/backend/accounts/settings";
|
||||
import { editUser } from "@/backend/accounts/user";
|
||||
import { getProviders } from "@/backend/providers/providers";
|
||||
import { Button } from "@/components/buttons/Button";
|
||||
import { WideContainer } from "@/components/layout/WideContainer";
|
||||
import { UserIcons } from "@/components/UserIcon";
|
||||
|
@ -125,6 +126,9 @@ export function SettingsPage() {
|
|||
const enableAutoplay = usePreferencesStore((s) => s.enableAutoplay);
|
||||
const setEnableAutoplay = usePreferencesStore((s) => s.setEnableAutoplay);
|
||||
|
||||
const sourceOrder = usePreferencesStore((s) => s.sourceOrder);
|
||||
const setSourceOrder = usePreferencesStore((s) => s.setSourceOrder);
|
||||
|
||||
const account = useAuthStore((s) => s.account);
|
||||
const updateProfile = useAuthStore((s) => s.setAccountProfile);
|
||||
const updateDeviceName = useAuthStore((s) => s.updateDeviceName);
|
||||
|
@ -148,6 +152,7 @@ export function SettingsPage() {
|
|||
account?.profile,
|
||||
enableThumbnails,
|
||||
enableAutoplay,
|
||||
sourceOrder,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -201,6 +206,7 @@ export function SettingsPage() {
|
|||
|
||||
setEnableThumbnails(state.enableThumbnails.state);
|
||||
setEnableAutoplay(state.enableAutoplay.state);
|
||||
setSourceOrder(state.sourceOrder.state);
|
||||
setAppLanguage(state.appLanguage.state);
|
||||
setTheme(state.theme.state);
|
||||
setSubStyling(state.subtitleStyling.state);
|
||||
|
@ -227,6 +233,7 @@ export function SettingsPage() {
|
|||
setEnableThumbnails,
|
||||
state,
|
||||
setEnableAutoplay,
|
||||
setSourceOrder,
|
||||
setAppLanguage,
|
||||
setTheme,
|
||||
setSubStyling,
|
||||
|
@ -274,6 +281,14 @@ export function SettingsPage() {
|
|||
setEnableThumbnails={state.enableThumbnails.set}
|
||||
enableAutoplay={state.enableAutoplay.state}
|
||||
setEnableAutoplay={state.enableAutoplay.set}
|
||||
sourceOrder={
|
||||
state.sourceOrder.state.length > 0
|
||||
? state.sourceOrder.state
|
||||
: getProviders()
|
||||
.listSources()
|
||||
.map((s) => s.id)
|
||||
}
|
||||
setSourceOrder={state.sourceOrder.set}
|
||||
/>
|
||||
</div>
|
||||
<div id="settings-appearance" className="mt-48">
|
||||
|
|
|
@ -4,6 +4,7 @@ import { useTranslation } from "react-i18next";
|
|||
import { Toggle } from "@/components/buttons/Toggle";
|
||||
import { FlagIcon } from "@/components/FlagIcon";
|
||||
import { Dropdown } from "@/components/form/Dropdown";
|
||||
import { DraggableList } from "@/components/form/SortableList";
|
||||
import { Heading1 } from "@/components/utils/Text";
|
||||
import { appLanguageOptions } from "@/setup/i18n";
|
||||
import { isAutoplayAllowed } from "@/utils/autoplay";
|
||||
|
@ -16,6 +17,8 @@ export function PreferencesPart(props: {
|
|||
setEnableThumbnails: (v: boolean) => void;
|
||||
enableAutoplay: boolean;
|
||||
setEnableAutoplay: (v: boolean) => void;
|
||||
sourceOrder: string[];
|
||||
setSourceOrder: (v: string[]) => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const sorted = sortLangCodes(appLanguageOptions.map((item) => item.code));
|
||||
|
@ -94,6 +97,20 @@ export function PreferencesPart(props: {
|
|||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-3">
|
||||
<p className="text-white font-bold">
|
||||
{t("settings.preferences.sourceOrder")}
|
||||
</p>
|
||||
<p className="max-w-[25rem] font-medium">
|
||||
{t("settings.preferences.sourceOrderDescription")}
|
||||
</p>
|
||||
|
||||
<DraggableList
|
||||
items={props.sourceOrder}
|
||||
setItems={props.setSourceOrder}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,26 +4,35 @@ import { immer } from "zustand/middleware/immer";
|
|||
|
||||
export interface PreferencesStore {
|
||||
enableThumbnails: boolean;
|
||||
setEnableThumbnails(v: boolean): void;
|
||||
enableAutoplay: boolean;
|
||||
sourceOrder: string[];
|
||||
|
||||
setEnableThumbnails(v: boolean): void;
|
||||
setEnableAutoplay(v: boolean): void;
|
||||
setSourceOrder(v: string[]): void;
|
||||
}
|
||||
|
||||
export const usePreferencesStore = create(
|
||||
persist(
|
||||
immer<PreferencesStore>((set) => ({
|
||||
enableThumbnails: false,
|
||||
enableAutoplay: false,
|
||||
sourceOrder: [],
|
||||
setEnableThumbnails(v) {
|
||||
set((s) => {
|
||||
s.enableThumbnails = v;
|
||||
});
|
||||
},
|
||||
enableAutoplay: false,
|
||||
setEnableAutoplay(v) {
|
||||
set((s) => {
|
||||
s.enableAutoplay = v;
|
||||
});
|
||||
},
|
||||
setSourceOrder(v) {
|
||||
set((s) => {
|
||||
s.sourceOrder = v;
|
||||
});
|
||||
},
|
||||
})),
|
||||
{
|
||||
name: "__MW::preferences",
|
||||
|
|
Loading…
Reference in a new issue