Skip to content
Snippets Groups Projects
Verified Commit 23fcf2b4 authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Implement basic solution

parent 02ddd4a8
No related branches found
No related tags found
No related merge requests found
import {Genre} from "../Genre";
import {Title} from "../Title";
export interface GenreWithTitles {
genre: Genre,
titles: Title[],
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
import {produce} from 'immer'
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import {defaults} from 'react-sweet-state';
import App from './App';
import * as serviceWorker from './serviceWorker';
defaults.devtools = process.env.NODE_ENV !== "production";
defaults.mutator = (currentState, producer) => produce(currentState, producer)
ReactDOM.render(
<React.StrictMode>
<App/>
......
import {LocalizedData} from "../api/models/LocalizedData";
export interface Locale {
language: string,
region: string
}
export enum LocalePriority {
REGION_ONLY,
REGION_BEFORE_LOCALE,
LOCALE_BEFORE_REGION
}
function filterVersions<T extends LocalizedData>(locale: Locale, method: LocalePriority, data: T[]): T | undefined {
switch (method) {
case LocalePriority.REGION_ONLY:
return data.find((el) => {
return (el.region === locale.region);
});
case LocalePriority.REGION_BEFORE_LOCALE:
return data.sort((a, b) => (+b.languages.includes(locale.language)) - (+a.languages.includes(locale.language)))
.find((el) => el.region === locale.region);
case LocalePriority.LOCALE_BEFORE_REGION:
return data.sort((a, b) => (+(b.region === locale.region)) - (+(a.region === locale.region)))
.find((el) => el.languages.includes(locale.language));
}
}
export function selectLocaleVersion<T extends LocalizedData>(locale: Locale, method: LocalePriority, data: T[]): T | null {
return filterVersions(locale, method, data.filter(it => it.kind === "localized"))
|| data.find(it => it.kind === "primary")
|| data.find(it => it.kind === "original")
|| null;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3">
<g fill="#61DAFB">
<path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/>
<circle cx="420.9" cy="296.5" r="45.7"/>
<path d="M520.5 78.1z"/>
</g>
</svg>
export enum PlayabilityRating {
UNLIKELY = 0,
MAYBE = 1,
PROBABLY = 2,
}
import {useRef} from "react";
import {Media} from "../api/models/Media";
import {PlayabilityRating} from "./PlayabilityRating";
import {videoMimeString} from "./videoMimeString";
export const usePlayabilityRating = () => {
const mediaElement = useRef(document.createElement("video")).current;
return (media: Media) => {
switch (mediaElement.canPlayType(videoMimeString(media))) {
case "":
return PlayabilityRating.UNLIKELY;
case "maybe":
return PlayabilityRating.MAYBE;
case "probably":
return PlayabilityRating.PROBABLY;
}
}
}
import {Media} from "../api/models/Media";
export const videoMimeString = (media: Media) =>
`${media.mime}; codecs="${media.codecs.join(", ")}"`;
import {RequestError} from "./RequestError";
import {RequestErrorKind} from "./RequestErrorKind";
export class RequestClient {
private baseUrl: string
constructor(baseUrl: string) {
this.baseUrl = baseUrl;
}
protected async request<T>(path: string, headers?: RequestInit): Promise<T> {
const url = new URL(path, this.baseUrl).toString();
const response = await fetch(url, headers);
if (response.ok) {
return await response.json();
} else {
if (response.status in RequestErrorKind) {
throw new RequestError(response.statusText, response.status)
} else {
throw new RequestError(response.statusText, RequestErrorKind.UnknownError)
}
}
}
}
import {RequestErrorKind} from "./RequestErrorKind";
export class RequestError extends Error {
public kind: RequestErrorKind;
public message: string;
constructor(message: string, kind: RequestErrorKind) {
super(`RequestError ${kind}: ${message}`);
this.kind = kind;
this.message = message;
}
}
export enum RequestErrorKind {
UnknownError = 0,
BadRequest = 400,
Unauthorized = 401,
PaymentRequired = 402,
Forbidden = 403,
NotFound = 404,
MethodNotAllowed = 405,
NotAcceptable = 406,
ProxyAuthenticationRequired = 407,
RequestTimeout = 408,
Conflict = 409,
Gone = 410,
LengthRequired = 411,
PreconditionFailed = 412,
PayloadTooLarge = 413,
UnsupportedMediaType = 415,
RangeNotSatisfiable = 416,
ExpectationFailed = 417,
IAmATeapot = 418,
MisdirectedRequest = 421,
UnprocessableEntity = 422,
Locked = 423,
FailedDeependency = 424,
TooEarly = 425,
UpgradeRequired = 426,
PreconditionRequired = 428,
TooManyRequests = 429,
RequestHeaderFieldsTooLarge = 431,
UnavailableForLegalReasons = 451,
InternalServerError = 500,
NotImplemented = 501,
BadGateway = 502,
ServiceUnavailable = 503,
GatewayTimeout = 504,
HttpVersionNotSupported = 505,
VariantAlsoNegotiates = 506,
InsufficientStorage = 507,
LoopDetected = 508,
NotExtended = 510,
NetworkAuthenticationRequired = 511
}
export const sortLexicallyAsc = <T>(accessor: ((data: T) => string) = String):
(a: T, b: T) => number => (a: T, b: T) => accessor(a).localeCompare(accessor(b));
export const sortLexicallyDesc = <T>(accessor: ((data: T) => string) = String):
(a: T, b: T) => number => (a: T, b: T) => accessor(b).localeCompare(accessor(a));
export const sortNumericallyAsc = <T>(accessor: ((data: T) => number) = Number):
(a: T, b: T) => number => (a: T, b: T) => accessor(a) - accessor(b);
export const sortNumericallyDesc = <T>(accessor: ((data: T) => number) = Number):
(a: T, b: T) => number => (a: T, b: T) => accessor(b) - accessor(a);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment