diff --git a/public/icons.svg b/public/icons.svg index 1e2f16a..d8a86b1 100644 --- a/public/icons.svg +++ b/public/icons.svg @@ -26,7 +26,9 @@ - + + + diff --git a/public/zap-stream.svg b/public/zap-stream.svg new file mode 100644 index 0000000..30f2088 --- /dev/null +++ b/public/zap-stream.svg @@ -0,0 +1,4 @@ + + + diff --git a/src/index.css b/src/index.css index 7616ae6..829769e 100644 --- a/src/index.css +++ b/src/index.css @@ -80,8 +80,8 @@ a { color: white; } -.btn-red { - background: rgb(143, 0, 0); +.btn-warning { + background: #FF563F; color: white; } @@ -150,4 +150,4 @@ div.paper { .border-warning { border: 1px solid #FF563F; -} \ No newline at end of file +} diff --git a/src/index.tsx b/src/index.tsx index f484295..b033c29 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -47,6 +47,10 @@ const router = createBrowserRouter([ path: "/p/:npub", element: , }, + { + path: "/nsfw", + element: + }, { path: "/:id", element: , diff --git a/src/pages/layout.css b/src/pages/layout.css index 40091b9..423185b 100644 --- a/src/pages/layout.css +++ b/src/pages/layout.css @@ -32,7 +32,7 @@ grid-template-rows: 64px min-content; grid-template-columns: 600px 1fr; gap: 0; - } + } .video-content video { height: 100%; @@ -61,21 +61,24 @@ padding: 0 40px; grid-template-columns: auto 450px; } + .video-content { max-height: calc(100vh - 320px); } + .video-content video { height: 100%; } } header { - grid-area: header; - align-items: center; - display: grid; - grid-template-columns: min-content min-content auto; - padding: 8px 16px; - gap: 8px; + grid-area: header; + align-items: center; + display: grid; + grid-template-columns: min-content min-content min-content auto; + padding: 8px 16px; + gap: 8px; + white-space: nowrap; } @media (min-width: 1020px) { @@ -90,39 +93,60 @@ header { } header .logo { - background: url("public/logo.png") no-repeat #171717; - background-size: cover; - border-radius: 16px; - width: 48px; - height: 48px; - cursor: pointer; + background: url("public/logo.png") no-repeat #171717; + background-size: cover; + border-radius: 16px; + width: 48px; + height: 48px; + cursor: pointer; +} + +header .btn-header { + height: 32px; + border-bottom: 2px solid transparent; + user-select: none; + cursor: pointer; + font-weight: 700; + font-size: 16px; + line-height: 20px; + padding: 8px 16px; + display: flex; + align-items: center; +} + +header .btn-header.active { + border-bottom: 2px solid; +} + +header .btn-header:hover { + border-bottom: 2px solid; } header .paper { - min-width: 300px; - height: 32px; + min-width: 300px; + height: 32px; } header .header-right { - justify-self: end; - display: flex; - gap: 24px; + justify-self: end; + display: flex; + gap: 24px; } header input[type="text"]:active { - border: unset; + border: unset; } header button { - height: 48px; - display: flex; - align-items: center; - gap: 8px; + height: 48px; + display: flex; + align-items: center; + gap: 8px; } header .profile img { - width: 48px; - height: 48px; + width: 48px; + height: 48px; } @media (max-width: 1020px) { @@ -183,3 +207,39 @@ button span.hide-on-mobile { display: flex; gap: 8px; } + +.fullscreen-exclusive { + width: 100vw; + height: 100vh; + position: absolute; + top: 0; + left: 0; + z-index: 999; + background: #0A0A0A; +} + +.age-check { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 24px; +} + +.age-check::after { + content: " "; + background: url("public/zap-stream.svg") no-repeat; + background-position: center; + background-size: contain; + position: absolute; + top: 20px; + left: 20px; + width: calc(100vw - 40px); + height: calc(100vh - 40px); + z-index: -1; + opacity: 0.02; +} + +.age-check .btn { + padding: 12px 16px; +} \ No newline at end of file diff --git a/src/pages/layout.tsx b/src/pages/layout.tsx index 64147bb..0fc762e 100644 --- a/src/pages/layout.tsx +++ b/src/pages/layout.tsx @@ -3,12 +3,13 @@ import "./layout.css"; import { EventPublisher, } from "@snort/system"; -import { Outlet, useNavigate, useLocation } from "react-router-dom"; +import { Outlet, useNavigate, useLocation, Link } from "react-router-dom"; import AsyncButton from "element/async-button"; import { Login } from "index"; import { useLogin } from "hooks/login"; import { Profile } from "element/profile"; import { NewStreamDialog } from "element/new-stream"; +import { useState } from "react"; export function LayoutPage() { const navigate = useNavigate(); @@ -51,15 +52,16 @@ export function LayoutPage() { ); } + const isNsfw = window.location.pathname === "/nsfw"; return (
@@ -68,12 +70,43 @@ export function LayoutPage() {
+ +
+ Adult (18+) +
+ +
{loggedIn()} {loggedOut()}
+ {isNsfw && } ); } + +function ContentWarningOverlay() { + const navigate = useNavigate(); + const [is18Plus, setIs18Plus] = useState(Boolean(window.localStorage.getItem("accepted-content-warning"))); + if (is18Plus) return null; + + function grownUp() { + window.localStorage.setItem("accepted-content-warning", "true"); + setIs18Plus(true); + } + + return
+

Sexually explicit material ahead!

+

Confirm your age

+
+ + +
+
+} \ No newline at end of file diff --git a/src/pages/root.tsx b/src/pages/root.tsx index 3a15916..767afea 100644 --- a/src/pages/root.tsx +++ b/src/pages/root.tsx @@ -12,7 +12,7 @@ import { VideoTile } from "../element/video-tile"; import { findTag } from "../utils"; import { LIVE_STREAM } from "../const"; -export function RootPage() { +export function RootPage({ nsfw }: { nsfw?: boolean }) { const rb = useMemo(() => { const rb = new RequestBuilder("root"); rb.withOptions({ @@ -31,7 +31,7 @@ export function RootPage() { ); const feedSorted = useMemo(() => { if (feed.data) { - return [...feed.data].sort((a, b) => { + return [...feed.data].filter(a => nsfw ? findTag(a, "content-warning") !== undefined : findTag(a, "content-warning") === undefined).sort((a, b) => { const aStatus = findTag(a, "status")!; const bStatus = findTag(b, "status")!; if (aStatus === bStatus) { @@ -44,7 +44,7 @@ export function RootPage() { }); } return []; - }, [feed.data]); + }, [feed.data, nsfw]); const live = feedSorted.filter( (a) => findTag(a, "status") === StreamState.Live diff --git a/src/pages/stream-page.tsx b/src/pages/stream-page.tsx index dfd6864..75eba37 100644 --- a/src/pages/stream-page.tsx +++ b/src/pages/stream-page.tsx @@ -60,7 +60,7 @@ function ProfileInfo({ ev }: { ev?: NostrEvent }) { )} Delete