From c0fc201d74d8e8d36d54dd0b13eac8414369c310 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Mon, 4 Dec 2023 21:55:43 +0100 Subject: [PATCH 01/12] show settings on playback error + make hls play with hlsjs if possible + latest version of provider package Co-authored-by: Jip Frijlink --- package.json | 2 +- pnpm-lock.yaml | 8 ++++---- src/pages/parts/player/PlayerPart.tsx | 5 ++++- src/utils/detectFeatures.ts | 2 ++ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 0c7a20a4..3b8da84f 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "dependencies": { "@formkit/auto-animate": "^0.7.0", "@headlessui/react": "^1.5.0", - "@movie-web/providers": "^1.1.2", + "@movie-web/providers": "^1.1.3", "@noble/hashes": "^1.3.2", "@react-spring/web": "^9.7.1", "@scure/bip39": "^1.2.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 77f1e762..0fb58410 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,8 +18,8 @@ dependencies: specifier: ^1.5.0 version: 1.7.17(react-dom@17.0.2)(react@17.0.2) '@movie-web/providers': - specifier: ^1.1.2 - version: 1.1.2 + specifier: ^1.1.3 + version: 1.1.3 '@noble/hashes': specifier: ^1.3.2 version: 1.3.2 @@ -1889,8 +1889,8 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true - /@movie-web/providers@1.1.2: - resolution: {integrity: sha512-ZPSHBoz9WFLc6bWnRAXpefE+Vf8GNJ4xuWv5gu+uNg7dNBIMCnPqeuABlNIGxpEi68Go7zYlyx6nH/GQItgweA==} + /@movie-web/providers@1.1.3: + resolution: {integrity: sha512-6oxRqoZLVWQJHkJJaS1ZqDV7/LATYJ2EY0RKHhQUho3eFP5SpcdAvElllvvaRaomVFix8ftYYuy+NHWTbFox0g==} dependencies: cheerio: 1.0.0-rc.12 crypto-js: 4.2.0 diff --git a/src/pages/parts/player/PlayerPart.tsx b/src/pages/parts/player/PlayerPart.tsx index bafd64fd..14df6f31 100644 --- a/src/pages/parts/player/PlayerPart.tsx +++ b/src/pages/parts/player/PlayerPart.tsx @@ -102,9 +102,12 @@ export function PlayerPart(props: PlayerPartProps) { - ) : null} + {status === playerStatus.PLAYBACK_ERROR || + status === playerStatus.PLAYING ? ( + + ) : null} diff --git a/src/utils/detectFeatures.ts b/src/utils/detectFeatures.ts index a82a3de3..58aa9893 100644 --- a/src/utils/detectFeatures.ts +++ b/src/utils/detectFeatures.ts @@ -1,4 +1,5 @@ import fscreen from "fscreen"; +import Hls from "hls.js"; export const isSafari = /^((?!chrome|android).)*safari/i.test( navigator.userAgent @@ -48,5 +49,6 @@ export function canWebkitPictureInPicture(): boolean { } export function canPlayHlsNatively(video: HTMLVideoElement): boolean { + if (Hls.isSupported()) return false; // no need to play natively return !!video.canPlayType("application/vnd.apple.mpegurl"); } From a74bc2257f961ab09bc674155734ef40484789ba Mon Sep 17 00:00:00 2001 From: mrjvs Date: Mon, 4 Dec 2023 23:10:06 +0100 Subject: [PATCH 02/12] new colors --- src/components/form/ColorPicker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/form/ColorPicker.tsx b/src/components/form/ColorPicker.tsx index 5836af81..6143e992 100644 --- a/src/components/form/ColorPicker.tsx +++ b/src/components/form/ColorPicker.tsx @@ -2,7 +2,7 @@ import classNames from "classnames"; import { Icon, Icons } from "../Icon"; -const colors = ["#2E65CF", "#7652DD", "#CF2E68", "#C2CF2E", "#2ECFA8"]; +const colors = ["#0A54FF", "#CF2E68", "#F9DD7F", "#7652DD", "#2ECFA8"]; export const initialColor = colors[0]; export function ColorPicker(props: { From bcb2e02b85ff0f825b8a49c1bfc6c4f9512ba2a1 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Wed, 6 Dec 2023 19:24:43 +0100 Subject: [PATCH 03/12] PWA periodic register --- src/index.tsx | 5 +---- src/setup/pwa.ts | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 src/setup/pwa.ts diff --git a/src/index.tsx b/src/index.tsx index 79daec72..ac372fee 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,3 +1,4 @@ +import "@/setup/pwa"; import "core-js/stable"; import "./stores/__old/imports"; import "@/setup/ga"; @@ -10,7 +11,6 @@ import { HelmetProvider } from "react-helmet-async"; import { useTranslation } from "react-i18next"; import { BrowserRouter, HashRouter } from "react-router-dom"; import { useAsync } from "react-use"; -import { registerSW } from "virtual:pwa-register"; import { Button } from "@/components/buttons/Button"; import { Icon, Icons } from "@/components/Icon"; @@ -40,9 +40,6 @@ if (key) { (window as any).initMW(conf().PROXY_URLS, key); } initializeChromecast(); -registerSW({ - immediate: true, -}); function LoadingScreen(props: { type: "user" | "lazy" }) { const mapping = { diff --git a/src/setup/pwa.ts b/src/setup/pwa.ts new file mode 100644 index 00000000..44b4b776 --- /dev/null +++ b/src/setup/pwa.ts @@ -0,0 +1,31 @@ +/* eslint-disable no-console */ +import { registerSW } from "virtual:pwa-register"; + +const intervalMS = 60 * 60 * 1000; + +registerSW({ + immediate: true, + onRegisteredSW(swUrl, r) { + console.log(`SW registered at: ${swUrl}`); + if (!r) return; + setInterval(async () => { + console.log(`attempting SW update`); + if (!(!r.installing && navigator)) return; + + if ("connection" in navigator && !navigator.onLine) return; + + const resp = await fetch(swUrl, { + cache: "no-store", + headers: { + cache: "no-store", + "cache-control": "no-cache", + }, + }); + + if (resp?.status === 200) { + console.log(`SW update successfully triggered`); + await r.update(); + } + }, intervalMS); + }, +}); From e7d6f4559e079bb9d9045c227d3690fe8f153edc Mon Sep 17 00:00:00 2001 From: mrjvs Date: Wed, 6 Dec 2023 19:37:51 +0100 Subject: [PATCH 04/12] less PWA logs + allow main indexjs to be cached --- src/setup/pwa.ts | 4 ---- vite.config.ts | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/setup/pwa.ts b/src/setup/pwa.ts index 44b4b776..e7147ea9 100644 --- a/src/setup/pwa.ts +++ b/src/setup/pwa.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-console */ import { registerSW } from "virtual:pwa-register"; const intervalMS = 60 * 60 * 1000; @@ -6,10 +5,8 @@ const intervalMS = 60 * 60 * 1000; registerSW({ immediate: true, onRegisteredSW(swUrl, r) { - console.log(`SW registered at: ${swUrl}`); if (!r) return; setInterval(async () => { - console.log(`attempting SW update`); if (!(!r.installing && navigator)) return; if ("connection" in navigator && !navigator.onLine) return; @@ -23,7 +20,6 @@ registerSW({ }); if (resp?.status === 200) { - console.log(`SW update successfully triggered`); await r.update(); } }, intervalMS); diff --git a/vite.config.ts b/vite.config.ts index 35e32efa..4fbb2776 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -42,6 +42,7 @@ export default defineConfig(({ mode }) => { disable: process.env.VITE_PWA_ENABLED !== "yes", registerType: "autoUpdate", workbox: { + maximumFileSizeToCacheInBytes: 4000000, // 4mb globIgnores: ["**ping.txt**"] }, includeAssets: [ From 8015ec5a92a2c1c36dd9c798fcef8467b7e9a851 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Wed, 6 Dec 2023 21:06:46 +0100 Subject: [PATCH 05/12] Reset caption specific settings Co-authored-by: William Oldham --- src/components/player/hooks/useCaptions.ts | 6 +++++- src/stores/subtitles/index.ts | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/components/player/hooks/useCaptions.ts b/src/components/player/hooks/useCaptions.ts index 522b22be..ec99c4fb 100644 --- a/src/components/player/hooks/useCaptions.ts +++ b/src/components/player/hooks/useCaptions.ts @@ -7,6 +7,9 @@ import { useSubtitleStore } from "@/stores/subtitles"; export function useCaptions() { const setLanguage = useSubtitleStore((s) => s.setLanguage); const enabled = useSubtitleStore((s) => s.enabled); + const resetSubtitleSpecificSettings = useSubtitleStore( + (s) => s.resetSubtitleSpecificSettings + ); const setCaption = usePlayerStore((s) => s.setCaption); const lastSelectedLanguage = useSubtitleStore((s) => s.lastSelectedLanguage); const captionList = usePlayerStore((s) => s.captionList); @@ -21,9 +24,10 @@ export function useCaptions() { srtData, url: caption.url, }); + resetSubtitleSpecificSettings(); setLanguage(language); }, - [setLanguage, captionList, setCaption] + [setLanguage, captionList, setCaption, resetSubtitleSpecificSettings] ); const disable = useCallback(async () => { diff --git a/src/stores/subtitles/index.ts b/src/stores/subtitles/index.ts index 1652ee93..1a461b3e 100644 --- a/src/stores/subtitles/index.ts +++ b/src/stores/subtitles/index.ts @@ -34,6 +34,7 @@ export interface SubtitleStore { setOverrideCasing(enabled: boolean): void; setDelay(delay: number): void; importSubtitleLanguage(lang: string | null): void; + resetSubtitleSpecificSettings(): void; } export const useSubtitleStore = create( @@ -51,6 +52,12 @@ export const useSubtitleStore = create( backgroundOpacity: 0.5, size: 1, }, + resetSubtitleSpecificSettings() { + set((s) => { + s.delay = 0; + s.overrideCasing = false; + }); + }, updateStyling(newStyling) { set((s) => { if (newStyling.backgroundOpacity !== undefined) From cb13ca72b25d92729c07bbebe3d43634a185433c Mon Sep 17 00:00:00 2001 From: mrjvs Date: Wed, 6 Dec 2023 21:19:36 +0100 Subject: [PATCH 06/12] updatedAt on import Co-authored-by: William Oldham --- src/backend/accounts/progress.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/backend/accounts/progress.ts b/src/backend/accounts/progress.ts index a5ad5022..037e4c56 100644 --- a/src/backend/accounts/progress.ts +++ b/src/backend/accounts/progress.ts @@ -19,6 +19,7 @@ export interface ProgressInput { episodeId?: string; seasonNumber?: number; episodeNumber?: number; + updatedAt?: string; } export function progressUpdateItemToInput( @@ -60,6 +61,7 @@ export function progressMediaItemToInputs( seasonId: episode.seasonId, episodeNumber: episode.number, seasonNumber: item.seasons[episode.seasonId].number, + updatedAt: new Date(episode.updatedAt).toISOString(), })); } return [ @@ -67,6 +69,7 @@ export function progressMediaItemToInputs( duration: item.progress?.duration ?? 0, watched: item.progress?.watched ?? 0, tmdbId, + updatedAt: new Date(item.updatedAt).toISOString(), meta: { title: item.title ?? "", type: item.type ?? "", From 08f378bc72ba7729516ad91cfaa7cd43627be875 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Wed, 6 Dec 2023 21:47:36 +0100 Subject: [PATCH 07/12] new user icons + better defaults for register form Co-authored-by: William Oldham --- src/components/UserIcon.tsx | 22 +++++++++++----------- src/components/form/IconPicker.tsx | 10 +++++----- src/pages/parts/auth/AccountCreatePart.tsx | 10 +++++----- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/components/UserIcon.tsx b/src/components/UserIcon.tsx index ba90a451..a3d30421 100644 --- a/src/components/UserIcon.tsx +++ b/src/components/UserIcon.tsx @@ -3,11 +3,11 @@ import { memo } from "react"; import { Icon, Icons } from "@/components/Icon"; export enum UserIcons { - SEARCH = "search", - BOOKMARK = "bookmark", - CLOCK = "clock", - EYE_SLASH = "eyeSlash", - USER = "user", + USER_GROUP = "userGroup", + COUCH = "couch", + MOBILE = "mobile", + TICKET = "ticket", + HANDCUFFS = "handcuffs", } export interface UserIconProps { @@ -16,16 +16,16 @@ export interface UserIconProps { } const iconList: Record = { - search: ``, - bookmark: ``, - clock: ``, - eyeSlash: ``, - user: ``, + userGroup: ``, + couch: ``, + mobile: ``, + ticket: ``, + handcuffs: ``, }; export const UserIcon = memo((props: UserIconProps) => { const icon = iconList[props.icon]; - if (!icon) return ; + if (!icon) return ; return ( (UserIcons.USER); + const [colorA, setColorA] = useState(initialColor); + const [colorB, setColorB] = useState(initialColor); + const [userIcon, setUserIcon] = useState(initialIcon); const { t } = useTranslation(); const [hasDeviceError, setHasDeviceError] = useState(false); From d0dca6b853c0cbf25679aea25122b727a4399df2 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Wed, 6 Dec 2023 22:04:50 +0100 Subject: [PATCH 08/12] add structured randomized titles + make hero title wider + add final randomized titles in lang files Co-authored-by: William Oldham --- src/assets/locales/en.json | 15 ++++++++++++--- src/hooks/useRandomTranslation.ts | 17 ++++++++++++----- src/pages/parts/home/HeroPart.tsx | 2 +- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index 8d9b0b72..6e755356 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -218,9 +218,18 @@ "stopEditing": "Stop editing" }, "titles": { - "morning": ["Morning title"], - "day": ["Day title"], - "night": ["Night title"] + "morning": { + "default": "What would you like to watch this morning?", + "extra": ["I hear Before Sunrise is good"] + }, + "day": { + "default": "What would you like to watch this afternoon?", + "extra": [] + }, + "night": { + "default": "What would you like to watch tonight?", + "extra": ["Tired? I hear The Excorcist is good."] + } }, "search": { "loading": "Loading...", diff --git a/src/hooks/useRandomTranslation.ts b/src/hooks/useRandomTranslation.ts index 90c4cdc9..5602ddf8 100644 --- a/src/hooks/useRandomTranslation.ts +++ b/src/hooks/useRandomTranslation.ts @@ -1,19 +1,26 @@ import { useCallback, useMemo } from "react"; import { useTranslation } from "react-i18next"; +// 10% chance of getting a joke title +const shouldGiveJokeTitle = () => Math.floor(Math.random() * 10) === 0; + export function useRandomTranslation() { const { t } = useTranslation(); const seed = useMemo(() => Math.random(), []); const getRandomTranslation = useCallback( - (key: string) => { - const res = t(key, { returnObjects: true }); + (key: string): string => { + const shouldRandom = shouldGiveJokeTitle(); + const defaultTitle = t(`${key}.default`) ?? ""; + if (!shouldRandom) return defaultTitle; - if (Array.isArray(res)) { - return res[Math.floor(seed * res.length)]; + const keys = t(`${key}.extra`, { returnObjects: true }); + if (Array.isArray(keys)) { + if (keys.length === 0) return defaultTitle; + return keys[Math.floor(seed * keys.length)]; } - return res; + return typeof keys === "string" ? keys : defaultTitle; }, [t, seed] ); diff --git a/src/pages/parts/home/HeroPart.tsx b/src/pages/parts/home/HeroPart.tsx index ea6e1112..871a2095 100644 --- a/src/pages/parts/home/HeroPart.tsx +++ b/src/pages/parts/home/HeroPart.tsx @@ -41,7 +41,7 @@ export function HeroPart({ setIsSticky, searchParams }: HeroPartProps) {
- {title} + {title}
Date: Wed, 6 Dec 2023 22:08:53 +0100 Subject: [PATCH 09/12] Fix translation bug --- src/pages/parts/home/HeroPart.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pages/parts/home/HeroPart.tsx b/src/pages/parts/home/HeroPart.tsx index 871a2095..e40a1aa0 100644 --- a/src/pages/parts/home/HeroPart.tsx +++ b/src/pages/parts/home/HeroPart.tsx @@ -1,4 +1,5 @@ import { useCallback, useRef, useState } from "react"; +import { useTranslation } from "react-i18next"; import Sticky from "react-sticky-el"; import { SearchBarInput } from "@/components/form/SearchBar"; @@ -15,7 +16,8 @@ export interface HeroPartProps { } export function HeroPart({ setIsSticky, searchParams }: HeroPartProps) { - const { t } = useRandomTranslation(); + const { t: randomT } = useRandomTranslation(); + const { t } = useTranslation(); const [search, setSearch, setSearchUnFocus] = searchParams; const [, setShowBg] = useState(false); const bannerSize = useBannerSize(); @@ -32,7 +34,7 @@ export function HeroPart({ setIsSticky, searchParams }: HeroPartProps) { if (hour < 12) time = "morning"; else if (hour < 19) time = "day"; - const title = t(`home.titles.${time}`); + const title = randomT(`home.titles.${time}`); const inputRef = useRef(null); useSlashFocus(inputRef); @@ -56,7 +58,7 @@ export function HeroPart({ setIsSticky, searchParams }: HeroPartProps) { onChange={setSearch} value={search} onUnFocus={setSearchUnFocus} - placeholder={t("home.search.placeholder")} + placeholder={t("home.search.placeholder") ?? ""} />
From e420049097ce8755d3b166424fec56fc3c44f344 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Wed, 6 Dec 2023 22:59:58 +0100 Subject: [PATCH 10/12] Added proper FAQ body text --- src/assets/locales/en.json | 20 +++++++++++++------- src/assets/locales/pirate.json | 22 ---------------------- src/components/LinksDropdown.tsx | 5 +---- src/components/utils/Ol.tsx | 4 ++-- src/pages/About.tsx | 16 ++++++++++++---- src/setup/App.tsx | 2 +- 6 files changed, 29 insertions(+), 40 deletions(-) diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index 6e755356..b84d0804 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -378,15 +378,21 @@ } } }, - "faq": { - "title": "About us", + "about": { + "title": "About movie-web", + "description": "movie-web is a web application that searches the internet for streams. The team aims for a mostly minimalistic approach to consuming content.", + "faqTitle": "Common questions", "q1": { - "title": "1", - "body": "Body of 1" + "title": "Where does the content come from?", + "body": "movie-web does not host any content. When you click on something to watch, the internet is searched for the selected media (On the loading screen and in the 'video sources' tab you can see which source you're using). Media never gets uploaded by movie-web, everything is through this searching mechanism." }, - "how": { - "title": "1", - "body": "Body of 1" + "q2": { + "title": "Where can I request a show or movie?", + "body": "It's not possible to request a show or movie, movie-web does not manage any content. All content is viewed through sources on the internet." + }, + "q3": { + "title": "The search results display the show or movie, why can't I play it?", + "body": "Our search results are powered by The Movie Database (TMDB) and display regardless of whether our sources actually have the content." } }, "footer": { diff --git a/src/assets/locales/pirate.json b/src/assets/locales/pirate.json index bf69b1a2..b0048e82 100644 --- a/src/assets/locales/pirate.json +++ b/src/assets/locales/pirate.json @@ -53,17 +53,6 @@ "reloadPage": "Reload the page", "title": "That be an error, Captain" }, - "faq": { - "how": { - "body": "Body of 1", - "title": "1" - }, - "q1": { - "body": "Body of 1", - "title": "1" - }, - "title": "About us" - }, "footer": { "legal": { "disclaimer": "Disclaimer", @@ -104,17 +93,6 @@ "noResults": "We couldn't find anythin', arrr!", "placeholder": "What do ye want to watch?", "sectionTitle": "Searchin' results" - }, - "titles": { - "day": [ - "Day title" - ], - "morning": [ - "Morning title" - ], - "night": [ - "Night title" - ] } }, "media": { diff --git a/src/components/LinksDropdown.tsx b/src/components/LinksDropdown.tsx index fa4910ab..3063ddb4 100644 --- a/src/components/LinksDropdown.tsx +++ b/src/components/LinksDropdown.tsx @@ -139,12 +139,9 @@ export function LinksDropdown(props: { children: React.ReactNode }) { {t("navigation.menu.settings")} - + {t("navigation.menu.about")} - - {t("navigation.menu.support")} - {deviceName ? (
@@ -17,7 +17,7 @@ export function Ol(props: { items: React.ReactNode[] }) {
{i !== props.items.length - 1 ? (
- {t("faq.title")} + {t("about.title")} + {t("about.description")} + {t("about.faqTitle")}
    {t("faq.q1.body")}, + + {t("about.q1.body")} + , + + {t("about.q2.body")} + , + + {t("about.q3.body")} + , ]} /> - {t("faq.how.title")} - {t("faq.how.body")} ); diff --git a/src/setup/App.tsx b/src/setup/App.tsx index cebb464a..d532d824 100644 --- a/src/setup/App.tsx +++ b/src/setup/App.tsx @@ -92,7 +92,7 @@ function App() { - + {shouldHaveDmcaPage() ? ( From 1217bae7eeada8325a5a2c88a05872f711174bc4 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Thu, 7 Dec 2023 01:52:35 +0100 Subject: [PATCH 11/12] Add back and forth links for register and login --- src/assets/locales/en.json | 2 ++ src/components/layout/LargeCard.tsx | 17 ++++++++++++++--- src/components/text/Link.tsx | 23 +++++++++++++++++++++++ src/pages/parts/auth/LoginFormPart.tsx | 8 +++++++- src/pages/parts/auth/TrustBackendPart.tsx | 12 +++++++++--- themes/default.ts | 2 +- 6 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 src/components/text/Link.tsx diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index b84d0804..4d098125 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -2,6 +2,8 @@ "auth": { "deviceNameLabel": "Device name", "deviceNamePlaceholder": "Personal phone", + "hasAccount": "Already have an account? <0>Login here.", + "createAccount": "Dont have an account yet? <0>Create an account.", "register": { "information": { "title": "Account information", diff --git a/src/components/layout/LargeCard.tsx b/src/components/layout/LargeCard.tsx index 2266be3a..dbc010af 100644 --- a/src/components/layout/LargeCard.tsx +++ b/src/components/layout/LargeCard.tsx @@ -1,3 +1,5 @@ +import classNames from "classnames"; + export function LargeCard(props: { children: React.ReactNode; top?: React.ReactNode; @@ -36,10 +38,19 @@ export function LargeCardText(props: { ); } -export function LargeCardButtons(props: { children: React.ReactNode }) { +export function LargeCardButtons(props: { + children: React.ReactNode; + splitAlign?: boolean; +}) { return ( -
    -
    +
    +
    {props.children}
    diff --git a/src/components/text/Link.tsx b/src/components/text/Link.tsx new file mode 100644 index 00000000..0956b307 --- /dev/null +++ b/src/components/text/Link.tsx @@ -0,0 +1,23 @@ +import { ReactNode } from "react"; +import { Link as LinkRouter } from "react-router-dom"; + +export function MwLink(props: { + children?: ReactNode; + to?: string; + url?: string; + onClick?: () => void; +}) { + const isExternal = !!props.url; + const isInternal = !!props.to; + const content = ( + + {props.children} + + ); + + if (isExternal) return {content}; + if (isInternal) return {content}; + return ( + props.onClick && props.onClick()}>{content} + ); +} diff --git a/src/pages/parts/auth/LoginFormPart.tsx b/src/pages/parts/auth/LoginFormPart.tsx index 82836e74..d87f6e14 100644 --- a/src/pages/parts/auth/LoginFormPart.tsx +++ b/src/pages/parts/auth/LoginFormPart.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { useTranslation } from "react-i18next"; +import { Trans, useTranslation } from "react-i18next"; import { useAsyncFn } from "react-use"; import { verifyValidMnemonic } from "@/backend/accounts/crypto"; @@ -10,6 +10,7 @@ import { LargeCardButtons, LargeCardText, } from "@/components/layout/LargeCard"; +import { MwLink } from "@/components/text/Link"; import { AuthInputBox } from "@/components/text-inputs/AuthInputBox"; import { useAuth } from "@/hooks/auth/useAuth"; import { useBookmarkStore } from "@/stores/bookmarks"; @@ -88,6 +89,11 @@ export function LoginFormPart(props: LoginFormPartProps) { {t("auth.login.submit")} +

    + + . + +

    ); } diff --git a/src/pages/parts/auth/TrustBackendPart.tsx b/src/pages/parts/auth/TrustBackendPart.tsx index 77a88409..9118eeae 100644 --- a/src/pages/parts/auth/TrustBackendPart.tsx +++ b/src/pages/parts/auth/TrustBackendPart.tsx @@ -12,6 +12,7 @@ import { LargeCardText, } from "@/components/layout/LargeCard"; import { Loading } from "@/components/layout/Loading"; +import { MwLink } from "@/components/text/Link"; import { useBackendUrl } from "@/hooks/auth/useBackendUrl"; import { conf } from "@/setup/config"; @@ -60,16 +61,21 @@ export function TrustBackendPart(props: TrustBackendPartProps) { {cardContent}
    + - +

    + + . + +

    ); } diff --git a/themes/default.ts b/themes/default.ts index bc855bc4..4f773103 100644 --- a/themes/default.ts +++ b/themes/default.ts @@ -63,7 +63,7 @@ export const defaultTheme = { secondary: "#64647B", danger: "#F46E6E", link: "#A87FD1", - linkHover: "#A87FD1", + linkHover: "#ba8fe6", }, // search bar From 91a24607a73629c52f3dbc1639f414f36e18d518 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Thu, 7 Dec 2023 01:55:56 +0100 Subject: [PATCH 12/12] Fix randomized titles getting new title on rerender --- src/hooks/useRandomTranslation.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hooks/useRandomTranslation.ts b/src/hooks/useRandomTranslation.ts index 5602ddf8..ade39350 100644 --- a/src/hooks/useRandomTranslation.ts +++ b/src/hooks/useRandomTranslation.ts @@ -6,13 +6,13 @@ const shouldGiveJokeTitle = () => Math.floor(Math.random() * 10) === 0; export function useRandomTranslation() { const { t } = useTranslation(); + const shouldJoke = useMemo(() => shouldGiveJokeTitle(), []); const seed = useMemo(() => Math.random(), []); const getRandomTranslation = useCallback( (key: string): string => { - const shouldRandom = shouldGiveJokeTitle(); const defaultTitle = t(`${key}.default`) ?? ""; - if (!shouldRandom) return defaultTitle; + if (!shouldJoke) return defaultTitle; const keys = t(`${key}.extra`, { returnObjects: true }); if (Array.isArray(keys)) { @@ -22,7 +22,7 @@ export function useRandomTranslation() { return typeof keys === "string" ? keys : defaultTitle; }, - [t, seed] + [t, seed, shouldJoke] ); return { t: getRandomTranslation };