1
0
Fork 0
mirror of https://github.com/sussy-code/smov.git synced 2024-12-20 14:37:43 +01:00

Modal is almost ready after bookmark button

This commit is contained in:
Captain Jack Sparrow 2024-07-06 22:04:32 +00:00
commit fae66c8db5
15 changed files with 1750 additions and 1479 deletions

View file

@ -16,7 +16,7 @@
## Referrers
- [Priacy Subreddit Megathread](https://www.reddit.com/r/Piracy/s/iymSloEpXn)
- [Piracy Subreddit Megathread](https://www.reddit.com/r/Piracy/s/iymSloEpXn)
- [Toon's Instances](https://erynith.github.io/movie-web-instances)
- [Sudo-Flix docs](https://sussy-code.github.io/docs)
- [Sudo-Flix Discord](https://discord.gg/r5cYshWM4G)

View file

@ -41,15 +41,15 @@
"@sozialhelden/ietf-language-tags": "^5.4.2",
"@types/node-forge": "^1.3.11",
"classnames": "^2.5.1",
"core-js": "^3.37.0",
"core-js": "^3.37.1",
"detect-browser": "^5.3.0",
"dompurify": "^3.1.1",
"flag-icons": "^7.2.1",
"dompurify": "^3.1.6",
"flag-icons": "^7.2.3",
"focus-trap-react": "^10.2.3",
"fscreen": "^1.2.0",
"fuse.js": "^7.0.0",
"hls.js": "^1.5.8",
"i18next": "^23.11.2",
"hls.js": "^1.5.13",
"i18next": "^23.11.5",
"immer": "^10.1.1",
"jwt-decode": "^4.0.0",
"lodash.isequal": "^4.5.0",
@ -62,33 +62,33 @@
"react-dom": "^18.3.1",
"react-ga4": "^2.1.0",
"react-google-recaptcha-v3": "^1.10.1",
"react-helmet-async": "^2.0.4",
"react-i18next": "^14.1.1",
"react-helmet-async": "^2.0.5",
"react-i18next": "^14.1.2",
"react-lazy-with-preload": "^2.2.1",
"react-loading-skeleton": "^3.4.0",
"react-router-dom": "^6.23.0",
"react-router-dom": "^6.24.1",
"react-sticky-el": "^2.1.0",
"react-use": "^17.5.0",
"semver": "^7.6.0",
"semver": "^7.6.2",
"slugify": "^1.6.6",
"subsrt-ts": "^2.1.2",
"zustand": "^4.5.2"
"zustand": "^4.5.4"
},
"devDependencies": {
"@babel/core": "^7.24.4",
"@babel/preset-env": "^7.24.4",
"@babel/preset-typescript": "^7.24.1",
"@rollup/wasm-node": "^4.17.0",
"@types/chromecast-caf-sender": "^1.0.9",
"@babel/core": "^7.24.7",
"@babel/preset-env": "^7.24.7",
"@babel/preset-typescript": "^7.24.7",
"@rollup/wasm-node": "^4.18.0",
"@types/chromecast-caf-sender": "^1.0.10",
"@types/crypto-js": "^4.2.2",
"@types/dompurify": "^3.0.5",
"@types/fscreen": "^1.0.4",
"@types/lodash.isequal": "^4.5.8",
"@types/lodash.merge": "^4.6.9",
"@types/lodash.throttle": "^4.1.9",
"@types/node": "^20.12.7",
"@types/node": "^20.14.10",
"@types/pako": "^2.0.3",
"@types/react": "^18.3.1",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/react-helmet": "^6.1.11",
"@types/react-lazy-load-image-component": "^1.6.4",
@ -99,7 +99,7 @@
"@types/semver": "^7.5.8",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"@vitejs/plugin-react": "^4.2.1",
"@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.19",
"cross-env": "^7.0.3",
"eslint": "^8.57.0",
@ -107,30 +107,30 @@
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-jsx-a11y": "^6.9.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "7.33.2",
"eslint-plugin-react-hooks": "4.6.0",
"glob": "^10.3.12",
"glob": "^10.4.3",
"handlebars": "^4.7.8",
"jsdom": "^23.2.0",
"postcss": "^8.4.38",
"postcss": "^8.4.39",
"postcss-rtl": "^2.0.0",
"postcss-rtlcss": "^4.0.9",
"prettier": "^3.2.5",
"prettier": "^3.3.2",
"prettier-plugin-tailwindcss": "^0.5.14",
"rollup-plugin-visualizer": "^5.12.0",
"tailwind-scrollbar": "^3.1.0",
"tailwindcss": "^3.4.3",
"tailwindcss": "^3.4.4",
"tailwindcss-themer": "^4.0.0",
"type-fest": "^4.17.0",
"typescript": "^5.4.5",
"vite": "^5.2.10",
"type-fest": "^4.21.0",
"typescript": "^5.5.3",
"vite": "^5.3.3",
"vite-plugin-checker": "^0.6.4",
"vite-plugin-package-version": "^1.1.0",
"vite-plugin-pwa": "^0.17.5",
"vite-plugin-static-copy": "^1.0.3",
"vitest": "^1.5.2",
"vite-plugin-static-copy": "^1.0.6",
"vitest": "^1.6.0",
"workbox-window": "^7.1.0"
},
"pnpm": {

File diff suppressed because it is too large Load diff

View file

@ -14,7 +14,15 @@
"body": "Резултатите от търсенето ни се поддържат от базата данни за филми (The Movie Database - TMDB) и се показват, независимо дали източниците ни реално разполагат със съдържанието.",
"title": "Резултатите от търсенето показват сериала или филма, защо не мога да го пусна?"
},
"title": "Относно sudo-flix"
"title": "Относно sudo-flix",
"q5": {
"title": "Как мога да разбера повече?",
"body": "Е, sudo-flix има акаунт в Twitter, който може да бъде намерен в долния колонтитул на тази страница, както и връзка към изходния код в Github."
},
"q4": {
"title": "Какво ще кажете за моите данни и други неща?",
"body": "Всички данни се синхронизират със sudo-бекенда, който е различен от бекенда на общността и се хоства независимо от мен, всеки може да използва и това."
}
},
"actions": {
"copied": "Копиране",
@ -58,7 +66,9 @@
"host": "Вие се свързвате към <0>{{hostname}}</0> - моля, потвърдете, че му вярвате, преди да създадете акаунт",
"no": "Върнете се назад",
"title": "Вярвате ли на този сървър?",
"yes": "Вярвам на този сървър"
"yes": "Вярвам на този сървър",
"noHostTitle": "Сървърът не е конфигуриран!",
"noHost": "Сървърът не е конфигуриран, следователно не можете да създадете акаунт"
},
"verify": {
"description": "Моля, въведете паролната фраза от по-рано, за да потвърдите, че сте я запазили, и за да създадете своя акаунт",
@ -85,7 +95,8 @@
"links": {
"discord": "Discord",
"dmca": "DMCA",
"github": "Github"
"github": "Github",
"twitter": "Twitter"
},
"tagline": "Гледайте любимите си предавания и филми с това отворено-код стрийминг приложение."
},
@ -97,7 +108,10 @@
"login": "Вход",
"pagetitle": "{{title}} - sudo-flix",
"register": "Регистрация",
"settings": "Настройки"
"settings": "Настройки",
"discover": "Открийте",
"support": "поддържа",
"onboarding": "Настройвам"
}
},
"home": {
@ -117,24 +131,61 @@
"noResults": "Не успяхме да намерим нищо!",
"placeholder": {
"default": "Какво искате да гледате?",
"extra": []
"extra": [
"За какво имаш настроение?",
"Трябва ли да изтрием историята на браузъра ви?",
"Какво искате да предавате?",
"Sudo-Flix е най-добрият сайт досега!",
"Какво е в списъка ви за гледане днес?",
"Как беше денят ти?",
"Лошото ми е, че сайтът никога не работи...",
"Не е ли sudo-flix най-добрият?",
">ᴗ<"
]
},
"sectionTitle": "Резултати от търсенето"
"sectionTitle": "Резултати от търсенето",
"empty": {
"default": "Добре дошли, намерете медии за гледане тук!",
"extra": [
"Тук няма нищо :(",
"Толкова празно...",
"Такава празнота.",
"Здравей нов потребител :3"
]
},
"discoverMore": "Открий повече",
"discover": "Открийте"
},
"titles": {
"day": {
"default": "Какво бихте искали да гледате този следобед?",
"extra": [
"Чувствате ли се авантюристично? \"Джурасик Парк\" може да бъде перфектният избор."
"Viva la sudo-flix!"
]
},
"morning": {
"default": "Какво бихте искали да гледате тази сутрин?",
"extra": ["Чух, че Before Sunrise е добър"]
"extra": [
"Viva la sudo-flix!"
]
},
"night": {
"default": "Какво бихте искали да гледате тази вечер?",
"extra": ["Изморен? Чух, че Екзорсистът е добър."]
"extra": [
"Viva la sudo-flix!"
]
},
"69": {
"default": "За нещо пикантно?",
"extra": [
"Честит 69 ден 😘!"
]
},
"420": {
"extra": [
"Честит 4/20 🥳!"
],
"default": "Какво бихте искали да гледате този 4/20?"
}
}
},
@ -143,7 +194,8 @@
"types": {
"movie": "Филм",
"show": "Сериал"
}
},
"unreleased": "Неиздавана"
},
"navigation": {
"banner": {
@ -154,14 +206,16 @@
"logout": "Излез",
"register": "Синхронизиране с облак",
"settings": "Настройки",
"support": "поддържа"
"support": "поддържа",
"discover": "Открийте"
}
},
"notFound": {
"badge": "Не е намерено",
"goHome": "Обратно към началото",
"message": "Търсихме навсякъде: под кошчетата, в килера, зад проксито, но в крайна сметка не успяхме да намерим страницата, която търсите.",
"title": "Тази страница не можа да бъде намерена"
"message": "Търсихме навсякъде: под кошчетата, в килера, зад проксито, но в крайна сметка не успяхме да намерим страницата, която търсите. (ಥ﹏ಥ)",
"title": "Тази страница не можа да бъде намерена",
"reloadButton": "Опитай пак"
},
"overlays": {
"close": "Затвори"
@ -282,5 +336,24 @@
"errorNotSupported": "Обектът медия или доставчик на медия не се поддържа."
}
}
},
"downtimeNotice": {
"badge": "Проблеми",
"goHome": "Прибирай се",
"timeFrame": "<bold>March 31th 11:00 PM - 5:00 AM EST</bold>",
"title": "Проблеми с доставчика",
"message": "sudo-flix.lol отново има проблеми с някои доставчици, ако не можете да намерите или пуснете шоу, моля, променете източника. Очаквайте тази грешка да продължи през времената по-долу."
},
"onboarding": {
"defaultConfirm": {
"cancel": "Отказ",
"confirm": "Използвайте настройките по подразбиране",
"title": "Сигурен ли си?",
"description": "Настройката по подразбиране няма най-добрите потоци и може да бъде непоносимо бавна. ( ͠° ͟ʖ ͡°)"
},
"extension": {
"back": "Върни се",
"explainer": "С помощта на разширението на браузъра можете да получите най-добрите потоци, които предлагаме. Само с проста инсталация. 👌"
}
}
}

View file

@ -180,6 +180,12 @@
"extra": [
"Glædelig 4/20 🥳!"
]
},
"69": {
"default": "Har du lyst til at \"hygge\"?",
"extra": [
"Glædelig 69-dag 😘!"
]
}
}
},
@ -456,7 +462,7 @@
"shortRemaining": "-{{timeLeft}}"
},
"turnstile": {
"description": "Bevis at du er et menneske ved at udfylde Captcha'en til højre. Dette er for at holde sudo-flix.lol sikker!",
"description": "Bevis at du er et menneske ved at udføre den hurtige opgave, det er for at holde sudo-flix sikker.",
"verifyingHumanity": "Bekræfter at du er et menneske... (^▽^)👍",
"title": "Er du en robot 🤖?",
"error": "Kunne ikke bekræfte at du er et menneske! Prøv venligst igen."
@ -544,7 +550,8 @@
"default": "Standard",
"gray": "Grå",
"red": "Rød",
"teal": "Blågrøn"
"teal": "Blågrøn",
"blck": "BLCK"
},
"title": "Udseende"
},

View file

@ -14,7 +14,15 @@
"body": "Nos résultats de recherche sont alimentés par The Movie Database (TMDB) et s'affichent indépendamment de la disponibilité réelle du contenu dans nos sources.",
"title": "Les résultats de la recherche affichent la série ou le film, pourquoi ne puis-je pas le lire ?"
},
"title": "À propos de sudo-flix"
"title": "À propos de sudo-flix",
"q4": {
"body": "La synchronisation de toutes les données se fait sur la sudo-backend, qui diffère de la backend de communauté et est hébergé indépendamment par moi. Tout le monde peut également l'utiliser.",
"title": "Qu'en est-il de mes données ?"
},
"q5": {
"body": "Sudo-flix possède un compte twitter qui peut être trouvé en bas de cette page ainsi qu'un lien vers le code source sur Github.",
"title": "Comment puis-je en savoir plus ?"
}
},
"actions": {
"copied": "Copié",
@ -87,7 +95,8 @@
"links": {
"discord": "Discord",
"dmca": "DMCA",
"github": "GitHub"
"github": "GitHub",
"twitter": "Twitter"
},
"tagline": "Regardez vos séries et films préférés avec cette application de streaming open source."
},
@ -100,7 +109,9 @@
"onboarding": "Mise en place",
"pagetitle": "{{title}} - sudo-flix",
"register": "Créer un compte",
"settings": "Paramètres"
"settings": "Paramètres",
"discover": "Découvrir",
"support": "Support"
}
},
"home": {

View file

@ -29,6 +29,8 @@ export enum Icons {
EXPAND = "expand",
COMPRESS = "compress",
VOLUME = "volume",
VOLUME_MED = "volume_med",
VOLUME_LOW = "volume_low",
VOLUME_X = "volume_x",
X = "x",
EDIT = "edit",
@ -102,7 +104,9 @@ const iconList: Record<Icons, string> = {
expand: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M32 32C14.3 32 0 46.3 0 64v96c0 17.7 14.3 32 32 32s32-14.3 32-32V96h64c17.7 0 32-14.3 32-32s-14.3-32-32-32H32zM64 352c0-17.7-14.3-32-32-32s-32 14.3-32 32v96c0 17.7 14.3 32 32 32h96c17.7 0 32-14.3 32-32s-14.3-32-32-32H64V352zM320 32c-17.7 0-32 14.3-32 32s14.3 32 32 32h64v64c0 17.7 14.3 32 32 32s32-14.3 32-32V64c0-17.7-14.3-32-32-32H320zM448 352c0-17.7-14.3-32-32-32s-32 14.3-32 32v64H320c-17.7 0-32 14.3-32 32s14.3 32 32 32h96c17.7 0 32-14.3 32-32V352z"/></svg>`,
compress: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M160 64c0-17.7-14.3-32-32-32s-32 14.3-32 32v64H32c-17.7 0-32 14.3-32 32s14.3 32 32 32h96c17.7 0 32-14.3 32-32V64zM32 320c-17.7 0-32 14.3-32 32s14.3 32 32 32H96v64c0 17.7 14.3 32 32 32s32-14.3 32-32V352c0-17.7-14.3-32-32-32H32zM352 64c0-17.7-14.3-32-32-32s-32 14.3-32 32v96c0 17.7 14.3 32 32 32h96c17.7 0 32-14.3 32-32s-14.3-32-32-32H352V64zM320 320c-17.7 0-32 14.3-32 32v96c0 17.7 14.3 32 32 32s32-14.3 32-32V384h64c17.7 0 32-14.3 32-32s-14.3-32-32-32H320z"/></svg>`,
volume: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M533.6 32.5C598.5 85.3 640 165.8 640 256s-41.5 170.8-106.4 223.5c-10.3 8.4-25.4 6.8-33.8-3.5s-6.8-25.4 3.5-33.8C557.5 398.2 592 331.2 592 256s-34.5-142.2-88.7-186.3c-10.3-8.4-11.8-23.5-3.5-33.8s23.5-11.8 33.8-3.5zM473.1 107c43.2 35.2 70.9 88.9 70.9 149s-27.7 113.8-70.9 149c-10.3 8.4-25.4 6.8-33.8-3.5s-6.8-25.4 3.5-33.8C475.3 341.3 496 301.1 496 256s-20.7-85.3-53.2-111.8c-10.3-8.4-11.8-23.5-3.5-33.8s23.5-11.8 33.8-3.5zm-60.5 74.5C434.1 199.1 448 225.9 448 256s-13.9 56.9-35.4 74.5c-10.3 8.4-25.4 6.8-33.8-3.5s-6.8-25.4 3.5-33.8C393.1 284.4 400 271 400 256s-6.9-28.4-17.7-37.3c-10.3-8.4-11.8-23.5-3.5-33.8s23.5-11.8 33.8-3.5zM301.1 34.8C312.6 40 320 51.4 320 64V448c0 12.6-7.4 24-18.9 29.2s-25 3.1-34.4-5.3L131.8 352H64c-35.3 0-64-28.7-64-64V224c0-35.3 28.7-64 64-64h67.8L266.7 40.1c9.4-8.4 22.9-10.4 34.4-5.3z"/></svg>`,
volume_x: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M301.1 34.8C312.6 40 320 51.4 320 64V448c0 12.6-7.4 24-18.9 29.2s-25 3.1-34.4-5.3L131.8 352H64c-35.3 0-64-28.7-64-64V224c0-35.3 28.7-64 64-64h67.8L266.7 40.1c9.4-8.4 22.9-10.4 34.4-5.3zM425 167l55 55 55-55c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-55 55 55 55c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-55-55-55 55c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l55-55-55-55c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0z"/></svg>`,
volume_med: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M473.1 107c43.2 35.2 70.9 88.9 70.9 149s-27.7 113.8-70.9 149c-10.3 8.4-25.4 6.8-33.8-3.5s-6.8-25.4 3.5-33.8C475.3 341.3 496 301.1 496 256s-20.7-85.3-53.2-111.8c-10.3-8.4-11.8-23.5-3.5-33.8s23.5-11.8 33.8-3.5zm-60.5 74.5C434.1 199.1 448 225.9 448 256s-13.9 56.9-35.4 74.5c-10.3 8.4-25.4 6.8-33.8-3.5s-6.8-25.4 3.5-33.8C393.1 284.4 400 271 400 256s-6.9-28.4-17.7-37.3c-10.3-8.4-11.8-23.5-3.5-33.8s23.5-11.8 33.8-3.5zM301.1 34.8C312.6 40 320 51.4 320 64V448c0 12.6-7.4 24-18.9 29.2s-25 3.1-34.4-5.3L131.8 352H64c-35.3 0-64-28.7-64-64V224c0-35.3 28.7-64 64-64h67.8L266.7 40.1c9.4-8.4 22.9-10.4 34.4-5.3z"/></svg>`,
volume_low: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M301.1 34.8C312.6 40 320 51.4 320 64V448c0 12.6-7.4 24-18.9 29.2s-25 3.1-34.4-5.3L131.8 352H64c-35.3 0-64-28.7-64-64V224c0-35.3 28.7-64 64-64h67.8L266.7 40.1c9.4-8.4 22.9-10.4 34.4-5.3zm105.5 145.2C434.1 199.1 448 225.9 448 256s-13.9 56.9-35.4 74.5c-10.3 8.4-25.4 6.8-33.8-3.5s-6.8-25.4 3.5-33.8C393.1 284.4 400 271 400 256s-6.9-28.4-17.7-37.3c-10.3-8.4-11.8-23.5-3.5-33.8s23.5-11.8 33.8-3.5z"/></svg>`,
volume_x: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M301.1 34.8C312.6 40 320 51.4 320 64V448c0 12.6-7.4 24-18.9 29.2s-25 3.1-34.4-5.3L131.8 352H64c-35.3 0-64-28.7-64-64V224c0-35.3 28.7-64 64-64h67.8L266.7 40.1c9.4-8.4 22.9-10.4 34.4-5.3zM425 167l55 55 55-55c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-55 55 55 55c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-55-55-55 55c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l55-55-55-55c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0z"/></svg>`,
x: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 320 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M310.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L160 210.7 54.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L114.7 256 9.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 301.3 265.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L205.3 256 310.6 150.6z"/></svg>`,
edit: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M362.7 19.3L314.3 67.7 444.3 197.7l48.4-48.4c25-25 25-65.5 0-90.5L453.3 19.3c-25-25-65.5-25-90.5 0zm-71 71L58.6 323.5c-10.4 10.4-18 23.3-22.2 37.4L1 481.2C-1.5 489.7 .8 498.8 7 505s15.3 8.5 23.7 6.1l120.3-35.4c14.1-4.2 27-11.8 37.4-22.2L421.7 220.3 291.7 90.3z"/></svg>`,
bookmark_outline: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M336 0h-288C21.49 0 0 21.49 0 48v431.9c0 24.7 26.79 40.08 48.12 27.64L192 423.6l143.9 83.93C357.2 519.1 384 504.6 384 479.9V48C384 21.49 362.5 0 336 0zM336 452L192 368l-144 84V54C48 50.63 50.63 48 53.1 48h276C333.4 48 336 50.63 336 54V452z"/></svg>`,

View file

@ -1,7 +1,7 @@
import classNames from "classnames";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import { To, useNavigate } from "react-router-dom";
import { base64ToBuffer, decryptData } from "@/backend/accounts/crypto";
import { UserAvatar } from "@/components/Avatar";
@ -24,8 +24,12 @@ function GoToLink(props: {
const navigate = useNavigate();
const goTo = (href: string) => {
if (href.startsWith("http")) window.open(href, "_blank");
else navigate(href);
if (href.startsWith("http")) {
window.open(href, "_blank");
} else {
window.scrollTo(0, 0);
navigate(href);
}
};
return (

View file

@ -1,5 +1,5 @@
import classNames from "classnames";
import { Link, useNavigate } from "react-router-dom";
import { Link, To, useNavigate } from "react-router-dom";
import { NoUserAvatar, UserAvatar } from "@/components/Avatar";
import { IconPatch } from "@/components/buttons/IconPatch";
@ -24,6 +24,11 @@ export function Navigation(props: NavigationProps) {
const navigate = useNavigate();
const { loggedIn } = useAuth();
const handleClick = (path: To) => {
window.scrollTo(0, 0);
navigate(path);
};
return (
<>
{/* lightbar */}
@ -79,11 +84,12 @@ export function Navigation(props: NavigationProps) {
}}
>
<div className={classNames("fixed left-0 right-0 flex items-center")}>
<div className="px-7 py-5 relative z-[60] flex flex-1 items-center justify-between">
<div className="px-7 py-3 relative z-[60] flex flex-1 items-center justify-between">
<div className="flex items-center space-x-1.5 ssm:space-x-3 pointer-events-auto">
<Link
className="block tabbable rounded-full text-xs ssm:text-base"
to="/"
onClick={() => window.scrollTo(0, 0)}
>
<BrandPill clickable header />
</Link>
@ -104,7 +110,7 @@ export function Navigation(props: NavigationProps) {
<IconPatch icon={Icons.GITHUB} clickable downsized />
</a>
<a
onClick={() => navigate("/discover")}
onClick={() => handleClick("/discover")}
rel="noreferrer"
className="text-xl text-white tabbable rounded-full"
>

View file

@ -61,7 +61,7 @@ export function EpisodeSelector({
return (
<div className="flex flex-row relative">
<div className="w-24 sm:w-96 cursor-pointer overflow-y-auto overflow-x-hidden max-h-60 z-10">
<div className="w-24 min-w-20 cursor-pointer overflow-y-auto overflow-x-hidden max-h-56 z-10 scrollbar-hide">
{seasonsData.map((season) => (
<div
key={season.season_number}
@ -79,8 +79,8 @@ export function EpisodeSelector({
</div>
))}
</div>
<div className="flex-auto mt-4 sm:mt-0 sm:ml-4 cursor-pointer overflow-x-auto overflow-y-hidden sm:overflow-y-auto sm:overflow-x-hidden max-h-60 max-w-[70vw] z-0">
<div className="flex sm:grid sm:grid-cols-3 sm:gap-2">
<div className="flex-auto sm:mt-0 sm:ml-4 cursor-pointer overflow-x-auto overflow-y-hidden sm:overflow-y-auto sm:overflow-x-hidden max-h-56 max-w-[70vw]">
<div className="flex sm:grid sm:grid-cols-3 sm:gap-2 gap-1">
{selectedSeason ? (
selectedSeason.episodes.map(
(episode: {
@ -92,11 +92,11 @@ export function EpisodeSelector({
<Flare.Base
key={episode.episode_number}
onClick={() => {
const navigateUrl = `/media/tmdb-tv-${tmdbId}-${mediaTitle}/${selectedSeason.id}/${episode.id}`;
// console.log("Navigating to:", navigateUrl);
navigate(navigateUrl);
navigate(
`/media/tmdb-tv-${tmdbId}-${mediaTitle}/${selectedSeason.id}/${episode.id}`,
);
}}
className="group cursor-pointer rounded-xl relative p-[0.65em] bg-background-main transition-colors duration-[0.28s] flex-shrink-0 w-48 sm:w-auto mr-2 sm:mr-0"
className="group cursor-pointer rounded-xl relative p-[0.6em] bg-background-secondary transition-colors duration-[0.25s] flex-shrink-0 w-44 max-h-48 sm:w-auto mr-2 sm:mr-0"
>
<Flare.Light
flareSize={300}
@ -109,10 +109,12 @@ export function EpisodeSelector({
src={`https://image.tmdb.org/t/p/w500/${episode.still_path}`}
className="w-full h-auto rounded"
/>
<p className="text-center text-[0.95em] mt-2">
<div className="text-center my-2 overflow-hidden">
<p className="text-[0.95em] overflow-ellipsis whitespace-wrap">
E{episode.episode_number}: {episode.name}
</p>
</div>
</div>
</Flare.Base>
),
)

View file

@ -60,8 +60,6 @@ function formatRuntime(runtime: number) {
export function PopupModal({
isVisible,
onClose,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
// idk just needed to add this line for commit
playingTitle,
media,
}: PopupModalProps) {
@ -171,28 +169,25 @@ export function PopupModal({
return (
<div
className="fixed inset-0 bg-black bg-opacity-40 flex justify-center items-center z-50 transition-opacity duration-100"
className="fixed inset-0 flex justify-center items-center z-50 transition-opacity duration-100"
style={{ opacity: style.opacity, visibility: style.visibility }}
>
<div
ref={modalRef}
className="rounded-xl bg-modal-background flex flex-col justify-center items-center transition-opacity duration-100 max-w-full sm:max-w-xl w-full sm:w-auto sm:h-auto overflow-y-auto p-4"
style={{ opacity: style.opacity, maxHeight: "90vh", height: "auto" }}
className="rounded-xl mx-4 min-w-[23em] overflow-x-hidden bg-modal-background flex flex-col justify-center items-center transition-opacity duration-100 sm:max-w-xl sm:w-auto sm:h-auto overflow-y-auto p-4"
style={{ opacity: style.opacity, height: "auto" }}
>
<div className="aspect-w-16 aspect-h-9 w-full sm:w-auto">
<div className="rounded-xl">
<div className="aspect-w-16 aspect-h-9 w-full sm:w-auto rounded-xl">
{data?.backdrop_path ? (
<img
src={`https://image.tmdb.org/t/p/original/${data.backdrop_path}`}
alt={media.poster ? "" : "failed to fetch :("}
className="rounded-xl object-cover w-full h-full"
className="rounded-xl object-cover"
loading="lazy"
style={{ maxHeight: "60vh" }}
/>
) : (
<Skeleton />
)}
</div>
<div className="flex pt-3 items-center gap-4">
<h1 className="relative text-xl sm:text-2xl whitespace-normal font-bold text-white">
{data?.title || data?.name ? (
@ -262,22 +257,24 @@ export function PopupModal({
</span>
))}
</div>
<div className="flex flex-row gap-3 flex-wrap">
{data?.genres && data.genres.length > 0
? data.genres.map((genre: { name: string }) => (
<div key={genre.name} className="inline-block">
<div className="px-2 py-1 bg-mediaCard-hoverBackground rounded hover:bg-search-background cursor-default duration-200 transition-colors transform hover:scale-110">
<div key={genre.name}>
<div className="px-2 py-1 text-[0.95em] bg-mediaCard-hoverBackground rounded hover:bg-search-background cursor-default duration-200 transition-colors transform hover:scale-110">
{genre.name}
</div>
</div>
))
: Array.from({ length: 3 }).map((_, idx) => (
// eslint-disable-next-line react/no-array-index-key
<div className="inline-block" key={idx}>
<div key={idx}>
<Skeleton />
</div>
))}
</div>
<div className="relative whitespace-normal font-medium overflow-y-auto max-h-32">
</div>
<div className="relative whitespace-normal font-medium overflow-y-auto max-h-28">
{data?.overview}
</div>
<div className="pt-3">
@ -285,7 +282,7 @@ export function PopupModal({
<EpisodeSelector tmdbId={media.id} mediaTitle={media.title} />
) : null}
</div>
<div className="flex justify-center items-center mt-4 mb-1">
<div className="flex justify-center items-center mt-3 mb-1">
<Button
theme="purple"
onClick={() =>

View file

@ -62,6 +62,19 @@ export function Volume(props: Props) {
[volume, setVolume],
);
const getVolumeIcon = (volumeLevel: number) => {
if (volumeLevel === 0) {
return Icons.VOLUME_X;
}
if (volumeLevel > 0 && volumeLevel <= 0.33) {
return Icons.VOLUME_LOW;
}
if (volumeLevel > 0.33 && volumeLevel <= 0.66) {
return Icons.VOLUME_MED;
}
return Icons.VOLUME;
};
return (
<div
className={props.className}
@ -71,7 +84,7 @@ export function Volume(props: Props) {
>
<div className="pointer-events-auto flex cursor-pointer items-center py-0 touch-none">
<div className="px-4 text-2xl text-white" onClick={handleClick}>
<Icon icon={percentage > 0 ? Icons.VOLUME : Icons.VOLUME_X} />
<Icon icon={getVolumeIcon(percentage / 100)} />
</div>
<div
className={`linear -ml-2 w-0 overflow-hidden transition-[width,opacity] duration-300 ${

View file

@ -118,10 +118,17 @@ export function KeyboardEvents() {
// Utils
if (keyL === "f") dataRef.current.display?.toggleFullscreen();
if (k === " " || keyL === "k")
dataRef.current.display?.[
dataRef.current.mediaPlaying.isPaused ? "play" : "pause"
]();
if (k === " " || keyL === "k") {
if (
evt.target &&
(evt.target as HTMLInputElement).nodeName === "BUTTON"
) {
return;
}
const action = dataRef.current.mediaPlaying.isPaused ? "play" : "pause";
dataRef.current.display?.[action]();
}
if (k === "Escape") dataRef.current.router.close();
// captions

View file

@ -1,7 +1,7 @@
import { useEffect, useState } from "react";
import { Helmet } from "react-helmet-async";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import { To, useNavigate } from "react-router-dom";
import { WideContainer } from "@/components/layout/WideContainer";
import { useDebounce } from "@/hooks/useDebounce";
@ -48,6 +48,11 @@ export function HomePage() {
const [showBookmarks, setShowBookmarks] = useState(false);
const [showWatching, setShowWatching] = useState(false);
const handleClick = (path: To) => {
window.scrollTo(0, 0);
navigate(path);
};
return (
<HomeLayout showBg={showBg}>
<div className="mb-16 sm:mb-24">
@ -77,7 +82,7 @@ export function HomePage() {
<p className="text-[18.5px] pb-3">{emptyText}</p>
<Button
className="px-py p-[0.35em] mt-3 rounded-xl text-type-dimmed box-content text-[18px] bg-largeCard-background text-buttons-secondaryText justify-center items-center"
onClick={() => navigate("/discover")}
onClick={() => handleClick("/discover")}
>
{t("home.search.discover")}
</Button>

View file

@ -59,7 +59,7 @@ export default defineConfig(({ mode }) => {
registerType: "autoUpdate",
workbox: {
maximumFileSizeToCacheInBytes: 4000000, // 4mb
globIgnores: ["**ping.txt**"],
globIgnores: ["!assets/**/*"],
},
includeAssets: [
"favicon.ico",