add trending stuff to right column

This commit is contained in:
Martti Malmi 2023-11-22 14:06:42 +02:00
parent f9d0318f36
commit f9e7bc8558
9 changed files with 68 additions and 40 deletions

View File

@ -10,7 +10,7 @@ import Icon from "@/Icons/Icon";
import { useNoteCreator } from "@/State/NoteCreator"; import { useNoteCreator } from "@/State/NoteCreator";
import { NoteCreator } from "./NoteCreator"; import { NoteCreator } from "./NoteCreator";
export const NoteCreatorButton = ({ className, alwaysShow }: { className?: string, alwaysShow?: boolean }) => { export const NoteCreatorButton = ({ className, alwaysShow }: { className?: string; alwaysShow?: boolean }) => {
const buttonRef = useRef<HTMLButtonElement>(null); const buttonRef = useRef<HTMLButtonElement>(null);
const location = useLocation(); const location = useLocation();
const { readonly } = useLogin(s => ({ readonly: s.readonly })); const { readonly } = useLogin(s => ({ readonly: s.readonly }));

View File

@ -6,7 +6,7 @@ import { ErrorOrOffline } from "./ErrorOrOffline";
import { HashTagHeader } from "@/Pages/HashTagsPage"; import { HashTagHeader } from "@/Pages/HashTagsPage";
import { useLocale } from "@/IntlProvider"; import { useLocale } from "@/IntlProvider";
export default function TrendingHashtags({ title }: { title?: ReactNode }) { export default function TrendingHashtags({ title, count = 5 }: { title?: ReactNode; count?: number }) {
const [hashtags, setHashtags] = useState<Array<{ hashtag: string; posts: number }>>(); const [hashtags, setHashtags] = useState<Array<{ hashtag: string; posts: number }>>();
const [error, setError] = useState<Error>(); const [error, setError] = useState<Error>();
const { lang } = useLocale(); const { lang } = useLocale();
@ -14,7 +14,7 @@ export default function TrendingHashtags({ title }: { title?: ReactNode }) {
async function loadTrendingHashtags() { async function loadTrendingHashtags() {
const api = new NostrBandApi(); const api = new NostrBandApi();
const rsp = await api.trendingHashtags(lang); const rsp = await api.trendingHashtags(lang);
setHashtags(rsp.hashtags); setHashtags(rsp.hashtags.slice(0, count)); // Limit the number of hashtags to the count
} }
useEffect(() => { useEffect(() => {

View File

@ -9,7 +9,8 @@ import { ErrorOrOffline } from "@/Element/ErrorOrOffline";
import { useLocale } from "@/IntlProvider"; import { useLocale } from "@/IntlProvider";
import useModeration from "@/Hooks/useModeration"; import useModeration from "@/Hooks/useModeration";
export default function TrendingNotes() { export default function TrendingNotes({ count = Infinity }) {
// Added count prop with a default value
const [posts, setPosts] = useState<Array<NostrEvent>>(); const [posts, setPosts] = useState<Array<NostrEvent>>();
const [error, setError] = useState<Error>(); const [error, setError] = useState<Error>();
const { lang } = useLocale(); const { lang } = useLocale();
@ -37,6 +38,7 @@ export default function TrendingNotes() {
<> <>
{posts {posts
.filter(a => !isEventMuted(a)) .filter(a => !isEventMuted(a))
.slice(0, count) // Limit the number of posts displayed
.map(e => ( .map(e => (
<Note key={e.id} data={e as TaggedNostrEvent} related={related?.data ?? []} depth={0} /> <Note key={e.id} data={e as TaggedNostrEvent} related={related?.data ?? []} depth={0} />
))} ))}

View File

@ -6,14 +6,14 @@ import PageSpinner from "@/Element/PageSpinner";
import NostrBandApi from "@/External/NostrBand"; import NostrBandApi from "@/External/NostrBand";
import { ErrorOrOffline } from "./ErrorOrOffline"; import { ErrorOrOffline } from "./ErrorOrOffline";
export default function TrendingUsers({ title }: { title?: ReactNode }) { export default function TrendingUsers({ title, count = 5 }: { title?: ReactNode; count?: number }) {
const [userList, setUserList] = useState<HexKey[]>(); const [userList, setUserList] = useState<HexKey[]>();
const [error, setError] = useState<Error>(); const [error, setError] = useState<Error>();
async function loadTrendingUsers() { async function loadTrendingUsers() {
const api = new NostrBandApi(); const api = new NostrBandApi();
const users = await api.trendingProfiles(); const users = await api.trendingProfiles();
const keys = users.profiles.map(a => a.pubkey); const keys = users.profiles.map(a => a.pubkey).slice(0, count); // Limit the user list to the count
setUserList(keys); setUserList(keys);
} }

View File

@ -1,12 +1,12 @@
import { LogoHeader } from "./LogoHeader"; import { LogoHeader } from "./LogoHeader";
import {Link, useNavigate} from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import Icon from "@/Icons/Icon"; import Icon from "@/Icons/Icon";
import {ProfileLink} from "../../Element/User/ProfileLink"; import { ProfileLink } from "../../Element/User/ProfileLink";
import Avatar from "../../Element/User/Avatar"; import Avatar from "../../Element/User/Avatar";
import useLogin from "../../Hooks/useLogin"; import useLogin from "../../Hooks/useLogin";
import {useUserProfile} from "@snort/system-react"; import { useUserProfile } from "@snort/system-react";
import {NoteCreatorButton} from "../../Element/Event/NoteCreatorButton"; import { NoteCreatorButton } from "../../Element/Event/NoteCreatorButton";
import {FormattedMessage} from "react-intl"; import { FormattedMessage } from "react-intl";
const MENU_ITEMS = [ const MENU_ITEMS = [
{ {
@ -49,7 +49,7 @@ export default function NavSidebar() {
<div className="flex flex-col items-center xl:items-start font-bold text-lg"> <div className="flex flex-col items-center xl:items-start font-bold text-lg">
{MENU_ITEMS.map(item => { {MENU_ITEMS.map(item => {
if (!item.nonLoggedIn && !publicKey) { if (!item.nonLoggedIn && !publicKey) {
return ''; return "";
} }
return ( return (
<NavLink <NavLink
@ -87,7 +87,9 @@ export default function NavSidebar() {
</div> </div>
</ProfileLink> </ProfileLink>
</> </>
) : ''} ) : (
""
)}
</div> </div>
); );
} }

View File

@ -1,11 +1,33 @@
import SearchBox from "../../Element/SearchBox"; import SearchBox from "@/Element/SearchBox";
import TrendingUsers from "@/Element/TrendingUsers";
import TrendingHashtags from "@/Element/TrendingHashtags";
import TrendingNotes from "@/Element/TrendingPosts";
import { FormattedMessage } from "react-intl";
export default function RightColumn() { export default function RightColumn() {
return ( return (
<div className="flex-col hidden lg:flex lg:w-1/3 sticky top-0 h-screen p-2 border-l border-neutral-900"> <div className="flex-col hidden lg:flex lg:w-1/3 sticky top-0 h-screen p-2 border-l border-neutral-900 gap-8">
<div> <div>
<SearchBox /> <SearchBox />
</div> </div>
<div>
<div className="font-bold">
<FormattedMessage defaultMessage="Trending hashtags" id="CbM2hK" />
</div>
<TrendingHashtags count={5} />
</div>
<div>
<div className="font-bold">
<FormattedMessage defaultMessage="Trending notes" id="6k7xfM" />
</div>
<TrendingNotes count={5} />
</div>
<div>
<div className="font-bold">
<FormattedMessage defaultMessage="Trending users" id="arZnG2" />
</div>
<TrendingUsers count={5} />
</div>
</div> </div>
); );
} }

View File

@ -16,9 +16,12 @@ const SettingsIndex = () => {
const pageWidth = usePageWidth(); const pageWidth = usePageWidth();
const sub = getCurrentSubscription(LoginStore.allSubscriptions()); const sub = getCurrentSubscription(LoginStore.allSubscriptions());
const handleNavigate = useCallback((path) => { const handleNavigate = useCallback(
navigate(path); path => {
}, [navigate]); navigate(path);
},
[navigate],
);
const handleLogout = useCallback(() => { const handleLogout = useCallback(() => {
logout(login.id); logout(login.id);
@ -31,7 +34,10 @@ const SettingsIndex = () => {
} }
}, [location, navigate, pageWidth]); }, [location, navigate, pageWidth]);
const [hideMenu, hideContent] = [location.pathname !== "/settings" && pageWidth < 768, location.pathname === "/settings" && pageWidth < 768]; const [hideMenu, hideContent] = [
location.pathname !== "/settings" && pageWidth < 768,
location.pathname === "/settings" && pageWidth < 768,
];
const menuItems = [ const menuItems = [
{ icon: "profile", message: messages.Profile, path: "profile" }, { icon: "profile", message: messages.Profile, path: "profile" },
@ -43,7 +49,7 @@ const SettingsIndex = () => {
{ icon: "wallet", message: "Wallet", id: "3yk8fB", path: "wallet" }, { icon: "wallet", message: "Wallet", id: "3yk8fB", path: "wallet" },
{ icon: "heart", message: messages.Donate, path: "/donate" }, { icon: "heart", message: messages.Donate, path: "/donate" },
{ icon: "hard-drive", message: "Cache", id: "DBiVK1", path: "cache" }, { icon: "hard-drive", message: "Cache", id: "DBiVK1", path: "cache" },
{ icon: "profile", message: messages.SocialGraph, path: "/graph" } { icon: "profile", message: messages.SocialGraph, path: "/graph" },
]; ];
if (CONFIG.features.subscriptions) { if (CONFIG.features.subscriptions) {

View File

@ -57,9 +57,6 @@
"00LcfG": { "00LcfG": {
"defaultMessage": "Load more" "defaultMessage": "Load more"
}, },
"08zn6O": {
"defaultMessage": "Export Keys"
},
"0Azlrb": { "0Azlrb": {
"defaultMessage": "Manage" "defaultMessage": "Manage"
}, },
@ -159,9 +156,6 @@
"3tVy+Z": { "3tVy+Z": {
"defaultMessage": "{n} Followers" "defaultMessage": "{n} Followers"
}, },
"3yk8fB": {
"defaultMessage": "Wallet"
},
"450Fty": { "450Fty": {
"defaultMessage": "None" "defaultMessage": "None"
}, },
@ -234,6 +228,9 @@
"6ewQqw": { "6ewQqw": {
"defaultMessage": "Likes ({n})" "defaultMessage": "Likes ({n})"
}, },
"6k7xfM": {
"defaultMessage": "Trending notes"
},
"6uMqL1": { "6uMqL1": {
"defaultMessage": "Unpaid" "defaultMessage": "Unpaid"
}, },
@ -243,9 +240,6 @@
"712i26": { "712i26": {
"defaultMessage": "Proxy uses HODL invoices to forward the payment, which hides the pubkey of your node" "defaultMessage": "Proxy uses HODL invoices to forward the payment, which hides the pubkey of your node"
}, },
"7BX/yC": {
"defaultMessage": "Account Switcher"
},
"7UOvbT": { "7UOvbT": {
"defaultMessage": "Offline" "defaultMessage": "Offline"
}, },
@ -261,6 +255,9 @@
"8ED/4u": { "8ED/4u": {
"defaultMessage": "Reply To" "defaultMessage": "Reply To"
}, },
"8HJxXG": {
"defaultMessage": "Sign up"
},
"8QDesP": { "8QDesP": {
"defaultMessage": "Zap {n} sats" "defaultMessage": "Zap {n} sats"
}, },
@ -368,6 +365,9 @@
"CVWeJ6": { "CVWeJ6": {
"defaultMessage": "Trending People" "defaultMessage": "Trending People"
}, },
"CbM2hK": {
"defaultMessage": "Trending hashtags"
},
"CmZ9ls": { "CmZ9ls": {
"defaultMessage": "{n} Muted" "defaultMessage": "{n} Muted"
}, },
@ -729,9 +729,6 @@
"Qxv0B2": { "Qxv0B2": {
"defaultMessage": "You currently have {number} sats in your zap pool." "defaultMessage": "You currently have {number} sats in your zap pool."
}, },
"R/6nsx": {
"defaultMessage": "Subscription"
},
"R81upa": { "R81upa": {
"defaultMessage": "People you follow" "defaultMessage": "People you follow"
}, },
@ -940,6 +937,9 @@
"aWpBzj": { "aWpBzj": {
"defaultMessage": "Show more" "defaultMessage": "Show more"
}, },
"arZnG2": {
"defaultMessage": "Trending users"
},
"b12Goz": { "b12Goz": {
"defaultMessage": "Mnemonic" "defaultMessage": "Mnemonic"
}, },
@ -1458,9 +1458,6 @@
"wih7iJ": { "wih7iJ": {
"defaultMessage": "name is blocked" "defaultMessage": "name is blocked"
}, },
"wofVHy": {
"defaultMessage": "Moderation"
},
"wqyN/i": { "wqyN/i": {
"defaultMessage": "Find out more info about {service} at {link}" "defaultMessage": "Find out more info about {service} at {link}"
}, },

View File

@ -18,7 +18,6 @@
"/d6vEc": "Make your profile easier to find and share", "/d6vEc": "Make your profile easier to find and share",
"/n5KSF": "{n} ms", "/n5KSF": "{n} ms",
"00LcfG": "Load more", "00LcfG": "Load more",
"08zn6O": "Export Keys",
"0Azlrb": "Manage", "0Azlrb": "Manage",
"0BUTMv": "Search...", "0BUTMv": "Search...",
"0HFX0T": "Use Exact Location", "0HFX0T": "Use Exact Location",
@ -52,7 +51,6 @@
"3qnJlS": "You are voting with {amount} sats", "3qnJlS": "You are voting with {amount} sats",
"3t3kok": "{n,plural,=1{{n} new note} other{{n} new notes}}", "3t3kok": "{n,plural,=1{{n} new note} other{{n} new notes}}",
"3tVy+Z": "{n} Followers", "3tVy+Z": "{n} Followers",
"3yk8fB": "Wallet",
"450Fty": "None", "450Fty": "None",
"47FYwb": "Cancel", "47FYwb": "Cancel",
"4IPzdn": "Primary Developers", "4IPzdn": "Primary Developers",
@ -77,15 +75,16 @@
"6TfgXX": "{site} is an open source project built by passionate people in their free time", "6TfgXX": "{site} is an open source project built by passionate people in their free time",
"6bgpn+": "Not all clients support this, you may still receive some zaps as if zap splits was not configured", "6bgpn+": "Not all clients support this, you may still receive some zaps as if zap splits was not configured",
"6ewQqw": "Likes ({n})", "6ewQqw": "Likes ({n})",
"6k7xfM": "Trending notes",
"6uMqL1": "Unpaid", "6uMqL1": "Unpaid",
"7+Domh": "Notes", "7+Domh": "Notes",
"712i26": "Proxy uses HODL invoices to forward the payment, which hides the pubkey of your node", "712i26": "Proxy uses HODL invoices to forward the payment, which hides the pubkey of your node",
"7BX/yC": "Account Switcher",
"7UOvbT": "Offline", "7UOvbT": "Offline",
"7hp70g": "NIP-05", "7hp70g": "NIP-05",
"8/vBbP": "Reposts ({n})", "8/vBbP": "Reposts ({n})",
"89q5wc": "Confirm Reposts", "89q5wc": "Confirm Reposts",
"8ED/4u": "Reply To", "8ED/4u": "Reply To",
"8HJxXG": "Sign up",
"8QDesP": "Zap {n} sats", "8QDesP": "Zap {n} sats",
"8Rkoyb": "Recipient", "8Rkoyb": "Recipient",
"8Y6bZQ": "Invalid zap split: {input}", "8Y6bZQ": "Invalid zap split: {input}",
@ -121,6 +120,7 @@
"C8HhVE": "Suggested Follows", "C8HhVE": "Suggested Follows",
"CHTbO3": "Failed to load invoice", "CHTbO3": "Failed to load invoice",
"CVWeJ6": "Trending People", "CVWeJ6": "Trending People",
"CbM2hK": "Trending hashtags",
"CmZ9ls": "{n} Muted", "CmZ9ls": "{n} Muted",
"CsCUYo": "{n} sats", "CsCUYo": "{n} sats",
"Cu/K85": "Translated from {lang}", "Cu/K85": "Translated from {lang}",
@ -240,7 +240,6 @@
"QDFTjG": "{n} Relays", "QDFTjG": "{n} Relays",
"QWhotP": "Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)", "QWhotP": "Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)",
"Qxv0B2": "You currently have {number} sats in your zap pool.", "Qxv0B2": "You currently have {number} sats in your zap pool.",
"R/6nsx": "Subscription",
"R81upa": "People you follow", "R81upa": "People you follow",
"RSr2uB": "Username must only contain lowercase letters and numbers", "RSr2uB": "Username must only contain lowercase letters and numbers",
"RahCRH": "Expired", "RahCRH": "Expired",
@ -309,6 +308,7 @@
"aHje0o": "Name or nym", "aHje0o": "Name or nym",
"aMaLBK": "Supported Extensions", "aMaLBK": "Supported Extensions",
"aWpBzj": "Show more", "aWpBzj": "Show more",
"arZnG2": "Trending users",
"b12Goz": "Mnemonic", "b12Goz": "Mnemonic",
"b5vAk0": "Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address", "b5vAk0": "Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address",
"bLZL5a": "Get Address", "bLZL5a": "Get Address",
@ -480,7 +480,6 @@
"wSZR47": "Submit", "wSZR47": "Submit",
"wWLwvh": "Anon", "wWLwvh": "Anon",
"wih7iJ": "name is blocked", "wih7iJ": "name is blocked",
"wofVHy": "Moderation",
"wqyN/i": "Find out more info about {service} at {link}", "wqyN/i": "Find out more info about {service} at {link}",
"wtLjP6": "Copy ID", "wtLjP6": "Copy ID",
"x/Fx2P": "Fund the services that you use by splitting a portion of all your zaps into a pool of funds!", "x/Fx2P": "Fund the services that you use by splitting a portion of all your zaps into a pool of funds!",