Quality sorting, language selection UI for captions

Co-authored-by: mrjvs <mistrjvs@gmail.com>
This commit is contained in:
Jip Fr 2023-10-17 17:43:50 +02:00
parent 09c52d9f37
commit de885ba44d
5 changed files with 78 additions and 8 deletions

View File

@ -15,6 +15,7 @@
"core-js": "^3.29.1", "core-js": "^3.29.1",
"crypto-js": "^4.1.1", "crypto-js": "^4.1.1",
"dompurify": "^3.0.1", "dompurify": "^3.0.1",
"flag-icons": "^6.11.1",
"fscreen": "^1.2.0", "fscreen": "^1.2.0",
"fuse.js": "^6.4.6", "fuse.js": "^6.4.6",
"hls.js": "^1.0.7", "hls.js": "^1.0.7",

7
pnpm-lock.yaml generated
View File

@ -38,6 +38,9 @@ dependencies:
dompurify: dompurify:
specifier: ^3.0.1 specifier: ^3.0.1
version: 3.0.5 version: 3.0.5
flag-icons:
specifier: ^6.11.1
version: 6.11.1
fscreen: fscreen:
specifier: ^1.2.0 specifier: ^1.2.0
version: 1.2.0 version: 1.2.0
@ -3770,6 +3773,10 @@ packages:
path-exists: 4.0.0 path-exists: 4.0.0
dev: true dev: true
/flag-icons@6.11.1:
resolution: {integrity: sha512-c2UMJTFZoVQ47/sE1mb+9b5S1pi8SjXsx0MR063O31GV+O2EN4FMwMdEYSQItpien2bl9w1viLUoo2R3r6OK3g==}
dev: false
/flat-cache@3.1.0: /flat-cache@3.1.0:
resolution: {integrity: sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==} resolution: {integrity: sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==}
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}

View File

@ -1,3 +1,5 @@
import "flag-icons/css/flag-icons.min.css";
import classNames from "classnames"; import classNames from "classnames";
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
@ -141,15 +143,61 @@ function CaptionSettingsView({ id }: { id: string }) {
); );
} }
function CaptionOption(props: {
countryCode?: string;
children: React.ReactNode;
selected?: boolean;
}) {
return (
<div className="grid grid-cols-[auto,1fr,auto] items-center gap-3 rounded -ml-3 -mr-3 px-3 py-2 cursor-pointer hover:bg-video-context-border hover:bg-opacity-10">
<div>
<span
className={classNames(
"!w-8 h-6 rounded overflow-hidden bg-video-context-flagBg bg-cover bg-center block fi",
props.countryCode ? `fi-${props.countryCode}` : undefined
)}
/>
</div>
<span
className={classNames(props.selected && "text-white", "font-medium")}
>
{props.children}
</span>
{props.selected ? (
<Icon
icon={Icons.CIRCLE_CHECK}
className="text-xl text-video-context-type-accent"
/>
) : null}
</div>
);
}
function CaptionsView({ id }: { id: string }) { function CaptionsView({ id }: { id: string }) {
const router = useOverlayRouter(id); const router = useOverlayRouter(id);
return ( return (
<> <>
<Context.BackLink onClick={() => router.navigate("/captions")}> <Context.BackLink
onClick={() => router.navigate("/")}
rightSide={
<button
type="button"
onClick={() => router.navigate("/captions/settings")}
>
Customize
</button>
}
>
Captions Captions
</Context.BackLink> </Context.BackLink>
<Context.Section>Yee!</Context.Section> <Context.Section>
<CaptionOption>Off</CaptionOption>
<CaptionOption countryCode="nl" selected>
Nederlands
</CaptionOption>
<CaptionOption countryCode="gr">Idk Gibraltar of zo?</CaptionOption>
</Context.Section>
</> </>
); );
} }

View File

@ -22,6 +22,17 @@ export type SourceSliceSource =
url: string; url: string;
}; };
const qualitySorting: Record<SourceQuality, number> = {
"1080": 40,
"360": 10,
"480": 20,
"720": 30,
unknown: 0,
};
const sortedQualities: SourceQuality[] = Object.entries(qualitySorting)
.sort((a, b) => b[1] - a[1])
.map<SourceQuality>((v) => v[0] as SourceQuality);
export function selectQuality(source: SourceSliceSource): { export function selectQuality(source: SourceSliceSource): {
stream: LoadableSource; stream: LoadableSource;
quality: null | SourceQuality; quality: null | SourceQuality;
@ -32,12 +43,14 @@ export function selectQuality(source: SourceSliceSource): {
quality: null, quality: null,
}; };
if (source.type === "file") { if (source.type === "file") {
const firstQuality = Object.keys( const bestQuality = sortedQualities.find(
source.qualities (v) => source.qualities[v] && (source.qualities[v]?.url.length ?? 0) > 0
)[0] as keyof typeof source.qualities; );
const stream = source.qualities[firstQuality]; if (bestQuality) {
const stream = source.qualities[bestQuality];
if (stream) { if (stream) {
return { stream, quality: firstQuality }; return { stream, quality: bestQuality };
}
} }
} }
throw new Error("couldn't select quality"); throw new Error("couldn't select quality");

View File

@ -136,6 +136,7 @@ module.exports = {
light: "#4D79A8", light: "#4D79A8",
border: "#4F5C66", border: "#4F5C66",
buttonFocus: "#202836", buttonFocus: "#202836",
flagBg: "#202836",
type: { type: {
main: "#617A8A", main: "#617A8A",