Compare commits

..

9 Commits

Author SHA1 Message Date
Jorrin
f3dd80f42b
Merge pull request #1150 from movie-web/fix/#962
decrease amount of margin of edit button on small screens
2024-04-22 22:45:07 +02:00
William Oldham
cfc74dfa78
Merge branch 'dev' into fix/#962 2024-04-22 21:15:23 +01:00
William Oldham
1a3144a872
Merge pull request #1153 from movie-web/feature/#754
Improve how to change seasons
2024-04-22 21:14:09 +01:00
Jorrin
ae81832037 improve how to change seasons 2024-04-22 20:26:54 +02:00
Jorrin
3da8955607 decrease amount of margin on small screens 2024-04-22 19:12:18 +02:00
William Oldham
9bd5f30f40
Merge pull request #1140 from movie-web/fix/#1118
fix tmdb 404 request
2024-04-20 10:37:58 +01:00
Jorrin
0a15bb2023 consistent returns 2024-04-20 11:36:38 +02:00
Jorrin
cfa3cfd072 check for undefined 2024-04-19 19:28:49 +02:00
Jorrin
5fbe5d1ff5 fix tmdb 404 request 2024-04-19 19:26:29 +02:00
14 changed files with 55 additions and 313 deletions

View File

@ -26,9 +26,6 @@
] ]
}, },
"dependencies": { "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", "@formkit/auto-animate": "^0.8.1",
"@headlessui/react": "^1.7.17", "@headlessui/react": "^1.7.17",
"@ladjs/country-language": "^1.0.3", "@ladjs/country-language": "^1.0.3",

103
pnpm-lock.yaml generated
View File

@ -12,15 +12,6 @@ overrides:
rollup: npm:@rollup/wasm-node rollup: npm:@rollup/wasm-node
dependencies: 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': '@formkit/auto-animate':
specifier: ^0.8.1 specifier: ^0.8.1
version: 0.8.1 version: 0.8.1
@ -283,7 +274,7 @@ devDependencies:
version: 0.5.9(prettier@3.1.1) version: 0.5.9(prettier@3.1.1)
rollup-plugin-visualizer: rollup-plugin-visualizer:
specifier: ^5.11.0 specifier: ^5.11.0
version: 5.11.0(@rollup/wasm-node@4.14.3) version: 5.11.0(@rollup/wasm-node@4.14.2)
tailwind-scrollbar: tailwind-scrollbar:
specifier: ^3.0.5 specifier: ^3.0.5
version: 3.0.5(tailwindcss@3.4.0) version: 3.0.5(tailwindcss@3.4.0)
@ -2697,49 +2688,6 @@ packages:
to-fast-properties: 2.0.0 to-fast-properties: 2.0.0
dev: true 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: /@esbuild/aix-ppc64@0.19.10:
resolution: {integrity: sha512-Q+mk96KJ+FZ30h9fsJl+67IjNJm3x2eX+GBWGmocAKgzp27cowCOOqSdscX80s0SpdFXZnIv/+1xD1EctFx96Q==} resolution: {integrity: sha512-Q+mk96KJ+FZ30h9fsJl+67IjNJm3x2eX+GBWGmocAKgzp27cowCOOqSdscX80s0SpdFXZnIv/+1xD1EctFx96Q==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -3227,7 +3175,7 @@ packages:
engines: {node: '>=14.0.0'} engines: {node: '>=14.0.0'}
dev: false dev: false
/@rollup/plugin-babel@5.3.1(@babel/core@7.24.3)(@rollup/wasm-node@4.14.3): /@rollup/plugin-babel@5.3.1(@babel/core@7.24.3)(@rollup/wasm-node@4.14.2):
resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==} resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==}
engines: {node: '>= 10.0.0'} engines: {node: '>= 10.0.0'}
peerDependencies: peerDependencies:
@ -3240,36 +3188,36 @@ packages:
dependencies: dependencies:
'@babel/core': 7.24.3 '@babel/core': 7.24.3
'@babel/helper-module-imports': 7.24.3 '@babel/helper-module-imports': 7.24.3
'@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.14.3) '@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.14.2)
rollup: /@rollup/wasm-node@4.14.3 rollup: /@rollup/wasm-node@4.14.2
dev: true dev: true
/@rollup/plugin-node-resolve@11.2.1(@rollup/wasm-node@4.14.3): /@rollup/plugin-node-resolve@11.2.1(@rollup/wasm-node@4.14.2):
resolution: {integrity: sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==} resolution: {integrity: sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==}
engines: {node: '>= 10.0.0'} engines: {node: '>= 10.0.0'}
peerDependencies: peerDependencies:
rollup: npm:@rollup/wasm-node rollup: npm:@rollup/wasm-node
dependencies: dependencies:
'@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.14.3) '@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.14.2)
'@types/resolve': 1.17.1 '@types/resolve': 1.17.1
builtin-modules: 3.3.0 builtin-modules: 3.3.0
deepmerge: 4.3.1 deepmerge: 4.3.1
is-module: 1.0.0 is-module: 1.0.0
resolve: 1.22.8 resolve: 1.22.8
rollup: /@rollup/wasm-node@4.14.3 rollup: /@rollup/wasm-node@4.14.2
dev: true dev: true
/@rollup/plugin-replace@2.4.2(@rollup/wasm-node@4.14.3): /@rollup/plugin-replace@2.4.2(@rollup/wasm-node@4.14.2):
resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==} resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==}
peerDependencies: peerDependencies:
rollup: npm:@rollup/wasm-node rollup: npm:@rollup/wasm-node
dependencies: dependencies:
'@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.14.3) '@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.14.2)
magic-string: 0.25.9 magic-string: 0.25.9
rollup: /@rollup/wasm-node@4.14.3 rollup: /@rollup/wasm-node@4.14.2
dev: true dev: true
/@rollup/pluginutils@3.1.0(@rollup/wasm-node@4.14.3): /@rollup/pluginutils@3.1.0(@rollup/wasm-node@4.14.2):
resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==}
engines: {node: '>= 8.0.0'} engines: {node: '>= 8.0.0'}
peerDependencies: peerDependencies:
@ -3278,11 +3226,11 @@ packages:
'@types/estree': 0.0.39 '@types/estree': 0.0.39
estree-walker: 1.0.1 estree-walker: 1.0.1
picomatch: 2.3.1 picomatch: 2.3.1
rollup: /@rollup/wasm-node@4.14.3 rollup: /@rollup/wasm-node@4.14.2
dev: true dev: true
/@rollup/wasm-node@4.14.3: /@rollup/wasm-node@4.14.2:
resolution: {integrity: sha512-UyFUQV/iAu/Wt6rY6uQMYBQlfTMsynzYVIz6i7s9ySwjoG9WDNgtkK1TrazCSrUFbmuPZi2gbJm6VWdJCVw2yA==} resolution: {integrity: sha512-iwZbxtvP/0icwPWExUZWfA3A2jqQkDY38E8R5onRY2ALFmom0k7e37n9WDcJMMRcx/pdenfN8NaSohzX9LiDEQ==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'} engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true hasBin: true
dependencies: dependencies:
@ -6609,7 +6557,7 @@ packages:
'@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.6) '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.6)
'@babel/types': 7.23.6 '@babel/types': 7.23.6
kleur: 4.1.5 kleur: 4.1.5
rollup: /@rollup/wasm-node@4.14.3 rollup: /@rollup/wasm-node@4.14.2
unplugin: 1.5.1 unplugin: 1.5.1
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -7581,7 +7529,7 @@ packages:
glob: 7.2.3 glob: 7.2.3
dev: true dev: true
/rollup-plugin-terser@7.0.2(@rollup/wasm-node@4.14.3): /rollup-plugin-terser@7.0.2(@rollup/wasm-node@4.14.2):
resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==}
deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser
peerDependencies: peerDependencies:
@ -7589,12 +7537,12 @@ packages:
dependencies: dependencies:
'@babel/code-frame': 7.24.2 '@babel/code-frame': 7.24.2
jest-worker: 26.6.2 jest-worker: 26.6.2
rollup: /@rollup/wasm-node@4.14.3 rollup: /@rollup/wasm-node@4.14.2
serialize-javascript: 4.0.0 serialize-javascript: 4.0.0
terser: 5.30.0 terser: 5.30.0
dev: true dev: true
/rollup-plugin-visualizer@5.11.0(@rollup/wasm-node@4.14.3): /rollup-plugin-visualizer@5.11.0(@rollup/wasm-node@4.14.2):
resolution: {integrity: sha512-exM0Ms2SN3AgTzMeW7y46neZQcyLY7eKwWAop1ZoRTCZwyrIRdMMJ6JjToAJbML77X/9N8ZEpmXG4Z/Clb9k8g==} resolution: {integrity: sha512-exM0Ms2SN3AgTzMeW7y46neZQcyLY7eKwWAop1ZoRTCZwyrIRdMMJ6JjToAJbML77X/9N8ZEpmXG4Z/Clb9k8g==}
engines: {node: '>=14'} engines: {node: '>=14'}
hasBin: true hasBin: true
@ -7606,7 +7554,7 @@ packages:
dependencies: dependencies:
open: 8.4.2 open: 8.4.2
picomatch: 2.3.1 picomatch: 2.3.1
rollup: /@rollup/wasm-node@4.14.3 rollup: /@rollup/wasm-node@4.14.2
source-map: 0.7.4 source-map: 0.7.4
yargs: 17.7.2 yargs: 17.7.2
dev: true dev: true
@ -8744,7 +8692,7 @@ packages:
'@types/node': 20.10.5 '@types/node': 20.10.5
esbuild: 0.19.10 esbuild: 0.19.10
postcss: 8.4.32 postcss: 8.4.32
rollup: /@rollup/wasm-node@4.14.3 rollup: /@rollup/wasm-node@4.14.2
optionalDependencies: optionalDependencies:
fsevents: 2.3.3 fsevents: 2.3.3
dev: true dev: true
@ -9011,9 +8959,9 @@ packages:
'@babel/core': 7.24.3 '@babel/core': 7.24.3
'@babel/preset-env': 7.24.3(@babel/core@7.24.3) '@babel/preset-env': 7.24.3(@babel/core@7.24.3)
'@babel/runtime': 7.24.1 '@babel/runtime': 7.24.1
'@rollup/plugin-babel': 5.3.1(@babel/core@7.24.3)(@rollup/wasm-node@4.14.3) '@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.3) '@rollup/plugin-node-resolve': 11.2.1(@rollup/wasm-node@4.14.2)
'@rollup/plugin-replace': 2.4.2(@rollup/wasm-node@4.14.3) '@rollup/plugin-replace': 2.4.2(@rollup/wasm-node@4.14.2)
'@surma/rollup-plugin-off-main-thread': 2.2.3 '@surma/rollup-plugin-off-main-thread': 2.2.3
ajv: 8.12.0 ajv: 8.12.0
common-tags: 1.8.2 common-tags: 1.8.2
@ -9022,8 +8970,8 @@ packages:
glob: 7.2.3 glob: 7.2.3
lodash: 4.17.21 lodash: 4.17.21
pretty-bytes: 5.6.0 pretty-bytes: 5.6.0
rollup: /@rollup/wasm-node@4.14.3 rollup: /@rollup/wasm-node@4.14.2
rollup-plugin-terser: 7.0.2(@rollup/wasm-node@4.14.3) rollup-plugin-terser: 7.0.2(@rollup/wasm-node@4.14.2)
source-map: 0.8.0-beta.0 source-map: 0.8.0-beta.0
stringify-object: 3.3.0 stringify-object: 3.3.0
strip-comments: 2.0.1 strip-comments: 2.0.1
@ -9068,7 +9016,6 @@ packages:
/workbox-google-analytics@7.0.0: /workbox-google-analytics@7.0.0:
resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==} 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: dependencies:
workbox-background-sync: 7.0.0 workbox-background-sync: 7.0.0
workbox-core: 7.0.0 workbox-core: 7.0.0

View File

@ -278,7 +278,8 @@
"loadingError": "Error loading season", "loadingError": "Error loading season",
"loadingList": "Loading...", "loadingList": "Loading...",
"loadingTitle": "Loading...", "loadingTitle": "Loading...",
"unairedEpisodes": "One or more episodes in this season have been disabled because they haven't been aired yet." "unairedEpisodes": "One or more episodes in this season have been disabled because they haven't been aired yet.",
"seasons": "Seasons"
}, },
"playback": { "playback": {
"speedLabel": "Playback speed", "speedLabel": "Playback speed",
@ -527,8 +528,6 @@
"autoplay": "Autoplay", "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.", "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", "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. If a source is greyed out, it means it is not available on your device.",
"title": "Preferences" "title": "Preferences"
}, },
"reset": "Reset", "reset": "Reset",

View File

@ -25,11 +25,3 @@ export function getProviders() {
target: targets.BROWSER, target: targets.BROWSER,
}); });
} }
export function getAllProviders() {
return makeProviders({
fetcher: makeStandardFetcher(fetch),
target: targets.BROWSER_EXTENSION,
consistentIpForRequests: true,
});
}

View File

@ -25,7 +25,7 @@ export function EditButton(props: EditButtonProps) {
> >
<span ref={parent}> <span ref={parent}>
{props.editing ? ( {props.editing ? (
<span className="mx-4 whitespace-nowrap"> <span className="mx-2 sm:mx-4 whitespace-nowrap">
{t("home.mediaList.stopEditing")} {t("home.mediaList.stopEditing")}
</span> </span>
) : ( ) : (

View File

@ -1,97 +0,0 @@
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";
export interface Item {
id: string;
name: string;
disabled?: boolean;
}
function SortableItem(props: { item: Item }) {
const { attributes, listeners, setNodeRef, transform, transition } =
useSortable({ id: props.item.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 space-x-3 flex items-center max-w-[25rem] py-3 px-4 rounded-lg touch-none",
props.item.disabled && "opacity-50",
transform ? "cursor-grabbing" : "cursor-grab",
)}
>
<span className="flex-1 text-white font-bold">{props.item.name}</span>
{props.item.disabled && <Icon icon={Icons.WARNING} />}
<Icon icon={Icons.MENU} />
</div>
);
}
export function SortableList(props: {
items: Item[];
setItems: (items: Item[]) => 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.findIndex((item) => item.id === active.id);
const newIndex = currentItems.findIndex((item) => item.id === over.id);
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((item) => (
<SortableItem key={item.id} item={item} />
))}
</div>
</SortableContext>
</DndContext>
);
}

View File

@ -212,9 +212,16 @@ function EpisodesView({
return ( return (
<Menu.CardWithScrollable> <Menu.CardWithScrollable>
<Menu.BackLink onClick={goBack}> <Menu.BackLink
{loadingState?.value?.season.title || onClick={goBack}
t("player.menus.episodes.loadingTitle")} rightSide={
<span>
{loadingState?.value?.season.title ||
t("player.menus.episodes.loadingTitle")}
</span>
}
>
{t("player.menus.episodes.seasons")}
</Menu.BackLink> </Menu.BackLink>
{content} {content}
</Menu.CardWithScrollable> </Menu.CardWithScrollable>

View File

@ -46,10 +46,14 @@ function Button(props: {
); );
} }
function useSeasons(mediaId: string, isLastEpisode: boolean = false) { function useSeasons(
mediaId: string | undefined,
isLastEpisode: boolean = false,
) {
const state = useAsync(async () => { const state = useAsync(async () => {
if (isLastEpisode) { if (isLastEpisode) {
const data = await getMetaFromId(MWMediaType.SERIES, mediaId ?? ""); if (!mediaId) return null;
const data = await getMetaFromId(MWMediaType.SERIES, mediaId);
if (data?.meta.type !== MWMediaType.SERIES) return null; if (data?.meta.type !== MWMediaType.SERIES) return null;
return data.meta.seasons; return data.meta.seasons;
} }
@ -60,13 +64,14 @@ function useSeasons(mediaId: string, isLastEpisode: boolean = false) {
function useNextSeasonEpisode( function useNextSeasonEpisode(
nextSeason: MWSeasonMeta | undefined, nextSeason: MWSeasonMeta | undefined,
mediaId: string, mediaId: string | undefined,
) { ) {
const state = useAsync(async () => { const state = useAsync(async () => {
if (nextSeason) { if (nextSeason) {
if (!mediaId) return null;
const data = await getMetaFromId( const data = await getMetaFromId(
MWMediaType.SERIES, MWMediaType.SERIES,
mediaId ?? "", mediaId,
nextSeason?.id, nextSeason?.id,
); );
if (data?.meta.type !== MWMediaType.SERIES) return null; if (data?.meta.type !== MWMediaType.SERIES) return null;
@ -106,18 +111,17 @@ export function NextEpisodeButton(props: {
const enableAutoplay = usePreferencesStore((s) => s.enableAutoplay); const enableAutoplay = usePreferencesStore((s) => s.enableAutoplay);
const isLastEpisode = const isLastEpisode =
meta?.episode?.number === meta?.episodes?.at(-1)?.number; !meta?.episode?.number || !meta?.episodes?.at(-1)?.number
? false
: meta.episode.number === meta.episodes.at(-1)!.number;
const seasons = useSeasons(meta?.tmdbId ?? "", isLastEpisode); const seasons = useSeasons(meta?.tmdbId, isLastEpisode);
const nextSeason = seasons.value?.find( const nextSeason = seasons.value?.find(
(season) => season.number === (meta?.season?.number ?? 0) + 1, (season) => season.number === (meta?.season?.number ?? 0) + 1,
); );
const nextSeasonEpisode = useNextSeasonEpisode( const nextSeasonEpisode = useNextSeasonEpisode(nextSeason, meta?.tmdbId);
nextSeason,
meta?.tmdbId ?? "",
);
let show = false; let show = false;
const hasAutoplayed = useRef(false); const hasAutoplayed = useRef(false);

View File

@ -14,7 +14,6 @@ import {
} from "@/backend/helpers/providerApi"; } from "@/backend/helpers/providerApi";
import { getLoadbalancedProviderApiUrl } from "@/backend/providers/fetchers"; import { getLoadbalancedProviderApiUrl } from "@/backend/providers/fetchers";
import { getProviders } from "@/backend/providers/providers"; import { getProviders } from "@/backend/providers/providers";
import { usePreferencesStore } from "@/stores/preferences";
export interface ScrapingItems { export interface ScrapingItems {
id: string; id: string;
@ -157,8 +156,6 @@ export function useScrape() {
startScrape, startScrape,
} = useBaseScrape(); } = useBaseScrape();
const preferredSourceOrder = usePreferencesStore((s) => s.sourceOrder);
const startScraping = useCallback( const startScraping = useCallback(
async (media: ScrapeMedia) => { async (media: ScrapeMedia) => {
const providerApiUrl = getLoadbalancedProviderApiUrl(); const providerApiUrl = getLoadbalancedProviderApiUrl();
@ -184,7 +181,6 @@ export function useScrape() {
const providers = getProviders(); const providers = getProviders();
const output = await providers.runAll({ const output = await providers.runAll({
media, media,
sourceOrder: preferredSourceOrder,
events: { events: {
init: initEvent, init: initEvent,
start: startEvent, start: startEvent,
@ -203,7 +199,6 @@ export function useScrape() {
discoverEmbedsEvent, discoverEmbedsEvent,
getResult, getResult,
startScrape, startScrape,
preferredSourceOrder,
], ],
); );

View File

@ -52,7 +52,6 @@ export function useSettingsState(
| undefined, | undefined,
enableThumbnails: boolean, enableThumbnails: boolean,
enableAutoplay: boolean, enableAutoplay: boolean,
sourceOrder: string[],
) { ) {
const [proxyUrlsState, setProxyUrls, resetProxyUrls, proxyUrlsChanged] = const [proxyUrlsState, setProxyUrls, resetProxyUrls, proxyUrlsChanged] =
useDerived(proxyUrls); useDerived(proxyUrls);
@ -92,12 +91,6 @@ export function useSettingsState(
resetEnableAutoplay, resetEnableAutoplay,
enableAutoplayChanged, enableAutoplayChanged,
] = useDerived(enableAutoplay); ] = useDerived(enableAutoplay);
const [
sourceOrderState,
setSourceOrderState,
resetSourceOrder,
sourceOrderChanged,
] = useDerived(sourceOrder);
function reset() { function reset() {
resetTheme(); resetTheme();
@ -110,7 +103,6 @@ export function useSettingsState(
resetProfile(); resetProfile();
resetEnableThumbnails(); resetEnableThumbnails();
resetEnableAutoplay(); resetEnableAutoplay();
resetSourceOrder();
} }
const changed = const changed =
@ -122,8 +114,7 @@ export function useSettingsState(
proxyUrlsChanged || proxyUrlsChanged ||
profileChanged || profileChanged ||
enableThumbnailsChanged || enableThumbnailsChanged ||
enableAutoplayChanged || enableAutoplayChanged;
sourceOrderChanged;
return { return {
reset, reset,
@ -173,10 +164,5 @@ export function useSettingsState(
set: setEnableAutoplayState, set: setEnableAutoplayState,
changed: enableAutoplayChanged, changed: enableAutoplayChanged,
}, },
sourceOrder: {
state: sourceOrderState,
set: setSourceOrderState,
changed: sourceOrderChanged,
},
}; };
} }

View File

@ -31,10 +31,6 @@ import { SettingsSyncer } from "@/stores/subtitles/SettingsSyncer";
import { ThemeProvider } from "@/stores/theme"; import { ThemeProvider } from "@/stores/theme";
import { TurnstileProvider } from "@/stores/turnstile"; import { TurnstileProvider } from "@/stores/turnstile";
import {
extensionInfo,
isExtensionActiveCached,
} from "./backend/extension/messaging";
import { initializeChromecast } from "./setup/chromecast"; import { initializeChromecast } from "./setup/chromecast";
import { initializeOldStores } from "./stores/__old/migrations"; import { initializeOldStores } from "./stores/__old/migrations";
@ -144,15 +140,6 @@ function TheRouter(props: { children: ReactNode }) {
return <HashRouter>{props.children}</HashRouter>; return <HashRouter>{props.children}</HashRouter>;
} }
// Checks if the extension is installed
function ExtensionStatus() {
if (!isExtensionActiveCached()) {
throw extensionInfo();
}
return null;
}
const container = document.getElementById("root"); const container = document.getElementById("root");
const root = createRoot(container!); const root = createRoot(container!);
@ -162,7 +149,6 @@ root.render(
<TurnstileProvider /> <TurnstileProvider />
<HelmetProvider> <HelmetProvider>
<Suspense fallback={<LoadingScreen type="lazy" />}> <Suspense fallback={<LoadingScreen type="lazy" />}>
<ExtensionStatus />
<ThemeProvider applyGlobal> <ThemeProvider applyGlobal>
<ProgressSyncer /> <ProgressSyncer />
<BookmarkSyncer /> <BookmarkSyncer />

View File

@ -11,7 +11,6 @@ import {
import { getSessions, updateSession } from "@/backend/accounts/sessions"; import { getSessions, updateSession } from "@/backend/accounts/sessions";
import { updateSettings } from "@/backend/accounts/settings"; import { updateSettings } from "@/backend/accounts/settings";
import { editUser } from "@/backend/accounts/user"; import { editUser } from "@/backend/accounts/user";
import { getAllProviders } from "@/backend/providers/providers";
import { Button } from "@/components/buttons/Button"; import { Button } from "@/components/buttons/Button";
import { WideContainer } from "@/components/layout/WideContainer"; import { WideContainer } from "@/components/layout/WideContainer";
import { UserIcons } from "@/components/UserIcon"; import { UserIcons } from "@/components/UserIcon";
@ -126,9 +125,6 @@ export function SettingsPage() {
const enableAutoplay = usePreferencesStore((s) => s.enableAutoplay); const enableAutoplay = usePreferencesStore((s) => s.enableAutoplay);
const setEnableAutoplay = usePreferencesStore((s) => s.setEnableAutoplay); 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 account = useAuthStore((s) => s.account);
const updateProfile = useAuthStore((s) => s.setAccountProfile); const updateProfile = useAuthStore((s) => s.setAccountProfile);
const updateDeviceName = useAuthStore((s) => s.updateDeviceName); const updateDeviceName = useAuthStore((s) => s.updateDeviceName);
@ -152,25 +148,8 @@ export function SettingsPage() {
account?.profile, account?.profile,
enableThumbnails, enableThumbnails,
enableAutoplay, enableAutoplay,
sourceOrder,
); );
const availableSources = useMemo(() => {
const sources = getAllProviders().listSources();
const sourceIDs = sources.map((s) => s.id);
const stateSources = state.sourceOrder.state;
// Filter out sources that are not in `stateSources` and are in `sources`
const updatedSources = stateSources.filter((ss) => sourceIDs.includes(ss));
// Add sources from `sources` that are not in `stateSources`
const missingSources = sources
.filter((s) => !stateSources.includes(s.id))
.map((s) => s.id);
return [...updatedSources, ...missingSources];
}, [state.sourceOrder.state]);
useEffect(() => { useEffect(() => {
setPreviewTheme(activeTheme ?? "default"); setPreviewTheme(activeTheme ?? "default");
}, [setPreviewTheme, activeTheme]); }, [setPreviewTheme, activeTheme]);
@ -222,7 +201,6 @@ export function SettingsPage() {
setEnableThumbnails(state.enableThumbnails.state); setEnableThumbnails(state.enableThumbnails.state);
setEnableAutoplay(state.enableAutoplay.state); setEnableAutoplay(state.enableAutoplay.state);
setSourceOrder(state.sourceOrder.state);
setAppLanguage(state.appLanguage.state); setAppLanguage(state.appLanguage.state);
setTheme(state.theme.state); setTheme(state.theme.state);
setSubStyling(state.subtitleStyling.state); setSubStyling(state.subtitleStyling.state);
@ -249,7 +227,6 @@ export function SettingsPage() {
setEnableThumbnails, setEnableThumbnails,
state, state,
setEnableAutoplay, setEnableAutoplay,
setSourceOrder,
setAppLanguage, setAppLanguage,
setTheme, setTheme,
setSubStyling, setSubStyling,
@ -297,8 +274,6 @@ export function SettingsPage() {
setEnableThumbnails={state.enableThumbnails.set} setEnableThumbnails={state.enableThumbnails.set}
enableAutoplay={state.enableAutoplay.state} enableAutoplay={state.enableAutoplay.state}
setEnableAutoplay={state.enableAutoplay.set} setEnableAutoplay={state.enableAutoplay.set}
sourceOrder={availableSources}
setSourceOrder={state.sourceOrder.set}
/> />
</div> </div>
<div id="settings-appearance" className="mt-48"> <div id="settings-appearance" className="mt-48">

View File

@ -1,13 +1,9 @@
import classNames from "classnames"; import classNames from "classnames";
import { useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { getAllProviders, getProviders } from "@/backend/providers/providers";
import { Button } from "@/components/buttons/Button";
import { Toggle } from "@/components/buttons/Toggle"; import { Toggle } from "@/components/buttons/Toggle";
import { FlagIcon } from "@/components/FlagIcon"; import { FlagIcon } from "@/components/FlagIcon";
import { Dropdown } from "@/components/form/Dropdown"; import { Dropdown } from "@/components/form/Dropdown";
import { SortableList } from "@/components/form/SortableList";
import { Heading1 } from "@/components/utils/Text"; import { Heading1 } from "@/components/utils/Text";
import { appLanguageOptions } from "@/setup/i18n"; import { appLanguageOptions } from "@/setup/i18n";
import { isAutoplayAllowed } from "@/utils/autoplay"; import { isAutoplayAllowed } from "@/utils/autoplay";
@ -20,8 +16,6 @@ export function PreferencesPart(props: {
setEnableThumbnails: (v: boolean) => void; setEnableThumbnails: (v: boolean) => void;
enableAutoplay: boolean; enableAutoplay: boolean;
setEnableAutoplay: (v: boolean) => void; setEnableAutoplay: (v: boolean) => void;
sourceOrder: string[];
setSourceOrder: (v: string[]) => void;
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const sorted = sortLangCodes(appLanguageOptions.map((item) => item.code)); const sorted = sortLangCodes(appLanguageOptions.map((item) => item.code));
@ -40,17 +34,6 @@ export function PreferencesPart(props: {
(item) => item.id === getLocaleInfo(props.language)?.code, (item) => item.id === getLocaleInfo(props.language)?.code,
); );
const allSources = getAllProviders().listSources();
const sourceItems = useMemo(() => {
const currentDeviceSources = getProviders().listSources();
return props.sourceOrder.map((id) => ({
id,
name: allSources.find((s) => s.id === id)?.name || id,
disabled: !currentDeviceSources.find((s) => s.id === id),
}));
}, [props.sourceOrder, allSources]);
return ( return (
<div className="space-y-12"> <div className="space-y-12">
<Heading1 border>{t("settings.preferences.title")}</Heading1> <Heading1 border>{t("settings.preferences.title")}</Heading1>
@ -111,29 +94,6 @@ export function PreferencesPart(props: {
</p> </p>
</div> </div>
</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>
<SortableList
items={sourceItems}
setItems={(items) =>
props.setSourceOrder(items.map((item) => item.id))
}
/>
<Button
className="max-w-[25rem]"
theme="secondary"
onClick={() => props.setSourceOrder(allSources.map((s) => s.id))}
>
{t("settings.reset")}
</Button>
</div>
</div> </div>
); );
} }

View File

@ -4,35 +4,26 @@ import { immer } from "zustand/middleware/immer";
export interface PreferencesStore { export interface PreferencesStore {
enableThumbnails: boolean; enableThumbnails: boolean;
enableAutoplay: boolean;
sourceOrder: string[];
setEnableThumbnails(v: boolean): void; setEnableThumbnails(v: boolean): void;
enableAutoplay: boolean;
setEnableAutoplay(v: boolean): void; setEnableAutoplay(v: boolean): void;
setSourceOrder(v: string[]): void;
} }
export const usePreferencesStore = create( export const usePreferencesStore = create(
persist( persist(
immer<PreferencesStore>((set) => ({ immer<PreferencesStore>((set) => ({
enableThumbnails: false, enableThumbnails: false,
enableAutoplay: false,
sourceOrder: [],
setEnableThumbnails(v) { setEnableThumbnails(v) {
set((s) => { set((s) => {
s.enableThumbnails = v; s.enableThumbnails = v;
}); });
}, },
enableAutoplay: false,
setEnableAutoplay(v) { setEnableAutoplay(v) {
set((s) => { set((s) => {
s.enableAutoplay = v; s.enableAutoplay = v;
}); });
}, },
setSourceOrder(v) {
set((s) => {
s.sourceOrder = v;
});
},
})), })),
{ {
name: "__MW::preferences", name: "__MW::preferences",