feat: follow sets page
This commit is contained in:
@ -12,6 +12,8 @@ import usePreferences from "@/Hooks/usePreferences";
|
||||
import { dedupe, findTag, getDisplayName, hexToBech32 } from "@/Utils";
|
||||
import { useWallet } from "@/Wallet";
|
||||
|
||||
import { ProxyImg } from "../ProxyImg";
|
||||
|
||||
export default function PubkeyList({ ev, className }: { ev: NostrEvent; className?: string }) {
|
||||
const wallet = useWallet();
|
||||
const defaultZapAmount = usePreferences(s => s.defaultZapAmount);
|
||||
@ -62,29 +64,33 @@ export default function PubkeyList({ ev, className }: { ev: NostrEvent; classNam
|
||||
}
|
||||
}
|
||||
|
||||
const picture = findTag(ev, "image");
|
||||
return (
|
||||
<FollowListBase
|
||||
pubkeys={ids}
|
||||
className={className}
|
||||
title={findTag(ev, "title") ?? findTag(ev, "d")}
|
||||
actions={
|
||||
<>
|
||||
<AsyncButton className="mr5 secondary" onClick={() => zapAll()}>
|
||||
<FormattedMessage
|
||||
defaultMessage="Zap all {n} sats"
|
||||
id="IVbtTS"
|
||||
values={{
|
||||
n: <FormattedNumber value={defaultZapAmount * ids.length} />,
|
||||
}}
|
||||
/>
|
||||
</AsyncButton>
|
||||
</>
|
||||
}
|
||||
profilePreviewProps={{
|
||||
options: {
|
||||
about: true,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<>
|
||||
{picture && <ProxyImg src={picture} className="br max-h-44 w-full object-cover mb-4" />}
|
||||
<FollowListBase
|
||||
pubkeys={ids}
|
||||
className={className}
|
||||
title={findTag(ev, "title") ?? findTag(ev, "d")}
|
||||
actions={
|
||||
<>
|
||||
<AsyncButton className="mr5 secondary" onClick={() => zapAll()}>
|
||||
<FormattedMessage
|
||||
defaultMessage="Zap all {n} sats"
|
||||
id="IVbtTS"
|
||||
values={{
|
||||
n: <FormattedNumber value={defaultZapAmount * ids.length} />,
|
||||
}}
|
||||
/>
|
||||
</AsyncButton>
|
||||
</>
|
||||
}
|
||||
profilePreviewProps={{
|
||||
options: {
|
||||
about: true,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ export default memo(function EventComponent(props: NoteProps) {
|
||||
case EventKind.ZapstrTrack:
|
||||
content = <ZapstrEmbed ev={ev} />;
|
||||
break;
|
||||
case EventKind.StarterPackSet:
|
||||
case EventKind.FollowSet:
|
||||
case EventKind.ContactList:
|
||||
content = <PubkeyList ev={ev} className={className} />;
|
||||
|
@ -61,17 +61,6 @@ export function rootTabItems(base: string, pubKey: string | undefined, tags: Arr
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
tab: "suggested",
|
||||
path: `${base}/suggested`,
|
||||
show: Boolean(pubKey),
|
||||
element: (
|
||||
<>
|
||||
<Icon name="thumbs-up" />
|
||||
<FormattedMessage defaultMessage="Suggested Follows" />
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
tab: "trending/hashtags",
|
||||
path: `${base}/trending/hashtags`,
|
||||
@ -105,6 +94,17 @@ export function rootTabItems(base: string, pubKey: string | undefined, tags: Arr
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
tab: "follow-sets",
|
||||
path: `${base}/follow-sets`,
|
||||
show: true,
|
||||
element: (
|
||||
<>
|
||||
<Icon name="thumbs-up" />
|
||||
<FormattedMessage defaultMessage="Follow Sets" />
|
||||
</>
|
||||
),
|
||||
},
|
||||
] as Array<{
|
||||
tab: RootTabRoutePath;
|
||||
path: string;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { HexKey, NostrPrefix } from "@snort/system";
|
||||
import { NostrPrefix } from "@snort/system";
|
||||
import { useState } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
@ -61,7 +61,7 @@ export default function SuggestedProfiles() {
|
||||
</select>
|
||||
</div>
|
||||
<FollowListBase
|
||||
pubkeys={userList as HexKey[]}
|
||||
pubkeys={userList}
|
||||
profilePreviewProps={{
|
||||
options: {
|
||||
about: true,
|
||||
|
@ -1,16 +1,16 @@
|
||||
import { HexKey } from "@snort/system";
|
||||
import classNames from "classnames";
|
||||
import { ReactNode } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import ProfilePreview, { ProfilePreviewProps } from "@/Components/User/ProfilePreview";
|
||||
import useFollowsControls from "@/Hooks/useFollowControls";
|
||||
import useLogin from "@/Hooks/useLogin";
|
||||
import useWoT from "@/Hooks/useWoT";
|
||||
|
||||
import AsyncButton from "../Button/AsyncButton";
|
||||
import messages from "../messages";
|
||||
|
||||
export interface FollowListBaseProps {
|
||||
pubkeys: HexKey[];
|
||||
pubkeys: string[];
|
||||
title?: ReactNode;
|
||||
showFollowAll?: boolean;
|
||||
className?: string;
|
||||
@ -27,7 +27,8 @@ export default function FollowListBase({
|
||||
profilePreviewProps,
|
||||
}: FollowListBaseProps) {
|
||||
const control = useFollowsControls();
|
||||
const login = useLogin();
|
||||
const readonly = useLogin(s => s.readonly);
|
||||
const wot = useWoT();
|
||||
|
||||
async function followAll() {
|
||||
await control.addFollow(pubkeys);
|
||||
@ -37,15 +38,17 @@ export default function FollowListBase({
|
||||
<div className="flex flex-col gap-2">
|
||||
{(showFollowAll ?? true) && (
|
||||
<div className="flex items-center">
|
||||
<div className="grow font-bold">{title}</div>
|
||||
<div className="grow font-bold text-xl">{title}</div>
|
||||
{actions}
|
||||
<AsyncButton className="transparent" type="button" onClick={() => followAll()} disabled={login.readonly}>
|
||||
<FormattedMessage {...messages.FollowAll} />
|
||||
<AsyncButton className="transparent" type="button" onClick={() => followAll()} disabled={readonly}>
|
||||
<FormattedMessage defaultMessage="Follow All" />
|
||||
</AsyncButton>
|
||||
</div>
|
||||
)}
|
||||
<div className={className}>
|
||||
{pubkeys?.slice(0, 20).map(a => <ProfilePreview pubkey={a} key={a} {...profilePreviewProps} />)}
|
||||
<div className={classNames("flex flex-col gap-2", className)}>
|
||||
{wot.sortPubkeys(pubkeys).map(a => (
|
||||
<ProfilePreview pubkey={a} key={a} {...profilePreviewProps} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -277,6 +277,8 @@ export default function KindName({ kind }: { kind: number }) {
|
||||
return <FormattedMessage defaultMessage="Community Definition" />;
|
||||
case 38383:
|
||||
return <FormattedMessage defaultMessage="Peer-to-peer Order events" />;
|
||||
case 39089:
|
||||
return <FormattedMessage defaultMessage="Starter Pack" />;
|
||||
case 39701:
|
||||
return <FormattedMessage defaultMessage="Web bookmarks" />;
|
||||
default:
|
||||
|
Reference in New Issue
Block a user