diff --git a/.eslintrc.js b/.eslintrc.js
index be19d18c..8e91e06d 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,3 +1,6 @@
+const a11yOff = Object.keys(require('eslint-plugin-jsx-a11y').rules)
+ .reduce((acc, rule) => { acc[`jsx-a11y/${rule}`] = 'off'; return acc }, {})
+
module.exports = {
extends: [
"airbnb",
@@ -24,6 +27,16 @@ module.exports = {
"react/react-in-jsx-scope": "off",
"react/require-default-props": "off",
"react/destructuring-assignment": "off",
+ "no-underscore-dangle": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "no-console": "off",
+ "@typescript-eslint/no-this-alias": "off",
+ "import/prefer-default-export": "off",
+ "@typescript-eslint/no-empty-function": "off",
+ "no-shadow": "off",
+ "@typescript-eslint/no-shadow": ["error"],
+ "no-restricted-syntax": "off",
+ "react/jsx-props-no-spreading": "off",
"react/jsx-filename-extension": [
"error",
{ extensions: [".js", ".tsx", ".jsx"] },
@@ -36,5 +49,6 @@ module.exports = {
tsx: "never",
},
],
+ ...a11yOff
},
};
diff --git a/package.json b/package.json
index 898104db..5b917ff2 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
+ "@types/react-router": "^5.1.18",
"crypto-js": "^4.0.0",
"fuse.js": "^6.4.6",
"hls.js": "^1.0.7",
@@ -23,13 +24,7 @@
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
- "lint": "eslint src/**"
- },
- "eslintConfig": {
- "extends": [
- "react-app",
- "react-app/jest"
- ]
+ "lint": "eslint --ext .tsx,.ts src"
},
"browserslist": {
"production": [
@@ -57,7 +52,7 @@
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-typescript": "^2.5.0",
"eslint-plugin-import": "^2.25.4",
- "eslint-plugin-jsx-a11y": "6.5.1",
+ "eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-react": "7.28.0",
"eslint-plugin-react-hooks": "4.3.0",
"postcss": "^8.4.6",
diff --git a/src/components/Buttons/ButtonControl.tsx b/src/components/Buttons/ButtonControl.tsx
index 449a5e03..41e67f4c 100644
--- a/src/components/Buttons/ButtonControl.tsx
+++ b/src/components/Buttons/ButtonControl.tsx
@@ -4,6 +4,14 @@ export interface ButtonControlProps {
className?: string;
}
-export function ButtonControl({ onClick, children, className }: ButtonControlProps) {
- return {children}
+export function ButtonControl({
+ onClick,
+ children,
+ className,
+}: ButtonControlProps) {
+ return (
+
+ {children}
+
+ );
}
diff --git a/src/components/Buttons/DropdownButton.tsx b/src/components/Buttons/DropdownButton.tsx
index 0b517a0a..0dbfcb71 100644
--- a/src/components/Buttons/DropdownButton.tsx
+++ b/src/components/Buttons/DropdownButton.tsx
@@ -9,7 +9,13 @@ import React, {
import { Backdrop, useBackdrop } from "components/layout/Backdrop";
import { ButtonControlProps, ButtonControl } from "./ButtonControl";
-export interface DropdownButtonProps extends ButtonControlProps {
+export interface OptionItem {
+ id: string;
+ name: string;
+ icon: Icons;
+}
+
+interface DropdownButtonProps extends ButtonControlProps {
icon: Icons;
open: boolean;
setOpen: (open: boolean) => void;
@@ -24,12 +30,6 @@ export interface OptionProps {
tabIndex?: number;
}
-export interface OptionItem {
- id: string;
- name: string;
- icon: Icons;
-}
-
function Option({ option, onClick, tabIndex }: OptionProps) {
return (
((props, ref) => {
+>((props: DropdownButtonProps, ref) => {
const [setBackdrop, backdropProps, highlightedProps] = useBackdrop();
const [delayedSelectedId, setDelayedSelectedId] = useState(
props.selectedItem
diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx
index 5875b1ad..65d47891 100644
--- a/src/components/Icon.tsx
+++ b/src/components/Icon.tsx
@@ -42,7 +42,7 @@ const iconList: Record
= {
export function Icon(props: IconProps) {
return (
);
diff --git a/src/components/SearchBar.tsx b/src/components/SearchBar.tsx
index eda3dd9f..af3948f7 100644
--- a/src/components/SearchBar.tsx
+++ b/src/components/SearchBar.tsx
@@ -4,7 +4,6 @@ import { DropdownButton } from "./buttons/DropdownButton";
import { Icons } from "./Icon";
import { TextInputControl } from "./text-inputs/TextInputControl";
-
export interface SearchBarProps {
buttonText?: string;
placeholder?: string;
@@ -30,7 +29,7 @@ export function SearchBarInput(props: SearchBarProps) {
return (
setSearch(val)}
value={props.value.searchQuery}
className="placeholder-denim-700 w-full flex-1 bg-transparent text-white focus:outline-none"
placeholder={props.placeholder}
@@ -39,9 +38,9 @@ export function SearchBarInput(props: SearchBarProps) {
setDropdownOpen(val)}
selectedItem={props.value.type}
- setSelectedItem={setType}
+ setSelectedItem={(val) => setType(val)}
options={[
{
id: MWMediaType.MOVIE,
diff --git a/src/components/layout/Backdrop.tsx b/src/components/layout/Backdrop.tsx
index eed15e7f..cc5b68f2 100644
--- a/src/components/layout/Backdrop.tsx
+++ b/src/components/layout/Backdrop.tsx
@@ -40,7 +40,7 @@ export function useBackdrop(): [
}
export function Backdrop(props: BackdropProps) {
- const clickEvent = props.onClick || ((e: MouseEvent) => {});
+ const clickEvent = props.onClick || (() => {});
const animationEvent = props.onBackdropHide || (() => {});
const [isVisible, setVisible, fadeProps] = useFade();
@@ -63,6 +63,6 @@ export function Backdrop(props: BackdropProps) {
}`}
{...fadeProps}
onClick={(e) => clickEvent(e.nativeEvent)}
- />
+ />
);
}
diff --git a/src/components/layout/ErrorBoundary.tsx b/src/components/layout/ErrorBoundary.tsx
index 54428c4a..79b06378 100644
--- a/src/components/layout/ErrorBoundary.tsx
+++ b/src/components/layout/ErrorBoundary.tsx
@@ -14,10 +14,16 @@ interface ErrorBoundaryState {
};
}
-export class ErrorBoundary extends Component<{}, ErrorBoundaryState> {
- state: ErrorBoundaryState = {
- hasError: false,
- };
+export class ErrorBoundary extends Component<
+ Record,
+ ErrorBoundaryState
+> {
+ constructor() {
+ super({});
+ this.state = {
+ hasError: false,
+ };
+ }
static getDerivedStateFromError() {
return {
@@ -50,8 +56,16 @@ export class ErrorBoundary extends Component<{}, ErrorBoundaryState> {
Whoops, it broke
- The app encountered an error and wasn't able to recover, please
- report it to the Discord server or on GitHub.
+ The app encountered an error and wasn't able to recover, please
+ report it to the{" "}
+
+ Discord server
+ {" "}
+ or on{" "}
+
+ GitHub
+
+ .
{this.state.error ? (
diff --git a/src/components/media/VideoPlayer.tsx b/src/components/media/VideoPlayer.tsx
index f9e04e5a..351d6202 100644
--- a/src/components/media/VideoPlayer.tsx
+++ b/src/components/media/VideoPlayer.tsx
@@ -2,7 +2,7 @@ import { IconPatch } from "components/buttons/IconPatch";
import { Icons } from "components/Icon";
import { Loading } from "components/layout/Loading";
import { MWMediaStream } from "providers";
-import { useEffect, useRef, useState } from "react";
+import { ReactElement, useEffect, useRef, useState } from "react";
export interface VideoPlayerProps {
source: MWMediaStream;
@@ -16,7 +16,7 @@ export function SkeletonVideoPlayer(props: { error?: boolean }) {
{props.error ? (
-
Couldn't get your stream
+
Couldn't get your stream
) : (
@@ -41,13 +41,16 @@ export function VideoPlayer(props: VideoPlayerProps) {
setErrored(false);
}, [props.source.url]);
+ let skeletonUi: null | ReactElement = null;
+ if (hasErrored) {
+ skeletonUi =
;
+ } else if (isLoading) {
+ skeletonUi =
;
+ }
+
return (
<>
- {hasErrored ? (
-
- ) : isLoading ? (
-
- ) : null}
+ {skeletonUi}
Promise>(
if (!isMounted.current) return resolve(undefined);
setSuccess(true);
resolve(v);
+ return null;
})
.catch((err) => {
if (isMounted) {
diff --git a/src/hooks/usePortableMedia.ts b/src/hooks/usePortableMedia.ts
index d2e199c3..a68eac20 100644
--- a/src/hooks/usePortableMedia.ts
+++ b/src/hooks/usePortableMedia.ts
@@ -2,6 +2,15 @@ import { MWPortableMedia } from "providers";
import { useEffect, useState } from "react";
import { useParams } from "react-router";
+export function deserializePortableMedia(media: string): MWPortableMedia {
+ return JSON.parse(atob(decodeURIComponent(media)));
+}
+
+export function serializePortableMedia(media: MWPortableMedia): string {
+ const data = encodeURIComponent(btoa(JSON.stringify(media)));
+ return data;
+}
+
export function usePortableMedia(): MWPortableMedia | undefined {
const { media } = useParams<{ media: string }>();
const [mediaObject, setMediaObject] = useState(
@@ -19,12 +28,3 @@ export function usePortableMedia(): MWPortableMedia | undefined {
return mediaObject;
}
-
-export function deserializePortableMedia(media: string): MWPortableMedia {
- return JSON.parse(atob(decodeURIComponent(media)));
-}
-
-export function serializePortableMedia(media: MWPortableMedia): string {
- const data = encodeURIComponent(btoa(JSON.stringify(media)));
- return data;
-}
diff --git a/src/providers/index.ts b/src/providers/index.ts
index 902887ee..aed45219 100644
--- a/src/providers/index.ts
+++ b/src/providers/index.ts
@@ -1,9 +1,5 @@
import { getProviderFromId } from "./methods/helpers";
-import {
- MWMedia,
- MWPortableMedia,
- MWMediaStream,
-} from "./types";
+import { MWMedia, MWPortableMedia, MWMediaStream } from "./types";
import contentCache from "./methods/contentCache";
export * from "./types";
@@ -35,7 +31,7 @@ export async function convertPortableToMedia(
if (output) return output;
const provider = getProviderFromId(portable.providerId);
- return await provider?.getMediaFromPortable(portable);
+ return provider?.getMediaFromPortable(portable);
}
/*
@@ -47,5 +43,5 @@ export async function getStream(
const provider = getProviderFromId(media.providerId);
if (!provider) return undefined;
- return await provider.getStream(media);
+ return provider.getStream(media);
}
diff --git a/src/providers/list/theflix/portableToMedia.ts b/src/providers/list/theflix/portableToMedia.ts
index 65cda77d..17e76e38 100644
--- a/src/providers/list/theflix/portableToMedia.ts
+++ b/src/providers/list/theflix/portableToMedia.ts
@@ -4,7 +4,8 @@ import { MWMediaType, MWPortableMedia } from "providers/types";
const getTheFlixUrl = (media: MWPortableMedia, params?: URLSearchParams) => {
if (media.mediaType === MWMediaType.MOVIE) {
return `https://theflix.to/movie/${media.mediaId}?${params}`;
- } if (media.mediaType === MWMediaType.SERIES) {
+ }
+ if (media.mediaType === MWMediaType.SERIES) {
return `https://theflix.to/tv-show/${media.mediaId}/season-${media.season}/episode-${media.episode}`;
}
@@ -29,7 +30,7 @@ export async function getDataFromPortableSearch(
if (media.mediaType === MWMediaType.MOVIE) {
return JSON.parse(node.innerHTML).props.pageProps.movie;
- } if (media.mediaType === MWMediaType.SERIES) {
- return JSON.parse(node.innerHTML).props.pageProps.selectedTv;
}
+ // must be series here
+ return JSON.parse(node.innerHTML).props.pageProps.selectedTv;
}
diff --git a/src/providers/list/theflix/search.ts b/src/providers/list/theflix/search.ts
index e45b3ffa..0b460be4 100644
--- a/src/providers/list/theflix/search.ts
+++ b/src/providers/list/theflix/search.ts
@@ -4,10 +4,10 @@ import { MWMediaType, MWProviderMediaResult, MWQuery } from "providers";
const getTheFlixUrl = (type: "tv-shows" | "movies", params: URLSearchParams) =>
`https://theflix.to/${type}/trending?${params}`;
-export async function searchTheFlix(query: MWQuery): Promise {
+export function searchTheFlix(query: MWQuery): Promise {
const params = new URLSearchParams();
params.append("search", query.searchQuery);
- return await fetch(
+ return fetch(
CORS_PROXY_URL +
getTheFlixUrl(
query.type === MWMediaType.MOVIE ? "movies" : "tv-shows",
@@ -30,14 +30,11 @@ export function getDataFromSearch(page: string, limit = 10): any[] {
export function turnDataIntoMedia(data: any): MWProviderMediaResult {
return {
- mediaId:
- `${data.id
- }-${
- data.name
- .replace(/[^a-z0-9]+|\s+/gim, " ")
- .trim()
- .replace(/\s+/g, "-")
- .toLowerCase()}`,
+ mediaId: `${data.id}-${data.name
+ .replace(/[^a-z0-9]+|\s+/gim, " ")
+ .trim()
+ .replace(/\s+/g, "-")
+ .toLowerCase()}`,
title: data.name,
year: new Date(data.releaseDate).getFullYear().toString(),
};
diff --git a/src/providers/methods/search.ts b/src/providers/methods/search.ts
index 1a4bd32b..8edd4edc 100644
--- a/src/providers/methods/search.ts
+++ b/src/providers/methods/search.ts
@@ -1,20 +1,25 @@
import Fuse from "fuse.js";
-import { MWMassProviderOutput, MWMedia, MWQuery, convertMediaToPortable } from "providers";
+import {
+ MWMassProviderOutput,
+ MWMedia,
+ MWQuery,
+ convertMediaToPortable,
+} from "providers";
import { SimpleCache } from "utils/cache";
import { GetProvidersForType } from "./helpers";
import contentCache from "./contentCache";
// cache
const resultCache = new SimpleCache();
-resultCache.setCompare((a,b) => a.searchQuery === b.searchQuery && a.type === b.type);
+resultCache.setCompare(
+ (a, b) => a.searchQuery === b.searchQuery && a.type === b.type
+);
resultCache.initialize();
/*
-** actually call all providers with the search query
-*/
-async function callProviders(
- query: MWQuery
-): Promise {
+ ** actually call all providers with the search query
+ */
+async function callProviders(query: MWQuery): Promise {
const allQueries = GetProvidersForType(query.type).map<
Promise<{ media: MWMedia[]; success: boolean; id: string }>
>(async (provider) => {
@@ -55,33 +60,37 @@ async function callProviders(
output.results.forEach((result: MWMedia) => {
contentCache.set(convertMediaToPortable(result), result, 60 * 60);
- })
+ });
return output;
}
/*
-** sort results based on query
-*/
-function sortResults(query: MWQuery, providerResults: MWMassProviderOutput): MWMassProviderOutput {
- const fuse = new Fuse(providerResults.results, { threshold: 0.3, keys: ["title"] });
- providerResults.results = fuse.search(query.searchQuery).map((v) => v.item);
- return providerResults;
+ ** sort results based on query
+ */
+function sortResults(
+ query: MWQuery,
+ providerResults: MWMassProviderOutput
+): MWMassProviderOutput {
+ const results: MWMassProviderOutput = { ...providerResults };
+ const fuse = new Fuse(results.results, { threshold: 0.3, keys: ["title"] });
+ results.results = fuse.search(query.searchQuery).map((v) => v.item);
+ return results;
}
/*
** Call search on all providers that matches query type
*/
export async function SearchProviders(
- query: MWQuery
+ inputQuery: MWQuery
): Promise {
// input normalisation
+ const query = { ...inputQuery };
query.searchQuery = query.searchQuery.toLowerCase().trim();
// consult cache first
let output = resultCache.get(query);
- if (!output)
- output = await callProviders(query);
+ if (!output) output = await callProviders(query);
// sort results
output = sortResults(query, output);
diff --git a/src/providers/types.ts b/src/providers/types.ts
index b4773898..7d55560d 100644
--- a/src/providers/types.ts
+++ b/src/providers/types.ts
@@ -23,7 +23,7 @@ export interface MWMediaMeta extends MWPortableMedia {
year: string;
}
-export type MWMedia = MWMediaMeta
+export type MWMedia = MWMediaMeta;
export type MWProviderMediaResult = Omit;
diff --git a/src/state/bookmark/context.tsx b/src/state/bookmark/context.tsx
index 49cf2f8b..9a63ac77 100644
--- a/src/state/bookmark/context.tsx
+++ b/src/state/bookmark/context.tsx
@@ -1,5 +1,12 @@
import { getProviderMetadata, MWMediaMeta } from "providers";
-import { createContext, ReactNode, useContext, useState } from "react";
+import {
+ createContext,
+ ReactNode,
+ useCallback,
+ useContext,
+ useMemo,
+ useState,
+} from "react";
import { BookmarkStore } from "./store";
interface BookmarkStoreData {
@@ -20,55 +27,77 @@ const BookmarkedContext = createContext({
},
});
+function getBookmarkIndexFromMedia(
+ bookmarks: MWMediaMeta[],
+ media: MWMediaMeta
+): number {
+ const a = bookmarks.findIndex(
+ (v) =>
+ v.mediaId === media.mediaId &&
+ v.providerId === media.providerId &&
+ v.episode === media.episode &&
+ v.season === media.season
+ );
+ return a;
+}
+
export function BookmarkContextProvider(props: { children: ReactNode }) {
const bookmarkLocalstorage = BookmarkStore.get();
const [bookmarkStorage, setBookmarkStore] = useState(
bookmarkLocalstorage as BookmarkStoreData
);
- function setBookmarked(data: any) {
- setBookmarkStore((old) => {
- const old2 = JSON.parse(JSON.stringify(old));
- let newData = data;
- if (data.constructor === Function) {
- newData = data(old2);
- }
- bookmarkLocalstorage.save(newData);
- return newData;
- });
- }
-
- const contextValue = {
- setItemBookmark(media: MWMediaMeta, bookmarked: boolean) {
- setBookmarked((data: BookmarkStoreData) => {
- if (bookmarked) {
- const itemIndex = getBookmarkIndexFromMedia(data.bookmarks, media);
- if (itemIndex === -1) {
- const item = {
- mediaId: media.mediaId,
- mediaType: media.mediaType,
- providerId: media.providerId,
- title: media.title,
- year: media.year,
- episode: media.episode,
- season: media.season,
- };
- data.bookmarks.push(item);
- }
- } else {
- const itemIndex = getBookmarkIndexFromMedia(data.bookmarks, media);
- if (itemIndex !== -1) {
- data.bookmarks.splice(itemIndex);
- }
+ const setBookmarked = useCallback(
+ (data: any) => {
+ setBookmarkStore((old) => {
+ const old2 = JSON.parse(JSON.stringify(old));
+ let newData = data;
+ if (data.constructor === Function) {
+ newData = data(old2);
}
- return data;
+ bookmarkLocalstorage.save(newData);
+ return newData;
});
},
- getFilteredBookmarks() {
- return bookmarkStorage.bookmarks.filter((bookmark) => getProviderMetadata(bookmark.providerId)?.enabled);
- },
- bookmarkStore: bookmarkStorage,
- };
+ [bookmarkLocalstorage, setBookmarkStore]
+ );
+
+ const contextValue = useMemo(
+ () => ({
+ setItemBookmark(media: MWMediaMeta, bookmarked: boolean) {
+ setBookmarked((data: BookmarkStoreData) => {
+ if (bookmarked) {
+ const itemIndex = getBookmarkIndexFromMedia(data.bookmarks, media);
+ if (itemIndex === -1) {
+ const item = {
+ mediaId: media.mediaId,
+ mediaType: media.mediaType,
+ providerId: media.providerId,
+ title: media.title,
+ year: media.year,
+ episode: media.episode,
+ season: media.season,
+ };
+ data.bookmarks.push(item);
+ }
+ } else {
+ const itemIndex = getBookmarkIndexFromMedia(data.bookmarks, media);
+ if (itemIndex !== -1) {
+ data.bookmarks.splice(itemIndex);
+ }
+ }
+ return data;
+ });
+ },
+ getFilteredBookmarks() {
+ return bookmarkStorage.bookmarks.filter(
+ (bookmark) => getProviderMetadata(bookmark.providerId)?.enabled
+ );
+ },
+ bookmarkStore: bookmarkStorage,
+ }),
+ [bookmarkStorage, setBookmarked]
+ );
return (
@@ -81,19 +110,6 @@ export function useBookmarkContext() {
return useContext(BookmarkedContext);
}
-function getBookmarkIndexFromMedia(
- bookmarks: MWMediaMeta[],
- media: MWMediaMeta
-): number {
- const a = bookmarks.findIndex((v) => (
- v.mediaId === media.mediaId &&
- v.providerId === media.providerId &&
- v.episode === media.episode &&
- v.season === media.season
- ));
- return a;
-}
-
export function getIfBookmarkedFromPortable(
bookmarks: MWMediaMeta[],
media: MWMediaMeta
diff --git a/src/state/watched/context.tsx b/src/state/watched/context.tsx
index 75f60ea7..07380985 100644
--- a/src/state/watched/context.tsx
+++ b/src/state/watched/context.tsx
@@ -1,5 +1,12 @@
import { MWMediaMeta, getProviderMetadata } from "providers";
-import React, { createContext, ReactNode, useContext, useState } from "react";
+import React, {
+ createContext,
+ ReactNode,
+ useCallback,
+ useContext,
+ useMemo,
+ useState,
+} from "react";
import { VideoProgressStore } from "./store";
interface WatchedStoreItem extends MWMediaMeta {
@@ -17,6 +24,19 @@ interface WatchedStoreDataWrapper {
watched: WatchedStoreData;
}
+export function getWatchedFromPortable(
+ items: WatchedStoreItem[],
+ media: MWMediaMeta
+): WatchedStoreItem | undefined {
+ return items.find(
+ (v) =>
+ v.mediaId === media.mediaId &&
+ v.providerId === media.providerId &&
+ v.episode === media.episode &&
+ v.season === media.season
+ );
+}
+
const WatchedContext = createContext({
updateProgress: () => {},
getFilteredWatched: () => [],
@@ -32,48 +52,60 @@ export function WatchedContextProvider(props: { children: ReactNode }) {
watchedLocalstorage as WatchedStoreData
);
- function setWatched(data: any) {
- setWatchedReal((old) => {
- let newData = data;
- if (data.constructor === Function) {
- newData = data(old);
- }
- watchedLocalstorage.save(newData);
- return newData;
- });
- }
-
- const contextValue = {
- updateProgress(media: MWMediaMeta, progress: number, total: number): void {
- setWatched((data: WatchedStoreData) => {
- let item = getWatchedFromPortable(data.items, media);
- if (!item) {
- item = {
- mediaId: media.mediaId,
- mediaType: media.mediaType,
- providerId: media.providerId,
- title: media.title,
- year: media.year,
- percentage: 0,
- progress: 0,
- episode: media.episode,
- season: media.season,
- };
- data.items.push(item);
+ const setWatched = useCallback(
+ (data: any) => {
+ setWatchedReal((old) => {
+ let newData = data;
+ if (data.constructor === Function) {
+ newData = data(old);
}
-
- // update actual item
- item.progress = progress;
- item.percentage = Math.round((progress / total) * 100);
-
- return data;
+ watchedLocalstorage.save(newData);
+ return newData;
});
},
- getFilteredWatched() {
- return watched.items.filter((item) => getProviderMetadata(item.providerId)?.enabled);
- },
- watched,
- };
+ [setWatchedReal, watchedLocalstorage]
+ );
+
+ const contextValue = useMemo(
+ () => ({
+ updateProgress(
+ media: MWMediaMeta,
+ progress: number,
+ total: number
+ ): void {
+ setWatched((data: WatchedStoreData) => {
+ let item = getWatchedFromPortable(data.items, media);
+ if (!item) {
+ item = {
+ mediaId: media.mediaId,
+ mediaType: media.mediaType,
+ providerId: media.providerId,
+ title: media.title,
+ year: media.year,
+ percentage: 0,
+ progress: 0,
+ episode: media.episode,
+ season: media.season,
+ };
+ data.items.push(item);
+ }
+
+ // update actual item
+ item.progress = progress;
+ item.percentage = Math.round((progress / total) * 100);
+
+ return data;
+ });
+ },
+ getFilteredWatched() {
+ return watched.items.filter(
+ (item) => getProviderMetadata(item.providerId)?.enabled
+ );
+ },
+ watched,
+ }),
+ [watched, setWatched]
+ );
return (
@@ -85,15 +117,3 @@ export function WatchedContextProvider(props: { children: ReactNode }) {
export function useWatchedContext() {
return useContext(WatchedContext);
}
-
-export function getWatchedFromPortable(
- items: WatchedStoreItem[],
- media: MWMediaMeta
-): WatchedStoreItem | undefined {
- return items.find((v) => (
- v.mediaId === media.mediaId &&
- v.providerId === media.providerId &&
- v.episode === media.episode &&
- v.season === media.season
- ));
-}
diff --git a/src/utils/storage.ts b/src/utils/storage.ts
index 136b8333..3c82baf7 100644
--- a/src/utils/storage.ts
+++ b/src/utils/storage.ts
@@ -11,7 +11,8 @@ function buildStoreObject(d: any) {
id: d.storageString,
};
- function update(this: any, obj: any) {
+ function update(this: any, obj2: any) {
+ let obj = obj2;
if (!obj) throw new Error("object to update is not an object");
// repeat until object fully updated
@@ -53,54 +54,54 @@ function buildStoreObject(d: any) {
function get(this: any) {
// get from storage api
const store = this;
- let data: any = localStorage.getItem(this.id);
+ let gottenData: any = localStorage.getItem(this.id);
// parse json if item exists
- if (data) {
+ if (gottenData) {
try {
- data = JSON.parse(data);
- if (!data.constructor) {
+ gottenData = JSON.parse(gottenData);
+ if (!gottenData.constructor) {
console.error(
`Storage item for store ${this.id} has not constructor`
);
throw new Error("storage item has no constructor");
}
- if (data.constructor !== Object) {
+ if (gottenData.constructor !== Object) {
console.error(`Storage item for store ${this.id} is not an object`);
throw new Error("storage item is not an object");
}
} catch (_) {
// if errored, set to null so it generates new one, see below
console.error(`Failed to parse storage item for store ${this.id}`);
- data = null;
+ gottenData = null;
}
}
// if item doesnt exist, generate from version init
- if (!data) {
- data = this.versions[this.currentVersion.toString()].init();
+ if (!gottenData) {
+ gottenData = this.versions[this.currentVersion.toString()].init();
}
// update the data if needed
- data = this.update(data);
+ gottenData = this.update(gottenData);
// add a save object to return value
- data.save = function save(newData: any) {
- const dataToStore = newData || data;
+ gottenData.save = function save(newData: any) {
+ const dataToStore = newData || gottenData;
localStorage.setItem(store.id, JSON.stringify(dataToStore));
};
// add instance helpers
Object.entries(d.instanceHelpers).forEach(([name, helper]: any) => {
- if (data[name] !== undefined)
+ if (gottenData[name] !== undefined)
throw new Error(
`helper name: ${name} on instance of store ${this.id} is reserved`
);
- data[name] = helper.bind(data);
+ gottenData[name] = helper.bind(gottenData);
});
// return data
- return data;
+ return gottenData;
}
// add functions to store
@@ -158,7 +159,7 @@ export function versionedStoreBuilder(): any {
? (data: any) => {
// update function, and increment version
migrate(data);
- data["--version"] = version;
+ data["--version"] = version; // eslint-disable-line no-param-reassign
return data;
}
: undefined,
@@ -176,7 +177,8 @@ export function versionedStoreBuilder(): any {
registerHelper({ name, helper, type }: any) {
// type
- if (!type) type = "instance";
+ let helperType: string = type;
+ if (!helperType) helperType = "instance";
// input checking
if (!name || name.constructor !== String) {
@@ -185,14 +187,14 @@ export function versionedStoreBuilder(): any {
if (!helper || helper.constructor !== Function) {
throw new Error("helper function is not a function");
}
- if (!["instance", "static"].includes(type)) {
+ if (!["instance", "static"].includes(helperType)) {
throw new Error("helper type must be either 'instance' or 'static'");
}
// register helper
- if (type === "instance")
+ if (helperType === "instance")
this._data.instanceHelpers[name as string] = helper;
- else if (type === "static")
+ else if (helperType === "static")
this._data.staticHelpers[name as string] = helper;
return this;
diff --git a/src/views/MediaView.tsx b/src/views/MediaView.tsx
index 24025658..2916100d 100644
--- a/src/views/MediaView.tsx
+++ b/src/views/MediaView.tsx
@@ -17,7 +17,7 @@ import {
getProviderFromId,
MWMediaProvider,
} from "providers";
-import { ReactNode, useEffect, useState } from "react";
+import { ReactElement, useEffect, useState } from "react";
import { useHistory } from "react-router-dom";
import {
getIfBookmarkedFromPortable,
@@ -57,7 +57,7 @@ function StyledMediaView(props: StyledMediaViewProps) {
<>
updateProgress(e)}
startAt={startAtTime}
/>
@@ -110,11 +110,13 @@ function MediaViewContent(props: { portable: MWPortableMedia }) {
const mediaPortable = props.portable;
const [streamUrl, setStreamUrl] = useState();
const [media, setMedia] = useState();
- const [fetchAllData, loading, error] = useLoading((mediaPortable) => {
- const streamPromise = getStream(mediaPortable);
- const mediaPromise = convertPortableToMedia(mediaPortable);
- return Promise.all([streamPromise, mediaPromise]);
- });
+ const [fetchAllData, loading, error] = useLoading(
+ (portable: MWPortableMedia) => {
+ const streamPromise = getStream(portable);
+ const mediaPromise = convertPortableToMedia(portable);
+ return Promise.all([streamPromise, mediaPromise]);
+ }
+ );
useEffect(() => {
(async () => {
@@ -127,7 +129,7 @@ function MediaViewContent(props: { portable: MWPortableMedia }) {
})();
}, [mediaPortable, setStreamUrl, fetchAllData]);
- let content: ReactNode;
+ let content: ReactElement | null = null;
if (loading) content = ;
else if (error) content = ;
else if (mediaPortable && media && streamUrl)
@@ -141,7 +143,7 @@ function MediaViewContent(props: { portable: MWPortableMedia }) {
/>
);
- return <>{content}>;
+ return content;
}
export function MediaView() {
@@ -152,11 +154,11 @@ export function MediaView() {
{
+ onClick={() =>
reactHistory.action !== "POP"
? reactHistory.goBack()
- : reactHistory.push("/");
- }}
+ : reactHistory.push("/")
+ }
direction="left"
linkText="Go back"
/>
diff --git a/src/views/SearchView.tsx b/src/views/SearchView.tsx
index 34f383fc..dd52418d 100644
--- a/src/views/SearchView.tsx
+++ b/src/views/SearchView.tsx
@@ -1,7 +1,7 @@
import { WatchedMediaCard } from "components/media/WatchedMediaCard";
import { SearchBarInput } from "components/SearchBar";
import { MWMassProviderOutput, MWQuery, SearchProviders } from "providers";
-import { useEffect, useState } from "react";
+import { useEffect, useMemo, useState } from "react";
import { ThinContainer } from "components/layout/ThinContainer";
import { SectionHeading } from "components/layout/SectionHeading";
import { Icons } from "components/Icon";
@@ -78,9 +78,9 @@ function SearchResultsView({
useEffect(() => {
async function runSearch(query: MWQuery) {
- const results = await runSearchQuery(query);
- if (!results) return;
- setResults(results);
+ const searchResults = await runSearchQuery(query);
+ if (!searchResults) return;
+ setResults(searchResults);
}
if (searchQuery.searchQuery !== "") runSearch(searchQuery);
@@ -123,53 +123,6 @@ function SearchResultsView({
);
}
-export function SearchView() {
- const [searching, setSearching] = useState(false);
- const [loading, setLoading] = useState(false);
- const [search, setSearch] = useSearchQuery();
-
- const debouncedSearch = useDebounce(search, 2000);
- useEffect(() => {
- setSearching(search.searchQuery !== "");
- setLoading(search.searchQuery !== "");
- }, [search]);
- useEffect(() => {
- setLoading(false);
- }, [debouncedSearch]);
-
- return (
- <>
-
-
- {/* input section */}
-
-
- Because watching legally is boring
-
What movie do you want to watch?
-
-
-
-
- {/* results view */}
- {loading ? (
-
- ) : searching ? (
- setSearch({ searchQuery: "" })}
- />
- ) : (
-
- )}
-
- >
- );
-}
-
function ExtraItems() {
const { getFilteredBookmarks } = useBookmarkContext();
const { getFilteredWatched } = useWatchedContext();
@@ -207,3 +160,53 @@ function ExtraItems() {
);
}
+
+export function SearchView() {
+ const [searching, setSearching] = useState(false);
+ const [loading, setLoading] = useState(false);
+ const [search, setSearch] = useSearchQuery();
+
+ const debouncedSearch = useDebounce(search, 2000);
+ useEffect(() => {
+ setSearching(search.searchQuery !== "");
+ setLoading(search.searchQuery !== "");
+ }, [search]);
+ useEffect(() => {
+ setLoading(false);
+ }, [debouncedSearch]);
+
+ const resultView = useMemo(() => {
+ if (loading) return ;
+ if (searching)
+ return (
+ setSearch({ searchQuery: "" })}
+ />
+ );
+ return ;
+ }, [loading, searching, debouncedSearch, setSearch]);
+
+ return (
+ <>
+
+
+ {/* input section */}
+
+
+ Because watching legally is boring
+
What movie do you want to watch?
+
+
+
+
+ {/* results view */}
+ {resultView}
+
+ >
+ );
+}
diff --git a/yarn.lock b/yarn.lock
index d1098ecf..6d49e8b0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1256,7 +1256,7 @@
"@eslint/eslintrc@^1.2.0":
version "1.2.0"
- resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.0.tgz#7ce1547a5c46dfe56e1e45c3c9ed18038c721c6a"
+ resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.0.tgz"
integrity sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w==
dependencies:
ajv "^6.12.4"
@@ -1999,7 +1999,7 @@
"@types/react" "*"
"@types/react-router" "*"
-"@types/react-router@*":
+"@types/react-router@*", "@types/react-router@^5.1.18":
version "5.1.18"
resolved "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.18.tgz"
integrity sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==
@@ -2100,7 +2100,7 @@
"@typescript-eslint/eslint-plugin@^5.13.0":
version "5.13.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.13.0.tgz#2809052b85911ced9c54a60dac10e515e9114497"
+ resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.13.0.tgz"
integrity sha512-vLktb2Uec81fxm/cfz2Hd6QaWOs8qdmVAZXLdOBX6JFJDhf6oDZpMzZ4/LZ6SFM/5DgDcxIMIvy3F+O9yZBuiQ==
dependencies:
"@typescript-eslint/scope-manager" "5.13.0"
@@ -2137,7 +2137,7 @@
"@typescript-eslint/parser@^5.13.0":
version "5.13.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.13.0.tgz#0394ed8f2f849273c0bf4b811994d177112ced5c"
+ resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.13.0.tgz"
integrity sha512-GdrU4GvBE29tm2RqWOM0P5QfCtgCyN4hXICj/X9ibKED16136l9ZpoJvCL5pSKtmJzA+NRDzQ312wWMejCVVfg==
dependencies:
"@typescript-eslint/scope-manager" "5.13.0"
@@ -2165,7 +2165,7 @@
"@typescript-eslint/scope-manager@5.13.0":
version "5.13.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.13.0.tgz#cf6aff61ca497cb19f0397eea8444a58f46156b6"
+ resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.13.0.tgz"
integrity sha512-T4N8UvKYDSfVYdmJq7g2IPJYCRzwtp74KyDZytkR4OL3NRupvswvmJQJ4CX5tDSurW2cvCc1Ia1qM7d0jpa7IA==
dependencies:
"@typescript-eslint/types" "5.13.0"
@@ -2182,7 +2182,7 @@
"@typescript-eslint/type-utils@5.13.0":
version "5.13.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.13.0.tgz#b0efd45c85b7bab1125c97b752cab3a86c7b615d"
+ resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.13.0.tgz"
integrity sha512-/nz7qFizaBM1SuqAKb7GLkcNn2buRdDgZraXlkhz+vUGiN1NZ9LzkA595tHHeduAiS2MsHqMNhE2zNzGdw43Yg==
dependencies:
"@typescript-eslint/utils" "5.13.0"
@@ -2196,7 +2196,7 @@
"@typescript-eslint/types@5.13.0":
version "5.13.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.13.0.tgz#da1de4ae905b1b9ff682cab0bed6b2e3be9c04e5"
+ resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.13.0.tgz"
integrity sha512-LmE/KO6DUy0nFY/OoQU0XelnmDt+V8lPQhh8MOVa7Y5k2gGRd6U9Kp3wAjhB4OHg57tUO0nOnwYQhRRyEAyOyg==
"@typescript-eslint/typescript-estree@5.11.0":
@@ -2214,7 +2214,7 @@
"@typescript-eslint/typescript-estree@5.13.0":
version "5.13.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.13.0.tgz#b37c07b748ff030a3e93d87c842714e020b78141"
+ resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.13.0.tgz"
integrity sha512-Q9cQow0DeLjnp5DuEDjLZ6JIkwGx3oYZe+BfcNuw/POhtpcxMTy18Icl6BJqTSd+3ftsrfuVb7mNHRZf7xiaNA==
dependencies:
"@typescript-eslint/types" "5.13.0"
@@ -2239,7 +2239,7 @@
"@typescript-eslint/utils@5.13.0":
version "5.13.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.13.0.tgz#2328feca700eb02837298339a2e49c46b41bd0af"
+ resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.13.0.tgz"
integrity sha512-+9oHlPWYNl6AwwoEt5TQryEHwiKRVjz7Vk6kaBeD3/kwHE5YqTGHtm/JZY8Bo9ITOeKutFaXnBlMgSATMJALUQ==
dependencies:
"@types/json-schema" "^7.0.9"
@@ -2259,7 +2259,7 @@
"@typescript-eslint/visitor-keys@5.13.0":
version "5.13.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.13.0.tgz#f45ff55bcce16403b221ac9240fbeeae4764f0fd"
+ resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.13.0.tgz"
integrity sha512-HLKEAS/qA1V7d9EzcpLFykTePmOQqOFim8oCvhY3pZgQ8Hi38hYpHd9e5GN6nQBFQNecNhws5wkS9Y5XIO0s/g==
dependencies:
"@typescript-eslint/types" "5.13.0"
@@ -4051,7 +4051,7 @@ escodegen@^2.0.0:
eslint-config-airbnb-base@^15.0.0:
version "15.0.0"
- resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz#6b09add90ac79c2f8d723a2580e07f3925afd236"
+ resolved "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz"
integrity sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==
dependencies:
confusing-browser-globals "^1.0.10"
@@ -4061,7 +4061,7 @@ eslint-config-airbnb-base@^15.0.0:
eslint-config-airbnb@19.0.4:
version "19.0.4"
- resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz#84d4c3490ad70a0ffa571138ebcdea6ab085fdc3"
+ resolved "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz"
integrity sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==
dependencies:
eslint-config-airbnb-base "^15.0.0"
@@ -4070,7 +4070,7 @@ eslint-config-airbnb@19.0.4:
eslint-config-prettier@^8.5.0:
version "8.5.0"
- resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1"
+ resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz"
integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==
eslint-config-react-app@^7.0.0:
@@ -4103,7 +4103,7 @@ eslint-import-resolver-node@^0.3.6:
eslint-import-resolver-typescript@^2.5.0:
version "2.5.0"
- resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.5.0.tgz#07661966b272d14ba97f597b51e1a588f9722f0a"
+ resolved "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.5.0.tgz"
integrity sha512-qZ6e5CFr+I7K4VVhQu3M/9xGv9/YmwsEXrsm3nimw8vWaVHRDrQRp26BgCypTxBp3vUp4o5aVEJRiy0F2DFddQ==
dependencies:
debug "^4.3.1"
@@ -4128,7 +4128,7 @@ eslint-plugin-flowtype@^8.0.3:
lodash "^4.17.21"
string-natural-compare "^3.0.1"
-eslint-plugin-import@^2.25.3:
+eslint-plugin-import@^2.25.3, eslint-plugin-import@^2.25.4:
version "2.25.4"
resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz"
integrity sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==
@@ -4147,25 +4147,6 @@ eslint-plugin-import@^2.25.3:
resolve "^1.20.0"
tsconfig-paths "^3.12.0"
-eslint-plugin-import@^2.25.4:
- version "2.25.4"
- resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz#322f3f916a4e9e991ac7af32032c25ce313209f1"
- integrity sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==
- dependencies:
- array-includes "^3.1.4"
- array.prototype.flat "^1.2.5"
- debug "^2.6.9"
- doctrine "^2.1.0"
- eslint-import-resolver-node "^0.3.6"
- eslint-module-utils "^2.7.2"
- has "^1.0.3"
- is-core-module "^2.8.0"
- is-glob "^4.0.3"
- minimatch "^3.0.4"
- object.values "^1.1.5"
- resolve "^1.20.0"
- tsconfig-paths "^3.12.0"
-
eslint-plugin-jest@^25.3.0:
version "25.7.0"
resolved "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz"
@@ -4173,9 +4154,9 @@ eslint-plugin-jest@^25.3.0:
dependencies:
"@typescript-eslint/experimental-utils" "^5.0.0"
-eslint-plugin-jsx-a11y@6.5.1, eslint-plugin-jsx-a11y@^6.5.1:
+eslint-plugin-jsx-a11y@^6.5.1:
version "6.5.1"
- resolved "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz#cdbf2df901040ca140b6ec14715c988889c2a6d8"
integrity sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==
dependencies:
"@babel/runtime" "^7.16.3"
@@ -4241,7 +4222,7 @@ eslint-scope@^7.1.0:
eslint-scope@^7.1.1:
version "7.1.1"
- resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642"
+ resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz"
integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==
dependencies:
esrecurse "^4.3.0"
@@ -4266,7 +4247,7 @@ eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.2
eslint-visitor-keys@^3.3.0:
version "3.3.0"
- resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
+ resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz"
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
eslint-webpack-plugin@^3.1.1:
@@ -4282,7 +4263,7 @@ eslint-webpack-plugin@^3.1.1:
eslint@^8.10.0:
version "8.10.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.10.0.tgz#931be395eb60f900c01658b278e05b6dae47199d"
+ resolved "https://registry.npmjs.org/eslint/-/eslint-8.10.0.tgz"
integrity sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw==
dependencies:
"@eslint/eslintrc" "^1.2.0"
@@ -4373,7 +4354,7 @@ espree@^9.2.0, espree@^9.3.0:
espree@^9.3.1:
version "9.3.1"
- resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd"
+ resolved "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz"
integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==
dependencies:
acorn "^8.7.0"
@@ -4823,7 +4804,7 @@ glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
glob@^7.1.7:
version "7.2.0"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
+ resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz"
integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
dependencies:
fs.realpath "^1.0.0"
@@ -7402,12 +7383,12 @@ prelude-ls@~1.1.2:
prettier-plugin-tailwindcss@^0.1.7:
version "0.1.7"
- resolved "https://registry.yarnpkg.com/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.1.7.tgz#f51de7b7bbabaa0724d3aff7a62957e5aa873482"
+ resolved "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.1.7.tgz"
integrity sha512-tmBr45hCLuit2Cz9Pwow0/Jl1bGivYGsfcF29O+3sKcE++ybjz9dfie565S3ZsvAeV8uYer9SRMBWDsHPly2Lg==
prettier@^2.5.1:
version "2.5.1"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a"
+ resolved "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz"
integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==
pretty-bytes@^5.3.0, pretty-bytes@^5.4.1:
@@ -7481,7 +7462,7 @@ proxy-addr@~2.0.5:
proxy-compare@2.0.2:
version "2.0.2"
- resolved "https://registry.yarnpkg.com/proxy-compare/-/proxy-compare-2.0.2.tgz#343e624d0ec399dfbe575f1d365d4fa042c9fc69"
+ resolved "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.0.2.tgz"
integrity sha512-3qUXJBariEj3eO90M3Rgqq3+/P5Efl0t/dl9g/1uVzIQmO3M+ql4hvNH3mYdu8H+1zcKv07YvL55tsY74jmH1A==
psl@^1.1.33:
@@ -7720,7 +7701,7 @@ react-side-effect@^2.1.0:
react-tracked@^1.7.6:
version "1.7.6"
- resolved "https://registry.yarnpkg.com/react-tracked/-/react-tracked-1.7.6.tgz#11bccec80acccdf5029db20171a887b8b16b7ae1"
+ resolved "https://registry.npmjs.org/react-tracked/-/react-tracked-1.7.6.tgz"
integrity sha512-yqfkqj4UZpsadBLIHnPLrc8a0SLgjKoSQrdyipfWeXvLnPl+/AV8MrqRVbNogUJsqHOo+ojlWy2PMxuZPVcPnQ==
dependencies:
proxy-compare "2.0.2"
@@ -8057,7 +8038,7 @@ saxes@^5.0.1:
scheduler@^0.20.2:
version "0.20.2"
- resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
+ resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz"
integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
dependencies:
loose-envify "^1.1.0"
@@ -8792,7 +8773,7 @@ tsconfig-paths@^3.12.0:
tsconfig-paths@^3.9.0:
version "3.13.0"
- resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.13.0.tgz#f3e9b8f6876698581d94470c03c95b3a48c0e3d7"
+ resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.13.0.tgz"
integrity sha512-nWuffZppoaYK0vQ1SQmkSsQzJoHA4s6uzdb2waRpD806x9yfq153AdVsWz4je2qZcW+pENrMQXbGQ3sMCkXuhw==
dependencies:
"@types/json5" "^0.0.29"
@@ -8868,7 +8849,7 @@ typedarray-to-buffer@^3.1.5:
typescript@^4.6.2:
version "4.6.2"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4"
+ resolved "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz"
integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==
unbox-primitive@^1.0.1:
@@ -8968,7 +8949,7 @@ uri-js@^4.2.2:
use-context-selector@1.3.9:
version "1.3.9"
- resolved "https://registry.yarnpkg.com/use-context-selector/-/use-context-selector-1.3.9.tgz#d1527393839f0d790ccdd52e28e8f353b8be6c2e"
+ resolved "https://registry.npmjs.org/use-context-selector/-/use-context-selector-1.3.9.tgz"
integrity sha512-YgzRyeFjoJXwFn2qLVAuIbV6EQ8DOuzu3SS/eiCxyAyvBhcn02jYSz8c5v22QQU3LW6Ez/Iyo62kKvS7Kdqt3A==
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: