diff --git a/package.json b/package.json index 71fef462..80d2483c 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "@sentry/integrations": "^7.49.0", "@sentry/react": "^7.49.0", "@use-gesture/react": "^10.2.24", + "classnames": "^2.3.2", "core-js": "^3.29.1", "crypto-js": "^4.1.1", "dompurify": "^3.0.1", @@ -95,6 +96,7 @@ "prettier-plugin-tailwindcss": "^0.1.7", "tailwind-scrollbar": "^2.0.1", "tailwindcss": "^3.2.4", + "tailwindcss-themer": "^3.1.0", "typescript": "^4.6.4", "vite": "^4.0.1", "vite-plugin-checker": "^0.5.6", diff --git a/src/components/layout/Footer.tsx b/src/components/layout/Footer.tsx new file mode 100644 index 00000000..24f975fb --- /dev/null +++ b/src/components/layout/Footer.tsx @@ -0,0 +1,78 @@ +import { useTranslation } from "react-i18next"; + +import { Icon, Icons } from "@/components/Icon"; +import { BrandPill } from "@/components/layout/BrandPill"; +import { WideContainer } from "@/components/layout/WideContainer"; + +function FooterLink(props: { + href: string; + children: React.ReactNode; + icon: Icons; +}) { + return ( + + + {props.children} + + ); +} + +export function Footer() { + const { t } = useTranslation(); + + return ( + + ); +} + +export function FooterView(props: { + children: React.ReactNode; + className?: string; +}) { + return ( +
+
{props.children}
+
+ ); +} diff --git a/src/components/layout/WideContainer.tsx b/src/components/layout/WideContainer.tsx index f7d745fe..bcccd5e5 100644 --- a/src/components/layout/WideContainer.tsx +++ b/src/components/layout/WideContainer.tsx @@ -3,14 +3,15 @@ import { ReactNode } from "react"; interface WideContainerProps { classNames?: string; children?: ReactNode; + ultraWide?: boolean; } export function WideContainer(props: WideContainerProps) { return (
{props.children}
diff --git a/src/components/media/MediaGrid.tsx b/src/components/media/MediaGrid.tsx index a9f75b22..17bd4c7a 100644 --- a/src/components/media/MediaGrid.tsx +++ b/src/components/media/MediaGrid.tsx @@ -7,7 +7,10 @@ interface MediaGridProps { export const MediaGrid = forwardRef( (props, ref) => { return ( -
+
{props.children}
); diff --git a/src/components/utils/Flare.tsx b/src/components/utils/Flare.tsx new file mode 100644 index 00000000..680c3812 --- /dev/null +++ b/src/components/utils/Flare.tsx @@ -0,0 +1,75 @@ +import c from "classnames"; +import { useEffect, useRef } from "react"; + +export interface FlareProps { + className?: string; + backgroundClass: string; + flareSize?: number; + cssColorVar?: string; + enabled?: boolean; +} + +const SIZE_DEFAULT = 200; +const CSS_VAR_DEFAULT = "--colors-global-accentA"; + +export function Flare(props: FlareProps) { + const outerRef = useRef(null); + const size = props.flareSize ?? SIZE_DEFAULT; + const cssVar = props.cssColorVar ?? CSS_VAR_DEFAULT; + + useEffect(() => { + function mouseMove(e: MouseEvent) { + if (!outerRef.current) return; + outerRef.current.style.setProperty( + "--bg-x", + `${(e.clientX - size / 2).toFixed(0)}px` + ); + outerRef.current.style.setProperty( + "--bg-y", + `${(e.clientY - size / 2).toFixed(0)}px` + ); + } + document.addEventListener("mousemove", mouseMove); + + return () => document.removeEventListener("mousemove", mouseMove); + }, [size]); + + return ( +
+
+
+
+
+ ); +} diff --git a/src/setup/locales/en/translation.json b/src/setup/locales/en/translation.json index 8f48a9d6..f78adc46 100644 --- a/src/setup/locales/en/translation.json +++ b/src/setup/locales/en/translation.json @@ -131,5 +131,16 @@ }, "errors": { "offline": "Check your internet connection" + }, + "footer": { + "tagline": "Watch your favorite shows and movies with this open source streaming app.", + "links": { + "github": "GitHub", + "dmca": "DMCA" + }, + "legal": { + "disclaimer": "Disclaimer", + "disclaimerText": "movie-web does not host any files, it merely links to 3rd party services. Legal issues should be taken up with the file hosts and providers. movie-web is not responsible for any media files shown by the video providers." + } } } diff --git a/src/views/search/HomeView.tsx b/src/views/search/HomeView.tsx index a7a9a396..42868cc6 100644 --- a/src/views/search/HomeView.tsx +++ b/src/views/search/HomeView.tsx @@ -198,7 +198,7 @@ function NewDomainModal() { export function HomeView() { return ( -
+
diff --git a/src/views/search/SearchView.tsx b/src/views/search/SearchView.tsx index 3fee80b8..01aec28a 100644 --- a/src/views/search/SearchView.tsx +++ b/src/views/search/SearchView.tsx @@ -3,6 +3,7 @@ import { Helmet } from "react-helmet"; import { useTranslation } from "react-i18next"; import Sticky from "react-stickynode"; +import { FooterView } from "@/components/layout/Footer"; import { Navigation } from "@/components/layout/Navigation"; import { ThinContainer } from "@/components/layout/ThinContainer"; import { WideContainer } from "@/components/layout/WideContainer"; @@ -25,7 +26,7 @@ export function SearchView() { ); return ( - <> +
{t("global.name")} @@ -61,6 +62,6 @@ export function SearchView() { - + ); } diff --git a/tailwind.config.js b/tailwind.config.js index 3a6816a6..0733f489 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,3 +1,5 @@ +const themer = require("tailwindcss-themer"); + /** @type {import('tailwindcss').Config} */ module.exports = { content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], @@ -42,5 +44,30 @@ module.exports = { animation: { "loading-pin": "loading-pin 1.8s ease-in-out infinite" } } }, - plugins: [require("tailwind-scrollbar")] + plugins: [ + require("tailwind-scrollbar"), + themer({ + defaultTheme: { + extend: { + colors: { + background: { + main: "#0A0A10", + accentA: "#6E3B80", + accentB: "#1F1F50" + }, + global: { + accentA: "#505DBD", + accentB: "#3440A1" + }, + type: { + emphasis: "#FFFFFF", + text: "#73739D", + dimmed: "#926CAD", + divider: "#353549" + } + } + } + } + }) + ] }; diff --git a/yarn.lock b/yarn.lock index 8b7759b5..592a48f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2147,7 +2147,7 @@ chokidar@^3.5.1, chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" -classnames@^2.0.0: +classnames@^2.0.0, classnames@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== @@ -2184,11 +2184,27 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== -color-name@^1.1.4, color-name@~1.1.4: +color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-string@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^4.1.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" + integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== + dependencies: + color-convert "^2.0.1" + color-string "^1.9.0" + combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -3410,6 +3426,11 @@ is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: get-intrinsic "^1.2.0" is-typed-array "^1.1.10" +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -3761,6 +3782,11 @@ jsonpointer@^5.0.0: array-includes "^3.1.5" object.assign "^4.1.3" +just-unique@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/just-unique/-/just-unique-4.2.0.tgz#80927360b92f5039fad7e7f5f8bc48904d9177b6" + integrity sha512-cxQGGUiit6CGUpuuiezY8N4m1wgF4o7127rXEXDFcxeDUFfdV7gSkwA26Fe2wWBiNQq2SZOgN4gSmMxB/StA8Q== + language-subtag-registry@~0.3.2: version "0.3.22" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" @@ -3840,6 +3866,11 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lodash.mergewith@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" + integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== + lodash.pick@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" @@ -4859,6 +4890,13 @@ signal-exit@^4.0.1: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.0.2.tgz#ff55bb1d9ff2114c13b400688fa544ac63c36967" integrity sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q== +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== + dependencies: + is-arrayish "^0.3.1" + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -5124,6 +5162,16 @@ tailwind-scrollbar@^2.0.1: resolved "https://registry.yarnpkg.com/tailwind-scrollbar/-/tailwind-scrollbar-2.1.0.tgz#46e0b8788cef75387f9d163a5ec82b8cacd66c44" integrity sha512-zpvY5mDs0130YzYjZKBiDaw32rygxk5RyJ4KmeHjGnwkvbjm/PszON1m4Bbt2DkMRIXlXsfNevykAESgURN4KA== +tailwindcss-themer@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/tailwindcss-themer/-/tailwindcss-themer-3.1.0.tgz#4440d62d7edc54f8f0aaef3404bb71844fa556d6" + integrity sha512-IfgxpCxWm5rRK3Q7aTvVyhQ/7tyyn8EJl5tFak5tS+/n8oXT7OGfv8praYepR7+IsM92waAuBDZng1HgnstrYA== + dependencies: + color "^4.1.0" + just-unique "^4.2.0" + lodash.merge "^4.6.2" + lodash.mergewith "^4.6.2" + tailwindcss@^3.2.4: version "3.3.1" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.3.1.tgz#b6662fab6a9b704779e48d083a9fef5a81d2b81e"