tab selector vs content naming, refactoring
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Martti Malmi 2024-01-12 17:33:02 +02:00
parent ffa4a192f6
commit ef673c2a05
10 changed files with 82 additions and 66 deletions

View File

@ -583,7 +583,7 @@ https://git.v0l.io/Kieran/snort/compare/v0.1.9...v0.1.10
- Fix event mention bug by @SamSamskies in https://github.com/v0l/snort/pull/421
- fix NaN when parsing empty string by @SamSamskies in https://github.com/v0l/snort/pull/422
- NIP06 support by @w3irdrobot in https://github.com/v0l/snort/pull/425
- Added key attr to Tabs to remove React warning by @w3irdrobot in https://github.com/v0l/snort/pull/424
- Added key attr to TabSelectors to remove React warning by @w3irdrobot in https://github.com/v0l/snort/pull/424
- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/426
- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/436
- Update Wavlake embed URL, add support for album & artist links by @blastshielddown in https://github.com/v0l/snort/pull/439

View File

@ -8,7 +8,7 @@ import { FormattedMessage, useIntl } from "react-intl";
import CloseButton from "@/Components/Button/CloseButton";
import Icon from "@/Components/Icons/Icon";
import Modal from "@/Components/Modal/Modal";
import Tabs from "@/Components/Tabs/Tabs";
import TabSelectors from "@/Components/TabSelectors/TabSelectors";
import ProfileImage from "@/Components/User/ProfileImage";
import { formatShort } from "@/Utils/Number";
@ -75,7 +75,7 @@ const ReactionsModal = ({ onClose, event, initialTab = 0 }: ReactionsModalProps)
<FormattedMessage {...messages.ReactionsCount} values={{ n: total }} />
</h2>
</div>
<Tabs tabs={tabs} tab={tab} setTab={setTab} />
<TabSelectors tabs={tabs} tab={tab} setTab={setTab} />
<div className="reactions-body" key={tab.value}>
{tab.value === 0 && likes.map(ev => renderReactionItem(ev, "heart"))}
{tab.value === 1 &&

View File

@ -1,4 +1,4 @@
import "./Tabs.css";
import "./TabSelectors.css";
import { ReactNode } from "react";
@ -20,7 +20,7 @@ interface TabElementProps extends Omit<TabsProps, "tabs"> {
t: Tab;
}
export const TabElement = ({ t, tab, setTab }: TabElementProps) => {
export const TabSelector = ({ t, tab, setTab }: TabElementProps) => {
return (
<div
className={`tab${tab.value === t.value ? " active" : ""}${t.disabled ? " disabled" : ""}`}
@ -30,15 +30,15 @@ export const TabElement = ({ t, tab, setTab }: TabElementProps) => {
);
};
const Tabs = ({ tabs, tab, setTab }: TabsProps) => {
const TabSelectors = ({ tabs, tab, setTab }: TabsProps) => {
const horizontalScroll = useHorizontalScroll();
return (
<div className="tabs" ref={horizontalScroll}>
{tabs.map((t, index) => (
<TabElement key={index} tab={tab} setTab={setTab} t={t} />
<TabSelector key={index} tab={tab} setTab={setTab} t={t} />
))}
</div>
);
};
export default Tabs;
export default TabSelectors;

View File

@ -2,7 +2,7 @@ import { useState } from "react";
import { useIntl } from "react-intl";
import SuggestedProfiles from "@/Components/SuggestedProfiles";
import { Tab, TabElement } from "@/Components/Tabs/Tabs";
import { Tab, TabSelector } from "@/Components/TabSelectors/TabSelectors";
import TrendingNotes from "@/Components/Trending/TrendingPosts";
import TrendingUsers from "@/Components/Trending/TrendingUsers";
@ -32,7 +32,7 @@ export default function Discover() {
<>
<div className="tabs p">
{[Tabs.Follows, Tabs.Posts, Tabs.Profiles].map(a => (
<TabElement key={a.value} tab={tab} setTab={setTab} t={a} />
<TabSelector key={a.value} tab={tab} setTab={setTab} t={a} />
))}
</div>
{renderTab()}

View File

@ -7,7 +7,7 @@ import { Bar, BarChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recha
import { AsyncIcon } from "@/Components/Button/AsyncIcon";
import Icon from "@/Components/Icons/Icon";
import Tabs, { Tab } from "@/Components/Tabs/Tabs";
import TabSelectors, { Tab } from "@/Components/TabSelectors/TabSelectors";
import { orderAscending } from "@/Utils";
import { Day } from "@/Utils/Const";
import { formatShort } from "@/Utils/Number";
@ -123,7 +123,11 @@ export default function NotificationSummary({ evs }: { evs: Array<TaggedNostrEve
{filterIcon(NotificationSummaryFilter.Mentions, "at-sign", "text-mention")}
</div>
</div>
<Tabs tabs={periodTabs} tab={unwrap(periodTabs.find(a => a.value === period))} setTab={t => setPeriod(t.value)} />
<TabSelectors
tabs={periodTabs}
tab={unwrap(periodTabs.find(a => a.value === period))}
setTab={t => setPeriod(t.value)}
/>
<div>
<ResponsiveContainer height={200}>
<BarChart data={Object.values(stats)} margin={{ left: 0, right: 0 }} style={{ userSelect: "none" }}>

View File

@ -1,29 +1,34 @@
import "./ProfilePage.css";
import { fetchNip05Pubkey, LNURL } from "@snort/shared";
import { CachedMetadata, EventKind, NostrPrefix, tryParseNostrLink } from "@snort/system";
import { CachedMetadata, NostrPrefix, tryParseNostrLink } from "@snort/system";
import { useUserProfile } from "@snort/system-react";
import { useEffect, useMemo, useState } from "react";
import { useLocation, useNavigate, useParams } from "react-router-dom";
import Note from "@/Components/Event/EventComponent";
import Timeline from "@/Components/Feed/Timeline";
import { ProxyImg } from "@/Components/ProxyImg";
import { SpotlightMediaModal } from "@/Components/Spotlight/SpotlightMedia";
import { Tab, TabElement } from "@/Components/Tabs/Tabs";
import { Tab, TabSelector } from "@/Components/TabSelectors/TabSelectors";
import BlockList from "@/Components/User/BlockList";
import FollowsList from "@/Components/User/FollowListBase";
import MutedList from "@/Components/User/MutedList";
import useFollowsFeed from "@/Feed/FollowsFeed";
import useHorizontalScroll from "@/Hooks/useHorizontalScroll";
import { useMuteList, usePinList } from "@/Hooks/useLists";
import { useMuteList } from "@/Hooks/useLists";
import useLogin from "@/Hooks/useLogin";
import useModeration from "@/Hooks/useModeration";
import AvatarSection from "@/Pages/Profile/AvatarSection";
import ProfileDetails from "@/Pages/Profile/ProfileDetails";
import ProfileTab from "@/Pages/Profile/ProfileTab";
import { BookMarksTab, FollowersTab, FollowsTab, RelaysTab, ZapsProfileTab } from "@/Pages/Profile/ProfileTabs";
import {
BookMarksTab,
FollowersTab,
FollowsTab,
RelaysTab,
ZapsProfileTab,
} from "@/Pages/Profile/ProfileTabComponents";
import ProfileTabSelectors from "@/Pages/Profile/ProfileTabSelectors";
import { ProfileTabType } from "@/Pages/Profile/ProfileTabType";
import { NotesTab } from "@/Pages/Root/NotesTab";
import { parseId, unwrap } from "@/Utils";
import { EmailRegex } from "@/Utils/Const";
@ -58,15 +63,17 @@ export default function ProfilePage({ id: propId, state }: ProfilePageProps) {
// feeds
const { blocked } = useModeration();
const pinned = usePinList(id);
const muted = useMuteList(id);
const follows = useFollowsFeed(id);
// tabs
const [tab, setTab] = useState<Tab>(ProfileTab.Notes);
const optionalTabs = [ProfileTab.Zaps, ProfileTab.Relays, ProfileTab.Bookmarks, ProfileTab.Muted].filter(a =>
unwrap(a),
) as Tab[];
const [tab, setTab] = useState<Tab>(ProfileTabSelectors.Notes);
const optionalTabs = [
ProfileTabSelectors.Zaps,
ProfileTabSelectors.Relays,
ProfileTabSelectors.Bookmarks,
ProfileTabSelectors.Muted,
].filter(a => unwrap(a)) as Tab[];
const horizontalScroll = useHorizontalScroll();
useEffect(() => {
@ -98,7 +105,7 @@ export default function ProfilePage({ id: propId, state }: ProfilePageProps) {
}
}
}
setTab(ProfileTab.Notes);
setTab(ProfileTabSelectors.Notes);
}, [id, propId, params]);
function tabContent() {
@ -106,35 +113,7 @@ export default function ProfilePage({ id: propId, state }: ProfilePageProps) {
switch (tab.value) {
case ProfileTabType.NOTES:
return (
<>
{pinned
.filter(a => a.kind === EventKind.TextNote)
.map(n => {
return (
<Note
key={`pinned-${n.id}`}
data={n}
options={{ showTime: false, showPinned: true, canUnpin: isMe }}
/>
);
})}
<Timeline
key={id}
subject={{
type: "pubkey",
items: [id],
discriminator: id.slice(0, 12),
relay: relays,
}}
postsOnly={false}
method={"LIMIT_UNTIL"}
loadMore={false}
ignoreModeration={true}
window={60 * 60 * 6}
/>
</>
);
return <NotesTab id={id} relays={relays} isMe={isMe} />;
case ProfileTabType.ZAPS: {
return <ZapsProfileTab id={id} />;
}
@ -163,8 +142,8 @@ export default function ProfilePage({ id: propId, state }: ProfilePageProps) {
}
}
function renderTab(v: Tab) {
return <TabElement key={v.value} t={v} tab={tab} setTab={setTab} />;
function renderTabSelector(v: Tab) {
return <TabSelector key={v.value} t={v} tab={tab} setTab={setTab} />;
}
const bannerWidth = Math.min(window.innerWidth, 940);
@ -189,9 +168,11 @@ export default function ProfilePage({ id: propId, state }: ProfilePageProps) {
</div>
<div className="main-content">
<div className="tabs p" ref={horizontalScroll}>
{[ProfileTab.Notes, ProfileTab.Followers, ProfileTab.Follows].map(renderTab)}
{optionalTabs.map(renderTab)}
{isMe && blocked.length > 0 && renderTab(ProfileTab.Blocked)}
{[ProfileTabSelectors.Notes, ProfileTabSelectors.Followers, ProfileTabSelectors.Follows].map(
renderTabSelector,
)}
{optionalTabs.map(renderTabSelector)}
{isMe && blocked.length > 0 && renderTabSelector(ProfileTabSelectors.Blocked)}
</div>
</div>
<div className="main-content">{tabContent()}</div>

View File

@ -1,7 +1,10 @@
import { HexKey, NostrLink, NostrPrefix } from "@snort/system";
import { EventKind, HexKey, NostrLink, NostrPrefix } from "@snort/system";
import { useMemo } from "react";
import { FormattedMessage } from "react-intl";
import { Note } from "@/Components/Event/Note/Note";
import Zap from "@/Components/Event/Zap";
import Timeline from "@/Components/Feed/Timeline";
import RelaysMetadata from "@/Components/Relay/RelaysMetadata";
import Bookmarks from "@/Components/User/Bookmarks";
import FollowsList from "@/Components/User/FollowListBase";
@ -9,7 +12,7 @@ import useFollowersFeed from "@/Feed/FollowersFeed";
import useFollowsFeed from "@/Feed/FollowsFeed";
import useRelaysFeed from "@/Feed/RelaysFeed";
import useZapsFeed from "@/Feed/ZapsFeed";
import { useBookmarkList } from "@/Hooks/useLists";
import { useBookmarkList, usePinList } from "@/Hooks/useLists";
import messages from "@/Pages/messages";
import { formatShort } from "@/Utils/Number";
@ -47,3 +50,31 @@ export function BookMarksTab({ id }: { id: HexKey }) {
const bookmarks = useBookmarkList(id);
return <Bookmarks pubkey={id} bookmarks={bookmarks} />;
}
export function NotesTab({ id, relays, isMe }: { id: HexKey; relays?: Array<string>; isMe: boolean }) {
const pinned = usePinList(id);
const options = useMemo(() => ({ showTime: false, showPinned: true, canUnpin: isMe }), [isMe]);
return (
<>
{pinned
.filter(a => a.kind === EventKind.TextNote)
.map(n => {
return <Note key={`pinned-${n.id}`} data={n} options={options} />;
})}
<Timeline
key={id}
subject={{
type: "pubkey",
items: [id],
discriminator: id.slice(0, 12),
relay: relays,
}}
postsOnly={false}
method={"LIMIT_UNTIL"}
loadMore={false}
ignoreModeration={true}
window={60 * 60 * 6}
/>
</>
);
}

View File

@ -1,10 +1,10 @@
import { FormattedMessage } from "react-intl";
import Icon from "@/Components/Icons/Icon";
import { Tab } from "@/Components/Tabs/Tabs";
import { Tab } from "@/Components/TabSelectors/TabSelectors";
import { ProfileTabType } from "@/Pages/Profile/ProfileTabType";
const ProfileTab = {
const ProfileTabSelectors = {
Notes: {
text: (
<>
@ -88,4 +88,4 @@ const ProfileTab = {
},
} as { [key: string]: Tab };
export default ProfileTab;
export default ProfileTabSelectors;

View File

@ -3,7 +3,7 @@ import { FormattedMessage, useIntl } from "react-intl";
import { useNavigate, useParams } from "react-router-dom";
import Timeline from "@/Components/Feed/Timeline";
import Tabs, { Tab } from "@/Components/Tabs/Tabs";
import TabSelectors, { Tab } from "@/Components/TabSelectors/TabSelectors";
import TrendingNotes from "@/Components/Trending/TrendingPosts";
import TrendingUsers from "@/Components/Trending/TrendingUsers";
import FollowListBase from "@/Components/User/FollowListBase";
@ -107,7 +107,7 @@ const SearchPage = () => {
value={search}
onChange={e => setSearch(e.target.value)}
/>
<Tabs tabs={SearchTab} tab={tab} setTab={setTab} />
<TabSelectors tabs={SearchTab} tab={tab} setTab={setTab} />
</div>
{tabContent()}
</div>