Add DMCA & FAQ (sorta) pages

This commit is contained in:
Jip Fr 2023-09-06 20:27:17 +02:00
parent 4ca5e45216
commit 6fcdef3fd7
11 changed files with 207 additions and 24 deletions

View File

@ -41,6 +41,7 @@ export enum Icons {
PICTURE_IN_PICTURE = "pictureInPicture", PICTURE_IN_PICTURE = "pictureInPicture",
CHECKMARK = "checkmark", CHECKMARK = "checkmark",
TACHOMETER = "tachometer", TACHOMETER = "tachometer",
MAIL = "mail",
} }
export interface IconProps { export interface IconProps {
@ -89,6 +90,7 @@ const iconList: Record<Icons, string> = {
pictureInPicture: `<svg xmlns="http://www.w3.org/2000/svg" height="1em" width="1em" fill="currentColor" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98V5c0-1.1-.9-2-2-2zm0 16.01H3V4.98h18v14.03z"/></svg>`, pictureInPicture: `<svg xmlns="http://www.w3.org/2000/svg" height="1em" width="1em" fill="currentColor" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98V5c0-1.1-.9-2-2-2zm0 16.01H3V4.98h18v14.03z"/></svg>`,
checkmark: `<svg xmlns="http://www.w3.org/2000/svg" height="1em" width="1em" fill="currentColor" viewBox="0 0 24 24"><path d="M9 22l-10-10.598 2.798-2.859 7.149 7.473 13.144-14.016 2.909 2.806z" /></svg>`, checkmark: `<svg xmlns="http://www.w3.org/2000/svg" height="1em" width="1em" fill="currentColor" viewBox="0 0 24 24"><path d="M9 22l-10-10.598 2.798-2.859 7.149 7.473 13.144-14.016 2.909 2.806z" /></svg>`,
tachometer: `<svg xmlns="http://www.w3.org/2000/svg" height="1em" width="1em" fill="currentColor" viewBox="0 0 576 512"><!-- Font Awesome Pro 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M128 288c-17.67 0-32 14.33-32 32s14.33 32 32 32 32-14.33 32-32-14.33-32-32-32zm154.65-97.08l16.24-48.71c1.16-3.45 3.18-6.35 4.92-9.43-4.73-2.76-9.94-4.78-15.81-4.78-17.67 0-32 14.33-32 32 0 15.78 11.63 28.29 26.65 30.92zM176 176c-17.67 0-32 14.33-32 32s14.33 32 32 32 32-14.33 32-32-14.33-32-32-32zM288 32C128.94 32 0 160.94 0 320c0 52.8 14.25 102.26 39.06 144.8 5.61 9.62 16.3 15.2 27.44 15.2h443c11.14 0 21.83-5.58 27.44-15.2C561.75 422.26 576 372.8 576 320c0-159.06-128.94-288-288-288zm212.27 400H75.73C57.56 397.63 48 359.12 48 320 48 187.66 155.66 80 288 80s240 107.66 240 240c0 39.12-9.56 77.63-27.73 112zM416 320c0 17.67 14.33 32 32 32s32-14.33 32-32-14.33-32-32-32-32 14.33-32 32zm-56.41-182.77c-12.72-4.23-26.16 2.62-30.38 15.17l-45.34 136.01C250.49 290.58 224 318.06 224 352c0 11.72 3.38 22.55 8.88 32h110.25c5.5-9.45 8.88-20.28 8.88-32 0-19.45-8.86-36.66-22.55-48.4l45.34-136.01c4.17-12.57-2.64-26.17-15.21-30.36zM432 208c0-15.8-11.66-28.33-26.72-30.93-.07.21-.07.43-.14.65l-19.5 58.49c4.37 2.24 9.11 3.8 14.36 3.8 17.67-.01 32-14.34 32-32.01z"/></svg>`, tachometer: `<svg xmlns="http://www.w3.org/2000/svg" height="1em" width="1em" fill="currentColor" viewBox="0 0 576 512"><!-- Font Awesome Pro 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M128 288c-17.67 0-32 14.33-32 32s14.33 32 32 32 32-14.33 32-32-14.33-32-32-32zm154.65-97.08l16.24-48.71c1.16-3.45 3.18-6.35 4.92-9.43-4.73-2.76-9.94-4.78-15.81-4.78-17.67 0-32 14.33-32 32 0 15.78 11.63 28.29 26.65 30.92zM176 176c-17.67 0-32 14.33-32 32s14.33 32 32 32 32-14.33 32-32-14.33-32-32-32zM288 32C128.94 32 0 160.94 0 320c0 52.8 14.25 102.26 39.06 144.8 5.61 9.62 16.3 15.2 27.44 15.2h443c11.14 0 21.83-5.58 27.44-15.2C561.75 422.26 576 372.8 576 320c0-159.06-128.94-288-288-288zm212.27 400H75.73C57.56 397.63 48 359.12 48 320 48 187.66 155.66 80 288 80s240 107.66 240 240c0 39.12-9.56 77.63-27.73 112zM416 320c0 17.67 14.33 32 32 32s32-14.33 32-32-14.33-32-32-32-32 14.33-32 32zm-56.41-182.77c-12.72-4.23-26.16 2.62-30.38 15.17l-45.34 136.01C250.49 290.58 224 318.06 224 352c0 11.72 3.38 22.55 8.88 32h110.25c5.5-9.45 8.88-20.28 8.88-32 0-19.45-8.86-36.66-22.55-48.4l45.34-136.01c4.17-12.57-2.64-26.17-15.21-30.36zM432 208c0-15.8-11.66-28.33-26.72-30.93-.07.21-.07.43-.14.65l-19.5 58.49c4.37 2.24 9.11 3.8 14.36 3.8 17.67-.01 32-14.34 32-32.01z"/></svg>`,
mail: `<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M19.25 4.125H2.75C2.56766 4.125 2.3928 4.19743 2.26386 4.32636C2.13493 4.4553 2.0625 4.63016 2.0625 4.8125V16.5C2.0625 16.8647 2.20737 17.2144 2.46523 17.4723C2.72309 17.7301 3.07283 17.875 3.4375 17.875H18.5625C18.9272 17.875 19.2769 17.7301 19.5348 17.4723C19.7926 17.2144 19.9375 16.8647 19.9375 16.5V4.8125C19.9375 4.63016 19.8651 4.4553 19.7361 4.32636C19.6072 4.19743 19.4323 4.125 19.25 4.125ZM8.48289 11L3.4375 15.6243V6.3757L8.48289 11ZM9.50039 11.9324L10.5316 12.882C10.6585 12.9985 10.8244 13.0631 10.9966 13.0631C11.1687 13.0631 11.3346 12.9985 11.4615 12.882L12.4927 11.9324L17.4771 16.5H4.51773L9.50039 11.9324ZM13.5171 11L18.5625 6.37484V15.6252L13.5171 11Z" fill="currentColor" /></svg>`,
}; };
function ChromeCastButton() { function ChromeCastButton() {

View File

@ -23,7 +23,7 @@ export function IconPatch(props: IconPatchProps) {
return ( return (
<div className={props.className || undefined} onClick={props.onClick}> <div className={props.className || undefined} onClick={props.onClick}>
<div <div
className={`flex h-12 w-12 items-center justify-center rounded-full border-2 border-transparent bg-denim-500 transition-[background-color,color,transform,border-color] duration-75 ${transparentClasses} ${clickableClasses} ${activeClasses}`} className={`flex h-12 w-12 items-center justify-center rounded-full border-2 border-transparent bg-pill-background transition-[background-color,color,transform,border-color] duration-75 ${transparentClasses} ${clickableClasses} ${activeClasses}`}
> >
<Icon icon={props.icon} /> <Icon icon={props.icon} />
</div> </div>

View File

@ -10,7 +10,7 @@ export function BrandPill(props: {
return ( return (
<div <div
className={`flex items-center space-x-2 rounded-full bg-bink-300 bg-opacity-50 px-4 py-2 text-bink-600 ${ className={`flex items-center space-x-2 rounded-full bg-pill-background bg-opacity-50 px-4 py-2 text-bink-600 ${
props.clickable props.clickable
? "transition-[transform,background-color] hover:scale-105 hover:bg-bink-400 hover:text-bink-700 active:scale-95" ? "transition-[transform,background-color] hover:scale-105 hover:bg-bink-400 hover:text-bink-700 active:scale-95"
: "" : ""

View File

@ -12,17 +12,20 @@ import { BrandPill } from "./BrandPill";
export interface NavigationProps { export interface NavigationProps {
children?: ReactNode; children?: ReactNode;
bg?: boolean; bg?: boolean;
noLightbar?: boolean;
} }
export function Navigation(props: NavigationProps) { export function Navigation(props: NavigationProps) {
const bannerHeight = useBannerSize(); const bannerHeight = useBannerSize();
return ( return (
<> <>
{!props.noLightbar ? (
<div className="absolute inset-x-0 top-0 flex h-[88px] items-center justify-center"> <div className="absolute inset-x-0 top-0 flex h-[88px] items-center justify-center">
<div className="absolute inset-x-0 -mt-[22%] flex items-center sm:mt-0"> <div className="absolute inset-x-0 -mt-[22%] flex items-center sm:mt-0">
<Lightbar /> <Lightbar />
</div> </div>
</div> </div>
) : null}
<div <div
className="fixed left-0 right-0 top-0 z-10 min-h-[150px]" className="fixed left-0 right-0 top-0 z-10 min-h-[150px]"
style={{ style={{

View File

@ -0,0 +1,43 @@
interface TextProps {
className?: string;
children: React.ReactNode;
}
export function Heading1(props: TextProps) {
return (
<h1
className={[
"text-5xl font-bold text-white mb-9",
props.className ?? "",
].join(" ")}
>
{props.children}
</h1>
);
}
export function Heading2(props: TextProps) {
return (
<h2
className={[
"text-3xl font-bold text-white mt-20 mb-9",
props.className ?? "",
].join(" ")}
>
{props.children}
</h2>
);
}
export function Paragraph(props: TextProps) {
return (
<p
className={[
"text-type-text my-9 font-medium",
props.className ?? "",
].join(" ")}
>
{props.children}
</p>
);
}

73
src/pages/About.tsx Normal file
View File

@ -0,0 +1,73 @@
/* eslint-disable react/no-unescaped-entities */
import { ThinContainer } from "@/components/layout/ThinContainer";
import { Heading1, Heading2, Paragraph } from "@/components/utils/Text";
import { SubPageLayout } from "./layouts/SubPageLayout";
export function AboutPage() {
return (
<SubPageLayout>
<ThinContainer>
<Heading1>About us</Heading1>
<Paragraph>
Blue, oh so blue, like the tranquil sky on a summer's day. It's the
color of calm and serenity, a gentle embrace for your senses. When you
think of blue, you think of the vast ocean stretching endlessly,
inviting you to dive deep into its azure depths. Blue is the color of
dreams, where the world slows down, and you can hear the whispers of
the wind in the tall grass. It's a symphony of peacefulness that
resonates with your soul, like a melody that lingers in your heart.
</Paragraph>
<Heading2>How does it work?</Heading2>
<Paragraph>
Blue, well, it's like this cosmic wavelength, man, and it's like the
universe is just vibin', you know? It's like, when you stare at the
blue, it's like you're staring at the secrets of the cosmos, like,
whoa, it's like a trippy trip to another dimension where time doesn't
even matter, and you're just floating in a sea of, like, blue, man.
And it's like, it's not just a color, it's a whole experience, like,
you're in this cosmic rollercoaster ride through the quantum soup of
existence, and you're just riding the blue wave, man.
</Paragraph>
<Paragraph>
Blue, like, it's totally, um, the essence of like, everything, you
know? It's like, you look at it, and it's like, it's there, but it's
also not there, and it's like, you're trying to grasp the concept of
blue, but it's like trying to catch a dream in a net made of
spaghetti, you know? It's like, it's the ultimate paradox, and it's
like, it's just blowing your mind, man, like, it's like trying to find
the meaning of life in a jar of peanut butter, but the peanut butter
is made of pure energy, man, and it's like, whoa.
</Paragraph>
<Heading2>Frequently asked questions</Heading2>
<Paragraph>
Blue, blue, b-b-b-bluuuuuueeeeeeeee, zippity zappity zoooooo, it's
like, you know, it's like, blue is like, um, you know, it's like, um,
like a thing, but it's also not a thing, and it's like, whoa, dude,
it's like, it's like trying to juggle invisible watermelons while
riding a unicycle made of rubber bands and ketchup, and it's like,
you're just floating in the cosmic jellyfish of existence, and the
jellyfish are like, playing the accordion, man, and it's like, the
accordion is made of, like, spaghetti and, like, um, interdimensional
cheese, and it's like, whoa, dude, like, whoa.
</Paragraph>
<Paragraph>
Bloo-bloo-bloo, bleepity-bloop, blibber-blabber, blarble-blurble, blue
is like, um, you know, flibberflabberfloober, like,
zoomity-zamity-zoom, and it's like, um, sproingity-sproing, like, uh,
gibber-gabber-gobblygook, you know, it's like, um,
jibber-jabber-jibberish, like, whatchamacallit, thingamajig,
doodad-doodad-dingdong, like, ploopity-ploop, um, blibbity-blam,
flibbity-floo, like, gobbledygook-gobbledygook,
whoopsy-daisy-dingleberry, and it's like, uh,
flibberflabberflooberzoomity-sproing, um, like,
blibber-gibber-jibber-jabber, thingamajig-whatchamacallit, like, you
know, thingamajig-doodad-doodledee, and it's like, um,
doodad-gobbledygook-doodley-doo, like,
ploopity-whoopsy-doodleberry-flibber, you know, it's like, uh, blue,
man, like, totally, um, blue.
</Paragraph>
</ThinContainer>
</SubPageLayout>
);
}

25
src/pages/Dmca.tsx Normal file
View File

@ -0,0 +1,25 @@
/* eslint-disable react/no-unescaped-entities */
import { useTranslation } from "react-i18next";
import { Icon, Icons } from "@/components/Icon";
import { ThinContainer } from "@/components/layout/ThinContainer";
import { Heading1, Paragraph } from "@/components/utils/Text";
import { SubPageLayout } from "./layouts/SubPageLayout";
export function DmcaPage() {
const { t } = useTranslation();
return (
<SubPageLayout>
<ThinContainer>
<Heading1>{t("dmca.title")}</Heading1>
<Paragraph>{t("dmca.description")}</Paragraph>
<Paragraph className="flex space-x-3 items-center">
<Icon icon={Icons.MAIL} />
<span>dmca@movie-web.app</span>
</Paragraph>
</ThinContainer>
</SubPageLayout>
);
}

View File

@ -0,0 +1,24 @@
import { FooterView } from "@/components/layout/Footer";
import { Navigation } from "@/components/layout/Navigation";
export function SubPageLayout(props: { children: React.ReactNode }) {
return (
<div
className="from-[#0D0D1A] to-background-main"
style={{
backgroundImage:
"linear-gradient(to bottom, var(--tw-gradient-from), var(--tw-gradient-to) 800px)",
}}
>
{/* Blur elipsis */}
<div className="absolute top-0 -right-48 rotate-[32deg] w-[50rem] h-[15rem] rounded-[70rem] bg-background-accentA blur-[100px] pointer-events-none opacity-25" />
<div className="absolute top-0 right-48 rotate-[32deg] w-[50rem] h-[15rem] rounded-[70rem] bg-background-accentB blur-[100px] pointer-events-none opacity-25" />
{/* Main page */}
<FooterView>
<Navigation noLightbar />
<div className="mt-40">{props.children}</div>
</FooterView>
</div>
);
}

View File

@ -11,6 +11,8 @@ import {
import { convertLegacyUrl, isLegacyUrl } from "@/backend/metadata/getmeta"; import { convertLegacyUrl, isLegacyUrl } from "@/backend/metadata/getmeta";
import { generateQuickSearchMediaUrl } from "@/backend/metadata/tmdb"; import { generateQuickSearchMediaUrl } from "@/backend/metadata/tmdb";
import { BannerContextProvider } from "@/hooks/useBanner"; import { BannerContextProvider } from "@/hooks/useBanner";
import { AboutPage } from "@/pages/About";
import { DmcaPage } from "@/pages/Dmca";
import { NotFoundPage } from "@/pages/errors/NotFoundPage"; import { NotFoundPage } from "@/pages/errors/NotFoundPage";
import { HomePage } from "@/pages/HomePage"; import { HomePage } from "@/pages/HomePage";
import { MediaView } from "@/pages/media/MediaView"; import { MediaView } from "@/pages/media/MediaView";
@ -87,6 +89,8 @@ function App() {
path={["/browse/:query?", "/"]} path={["/browse/:query?", "/"]}
component={HomePage} component={HomePage}
/> />
<Route exact path="/faq" component={AboutPage} />
<Route exact path="/dmca" component={DmcaPage} />
{/* other */} {/* other */}
<Route <Route

View File

@ -132,6 +132,10 @@
"errors": { "errors": {
"offline": "Check your internet connection" "offline": "Check your internet connection"
}, },
"dmca": {
"title": "DMCA",
"description": "In an effort to address the copyright concerns associated with the website known as \"movie-web,\" the DMCA, or Digital Millennium Copyright Act, has been initiated to safeguard the intellectual property rights of content creators by reporting infringements on this platform, thereby adhering to legal protocols for takedown requests, which, like, you know, it's all about, like, maintaining the integrity of intellectual property, and, um, making sure, like, creators get their fair share, but then, it's, like, this intricate dance of digital legalities, where you have to, uh, like, navigate this labyrinth of code and bytes and, uh, send, you know, these, like, electronic documents that, um, point out the, uh, alleged infringement, and it's, like, this whole, like, teeter-totter of legality, where you're, like, balancing, um, the rights of the, you know, creators and the, um, operation of this, like, online, uh, entity, and, like, the DMCA, it's, like, this, um, powerful tool, but, uh, it's also, like, this, um, complex puzzle, where, you know, you're, like, seeking justice in the digital wilderness, and, uh, striving for harmony amidst the chaos of the internet, and, um, yeah, that's, like, the whole, like, DMCA-ing thing with movie-web, you know?"
},
"footer": { "footer": {
"tagline": "Watch your favorite shows and movies with this open source streaming app.", "tagline": "Watch your favorite shows and movies with this open source streaming app.",
"links": { "links": {

View File

@ -26,23 +26,23 @@ module.exports = {
"ash-400": "#3D394D", "ash-400": "#3D394D",
"ash-300": "#2C293A", "ash-300": "#2C293A",
"ash-200": "#2B2836", "ash-200": "#2B2836",
"ash-100": "#1E1C26" "ash-100": "#1E1C26",
}, },
/* fonts */ /* fonts */
fontFamily: { fontFamily: {
"open-sans": "'Open Sans'" "open-sans": "'Open Sans'",
}, },
/* animations */ /* animations */
keyframes: { keyframes: {
"loading-pin": { "loading-pin": {
"0%, 40%, 100%": { height: "0.5em", "background-color": "#282336" }, "0%, 40%, 100%": { height: "0.5em", "background-color": "#282336" },
"20%": { height: "1em", "background-color": "white" } "20%": { height: "1em", "background-color": "white" },
} },
},
animation: { "loading-pin": "loading-pin 1.8s ease-in-out infinite" },
}, },
animation: { "loading-pin": "loading-pin 1.8s ease-in-out infinite" }
}
}, },
plugins: [ plugins: [
require("tailwind-scrollbar"), require("tailwind-scrollbar"),
@ -50,22 +50,27 @@ module.exports = {
defaultTheme: { defaultTheme: {
extend: { extend: {
colors: { colors: {
// Branding
pill: {
background: "#1C1C36",
},
// meta data for the theme itself // meta data for the theme itself
global: { global: {
accentA: "#505DBD", accentA: "#505DBD",
accentB: "#3440A1" accentB: "#3440A1",
}, },
// light bar // light bar
lightBar: { lightBar: {
light: "#2A2A71" light: "#2A2A71",
}, },
// only used for body colors/textures // only used for body colors/textures
background: { background: {
main: "#0A0A10", main: "#0A0A10",
accentA: "#6E3B80", accentA: "#6E3B80",
accentB: "#1F1F50" accentB: "#1F1F50",
}, },
// typography // typography
@ -73,7 +78,7 @@ module.exports = {
emphasis: "#FFFFFF", emphasis: "#FFFFFF",
text: "#73739D", text: "#73739D",
dimmed: "#926CAD", dimmed: "#926CAD",
divider: "#262632" divider: "#262632",
}, },
// search bar // search bar
@ -82,7 +87,7 @@ module.exports = {
focused: "#24243C", focused: "#24243C",
placeholder: "#4A4A71", placeholder: "#4A4A71",
icon: "#545476", icon: "#545476",
text: "#FFFFFF" text: "#FFFFFF",
}, },
// media cards // media cards
@ -94,11 +99,11 @@ module.exports = {
barColor: "#4B4B63", barColor: "#4B4B63",
barFillColor: "#BA7FD6", barFillColor: "#BA7FD6",
badge: "#151522", badge: "#151522",
badgeText: "#5F5F7A" badgeText: "#5F5F7A",
} },
} },
} },
} },
}) }),
] ],
}; };