fixes: mobile
This commit is contained in:
parent
4990e6dbca
commit
bb207d7af1
@ -7,7 +7,7 @@ import { FormattedMessage } from "react-intl";
|
||||
import VideoGrid from "./video-grid";
|
||||
import { VideoTile } from "./video-tile";
|
||||
|
||||
export default function VideoGridSorted({ evs }: { evs: Array<TaggedNostrEvent> }) {
|
||||
export default function VideoGridSorted({ evs, showAll }: { evs: Array<TaggedNostrEvent>, showAll?: boolean }) {
|
||||
const login = useLogin();
|
||||
const mutedHosts = new Set(getTagValues(login?.muted.tags ?? [], "p"));
|
||||
const tags = login?.follows.tags ?? [];
|
||||
@ -17,7 +17,7 @@ export default function VideoGridSorted({ evs }: { evs: Array<TaggedNostrEvent>
|
||||
},
|
||||
[tags]
|
||||
);
|
||||
const { live, planned, ended } = useLiveStreams(evs);
|
||||
const { live, planned, ended } = useLiveStreams(evs, showAll ? 0 : undefined);
|
||||
const hashtags = getTagValues(tags, "t");
|
||||
const following = live.filter(followsHost);
|
||||
const liveNow = live.filter(e => !following.includes(e));
|
||||
|
@ -4,7 +4,7 @@ import { unixNow } from "@snort/shared";
|
||||
import { NostrEvent, TaggedNostrEvent } from "@snort/system";
|
||||
import { useMemo } from "react";
|
||||
|
||||
export function useLiveStreams(feed: Array<TaggedNostrEvent>) {
|
||||
export function useLiveStreams(feed: Array<TaggedNostrEvent>, oldest?: number) {
|
||||
function sortCreatedAt(a: NostrEvent, b: NostrEvent) {
|
||||
return b.created_at > a.created_at ? 1 : -1;
|
||||
}
|
||||
@ -18,7 +18,7 @@ export function useLiveStreams(feed: Array<TaggedNostrEvent>) {
|
||||
const feedSorted = useMemo(() => {
|
||||
if (feed) {
|
||||
return feed
|
||||
.filter(a => a.created_at > unixNow() - 7 * DAY)
|
||||
.filter(a => a.created_at > (oldest ?? (unixNow() - 7 * DAY)))
|
||||
.filter(a => !import.meta.env.VITE_SINGLE_PUBLISHER || import.meta.env.VITE_SINGLE_PUBLISHER === getHost(a));
|
||||
}
|
||||
return [];
|
||||
|
@ -132,7 +132,7 @@ const router = createBrowserRouter([
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "/search/:term",
|
||||
path: "/search/:term?",
|
||||
element: <SearchPage />,
|
||||
},
|
||||
{
|
||||
|
@ -56,11 +56,7 @@ export default function Category() {
|
||||
rb.withFilter().kinds([EventKind.LiveEvent]).tag("t", cat.tags);
|
||||
return rb;
|
||||
}, [cat]);
|
||||
const results = useRequestBuilder(sub).filter(a => {
|
||||
const { status } = extractStreamInfo(a);
|
||||
return status === StreamState.Live;
|
||||
});
|
||||
|
||||
const results = useRequestBuilder(sub);
|
||||
return (
|
||||
<div>
|
||||
<div className="flex gap-4">
|
||||
@ -69,7 +65,7 @@ export default function Category() {
|
||||
))}
|
||||
</div>
|
||||
<h1 className="uppercase my-4">{id}</h1>
|
||||
<VideoGridSorted evs={results} />
|
||||
<VideoGridSorted evs={results} showAll={true} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -146,10 +146,10 @@ export function LayoutPage() {
|
||||
<Logo width={40} height={40} />
|
||||
</div>
|
||||
<SearchBar />
|
||||
<Link to="/category">
|
||||
<Link to="/category" className="max-xl:hidden">
|
||||
<FormattedMessage defaultMessage="Categories" id="VKb1MS" />
|
||||
</Link>
|
||||
<Link to="/faq">
|
||||
<Link to="/faq" className="max-xl:hidden">
|
||||
<FormattedMessage defaultMessage="FAQ" id="W8nHSd" />
|
||||
</Link>
|
||||
</div>
|
||||
@ -178,9 +178,10 @@ function SearchBar() {
|
||||
const [search, setSearch] = useState(term ?? "");
|
||||
|
||||
return (
|
||||
<div className="bg-layer-2 rounded-xl pr-4 py-1 flex items-center">
|
||||
<div className="max-xl:bg-white xl:bg-layer-2 rounded-xl pr-4 py-1 flex items-center">
|
||||
<input
|
||||
type="text"
|
||||
className="max-xl:hidden"
|
||||
placeholder={formatMessage({
|
||||
defaultMessage: "Search",
|
||||
id: "xmcVZ0",
|
||||
@ -193,7 +194,13 @@ function SearchBar() {
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Icon name="search" className="text-layer-4" size={16} />
|
||||
<Icon
|
||||
name="search"
|
||||
className="max-xl:text-black mx:text-layer-4 max-xl:ml-4 max-xl:my-1"
|
||||
size={16}
|
||||
onClick={() => {
|
||||
navigate("/search")
|
||||
}}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ export function RootPage() {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="flex gap-4">
|
||||
<div className="flex gap-4 overflow-x-scroll scrollbar-hidden">
|
||||
{AllCategories.filter(a => a.priority === 0).map(a => (
|
||||
<CategoryLink key={a.id} {...a} />
|
||||
))}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import VideoGrid from "@/element/video-grid";
|
||||
import { VideoTile } from "@/element/video-tile";
|
||||
import { Icon } from "@/element/icon";
|
||||
import VideoGridSorted from "@/element/video-grid-sorted";
|
||||
import { EventKind, RequestBuilder } from "@snort/system";
|
||||
import { useRequestBuilder } from "@snort/system-react";
|
||||
import { useMemo } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useMemo, useState } from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
|
||||
export const SearchRelays = [
|
||||
"wss://relay.nostr.band",
|
||||
@ -15,12 +15,13 @@ export const SearchRelays = [
|
||||
|
||||
export default function SearchPage() {
|
||||
const { term } = useParams();
|
||||
const { formatMessage } = useIntl();
|
||||
const navigate = useNavigate();
|
||||
const [search, setSearch] = useState(term ?? "");
|
||||
|
||||
const sub = useMemo(() => {
|
||||
if (!term) return;
|
||||
const rb = new RequestBuilder(`search:${term}`);
|
||||
rb.withOptions({
|
||||
skipDiff: true,
|
||||
});
|
||||
rb.withFilter().relay(SearchRelays).kinds([EventKind.LiveEvent]).search(term).limit(50);
|
||||
return rb;
|
||||
}, [term]);
|
||||
@ -28,20 +29,41 @@ export default function SearchPage() {
|
||||
const results = useRequestBuilder(sub);
|
||||
return (
|
||||
<div>
|
||||
<h2 className="mb-4">
|
||||
<FormattedMessage
|
||||
defaultMessage="Search results: {term}"
|
||||
id="A1zT+z"
|
||||
values={{
|
||||
term,
|
||||
<div className="bg-layer-2 rounded-xl pr-4 py-1 flex items-center xl:hidden">
|
||||
<input
|
||||
type="text"
|
||||
placeholder={formatMessage({
|
||||
defaultMessage: "Search",
|
||||
id: "xmcVZ0",
|
||||
})}
|
||||
value={search}
|
||||
onChange={e => setSearch(e.target.value)}
|
||||
onKeyDown={e => {
|
||||
if (e.key === "Enter") {
|
||||
navigate(`/search/${encodeURIComponent(search)}`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</h2>
|
||||
<VideoGrid>
|
||||
{results.map(a => (
|
||||
<VideoTile ev={a} key={a.id} />
|
||||
))}
|
||||
</VideoGrid>
|
||||
<Icon
|
||||
name="search"
|
||||
className="text-layer-4 ml-4 my-1"
|
||||
size={16}
|
||||
onClick={() => {
|
||||
navigate("/search")
|
||||
}} />
|
||||
</div>
|
||||
{term && <>
|
||||
<h2 className="mb-4">
|
||||
<FormattedMessage
|
||||
defaultMessage="Search results: {term}"
|
||||
id="A1zT+z"
|
||||
values={{
|
||||
term,
|
||||
}}
|
||||
/>
|
||||
</h2>
|
||||
<VideoGridSorted evs={results} showAll={true} />
|
||||
</>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user