From bab713c83a213f1e4efa1b9a227ab3b04c058570 Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Tue, 7 Feb 2023 16:33:23 +0100 Subject: [PATCH 01/18] feat: read nip-58 badges --- README.md | 3 +- packages/app/src/Element/BadgeList.css | 29 ++++++++ packages/app/src/Element/BadgeList.tsx | 70 ++++++++++++++++++ packages/app/src/Element/SendSats.tsx | 14 +--- packages/app/src/Element/Username.tsx | 24 +++++++ packages/app/src/Element/Zap.tsx | 8 +-- packages/app/src/Feed/BadgesFeed.ts | 99 ++++++++++++++++++++++++++ packages/app/src/Pages/ProfilePage.css | 20 +++++- packages/app/src/Pages/ProfilePage.tsx | 5 ++ packages/app/src/Util.ts | 19 +++++ packages/nostr/src/legacy/EventKind.ts | 3 + packages/nostr/src/legacy/index.ts | 1 + 12 files changed, 273 insertions(+), 22 deletions(-) create mode 100644 packages/app/src/Element/BadgeList.css create mode 100644 packages/app/src/Element/BadgeList.tsx create mode 100644 packages/app/src/Element/Username.tsx create mode 100644 packages/app/src/Feed/BadgesFeed.ts diff --git a/README.md b/README.md index dc54610d..4ffdb560 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Snort supports the following NIP's: - [ ] NIP-42: Authentication of clients to relays - [x] NIP-50: Search - [x] NIP-51: Lists +- [x] NIP-58: Badges - [x] NIP-65: Relay List Metadata ### Running @@ -60,4 +61,4 @@ yarn workspace @snort/app intl-extract yarn workspace @snort/app intl-compile ``` -This will create the source file `packages/app/src/translations/en.json` \ No newline at end of file +This will create the source file `packages/app/src/translations/en.json` diff --git a/packages/app/src/Element/BadgeList.css b/packages/app/src/Element/BadgeList.css new file mode 100644 index 00000000..fe173a8e --- /dev/null +++ b/packages/app/src/Element/BadgeList.css @@ -0,0 +1,29 @@ +.badge-list { + margin-top: 4px; + display: flex; + align-items: center; +} + +.badge-item { + width: 32px; + height: 32px; + object-fit: contain; +} + +.badge-item:not(:last-child) { + margin-right: 4px; +} + +.badge-info { + margin-left: 12px; + display: flex; + flex-direction: column; +} + +.badge-info p { + margin: 0; +} + +.badge-info h3 { + margin: 0; +} diff --git a/packages/app/src/Element/BadgeList.tsx b/packages/app/src/Element/BadgeList.tsx new file mode 100644 index 00000000..95a6a14e --- /dev/null +++ b/packages/app/src/Element/BadgeList.tsx @@ -0,0 +1,70 @@ +import "./BadgeList.css"; + +import { useState } from "react"; +import { FormattedMessage } from "react-intl"; + +import { TaggedRawEvent } from "@snort/nostr"; + +import Icon from "Icons/Icon"; +import Modal from "Element/Modal"; +import Username from "Element/Username"; +import { findTag } from "Util"; + +export default function BadgeList({ badges }: { badges: TaggedRawEvent[] }) { + const [showModal, setShowModal] = useState(false); + const badgeMetadata = badges.map(b => { + const thumb = findTag(b, "thumb"); + const image = findTag(b, "image"); + const name = findTag(b, "name"); + const description = findTag(b, "description"); + return { + id: b.id, + pubkey: b.pubkey, + name, + description, + img: thumb || image, + }; + }); + return ( + <> +
setShowModal(!showModal)}> + {badgeMetadata.map(({ id, name, img }) => ( + {name} + ))} +
+ {showModal && ( + setShowModal(false)}> +
+
setShowModal(false)}> + +
+
+

+ +

+
+
+ {badgeMetadata.map(({ id, name, pubkey, description, img }) => { + return ( +
+ {name} +
+

{name}

+

{description}

+

+ setShowModal(false)} /> }} + /> +

+
+
+ ); + })} +
+
+
+ )} + + ); +} diff --git a/packages/app/src/Element/SendSats.tsx b/packages/app/src/Element/SendSats.tsx index d216c653..c0d8f255 100644 --- a/packages/app/src/Element/SendSats.tsx +++ b/packages/app/src/Element/SendSats.tsx @@ -13,7 +13,7 @@ import Modal from "Element/Modal"; import QrCode from "Element/QrCode"; import Copy from "Element/Copy"; import { LNURL, LNURLError, LNURLErrorCode, LNURLInvoice, LNURLSuccessAction } from "LNURL"; -import { debounce } from "Util"; +import { chunks, debounce } from "Util"; import messages from "./messages"; import { useWallet } from "Wallet"; @@ -37,18 +37,6 @@ export interface SendSatsProps { author?: HexKey; } -function chunks(arr: T[], length: number) { - const result = []; - let idx = 0; - let n = arr.length / length; - while (n > 0) { - result.push(arr.slice(idx, idx + length)); - idx += length; - n -= 1; - } - return result; -} - export default function SendSats(props: SendSatsProps) { const onClose = props.onClose || (() => undefined); const { note, author, target } = props; diff --git a/packages/app/src/Element/Username.tsx b/packages/app/src/Element/Username.tsx new file mode 100644 index 00000000..989890f9 --- /dev/null +++ b/packages/app/src/Element/Username.tsx @@ -0,0 +1,24 @@ +import { MouseEvent } from "react"; +import { useNavigate, Link } from "react-router-dom"; + +import { HexKey } from "@snort/nostr"; + +import { useUserProfile } from "Hooks/useUserProfile"; +import { profileLink } from "Util"; + +export default function Username({ pubkey, onLinkVisit }: { pubkey: HexKey; onLinkVisit(): void }) { + const user = useUserProfile(pubkey); + const navigate = useNavigate(); + + function onClick(ev: MouseEvent) { + ev.preventDefault(); + onLinkVisit(); + navigate(profileLink(pubkey)); + } + + return user ? ( + + {user.name || pubkey.slice(0, 12)} + + ) : null; +} diff --git a/packages/app/src/Element/Zap.tsx b/packages/app/src/Element/Zap.tsx index 5e403d2a..08a45452 100644 --- a/packages/app/src/Element/Zap.tsx +++ b/packages/app/src/Element/Zap.tsx @@ -9,16 +9,10 @@ import { formatShort } from "Number"; import Text from "Element/Text"; import ProfileImage from "Element/ProfileImage"; import { RootState } from "State/Store"; +import { findTag } from "Util"; import messages from "./messages"; -function findTag(e: TaggedRawEvent, tag: string) { - const maybeTag = e.tags.find(evTag => { - return evTag[0] === tag; - }); - return maybeTag && maybeTag[1]; -} - function getInvoice(zap: TaggedRawEvent) { const bolt11 = findTag(zap, "bolt11"); if (!bolt11) { diff --git a/packages/app/src/Feed/BadgesFeed.ts b/packages/app/src/Feed/BadgesFeed.ts new file mode 100644 index 00000000..95b2a894 --- /dev/null +++ b/packages/app/src/Feed/BadgesFeed.ts @@ -0,0 +1,99 @@ +import { useMemo } from "react"; +import { TaggedRawEvent, EventKind, HexKey, Lists, Subscriptions } from "@snort/nostr"; +import useSubscription from "Feed/Subscription"; +import { unwrap, findTag, chunks } from "Util"; + +type BadgeAwards = { + pubkeys: string[]; + ds: string[]; +}; + +export default function useProfileBadges(pubkey?: HexKey) { + const sub = useMemo(() => { + if (!pubkey) return null; + const s = new Subscriptions(); + s.Id = `profile_badges:${pubkey.slice(0, 12)}`; + s.Kinds = new Set([EventKind.ProfileBadges]); + s.DTags = new Set([Lists.Badges]); + s.Authors = new Set([pubkey]); + return s; + }, [pubkey]); + const profileBadges = useSubscription(sub, { leaveOpen: true, cache: false }); + + const profile = useMemo(() => { + const sorted = [...profileBadges.store.notes]; + sorted.sort((a, b) => b.created_at - a.created_at); + const last = sorted[0]; + if (last) { + return chunks( + last.tags.filter(t => t[0] === "a" || t[0] === "e"), + 2 + ).reduce((acc, [a, e]) => { + return { + ...acc, + [e[1]]: a[1], + }; + }, {}); + } + return {}; + }, [pubkey, profileBadges.store.notes]); + + const awardsSub = useMemo(() => { + if (!pubkey) return null; + const s = new Subscriptions(); + s.Id = `profile_awards:${pubkey.slice(0, 12)}`; + s.Kinds = new Set([EventKind.BadgeAward]); + s.Ids = new Set(Object.keys(profile)); + return s; + }, [pubkey, profileBadges.store.notes]); + + const awards = useSubscription(awardsSub); + + const { ds, pubkeys } = useMemo(() => { + return Object.values(profile).reduce( + (acc: BadgeAwards, addr) => { + const [, pubkey, d] = (addr as string).split(":"); + acc.pubkeys.push(pubkey); + acc.ds.push(d); + return acc; + }, + { pubkeys: [], ds: [] } as BadgeAwards + ) as BadgeAwards; + }, [profile]); + + const badgesSub = useMemo(() => { + if (!pubkey) return null; + const s = new Subscriptions(); + s.Id = `profile_awards:${pubkey.slice(0, 12)}`; + s.Kinds = new Set([EventKind.Badge]); + s.DTags = new Set(ds); + s.Authors = new Set(pubkeys); + return s; + }, [pubkey, profile]); + + const badges = useSubscription(badgesSub, { leaveOpen: true, cache: false }); + + const result = useMemo(() => { + return awards.store.notes + .map((award: TaggedRawEvent) => { + const [, pubkey, d] = + award.tags + .find(t => t[0] === "a") + ?.at(1) + ?.split(":") ?? []; + const badge = badges.store.notes.find(b => b.pubkey === pubkey && findTag(b, "d") === d); + + return { + award, + badge, + }; + }) + .filter( + ({ award, badge }) => + badge && award.pubkey === badge.pubkey && award.tags.find(t => t[0] === "p" && t[1] === pubkey) + ) + .map(({ badge }) => unwrap(badge)); + }, [pubkey, awards.store.notes, badges.store.notes]); + + return result; +} diff --git a/packages/app/src/Pages/ProfilePage.css b/packages/app/src/Pages/ProfilePage.css index a227217d..8dbb2509 100644 --- a/packages/app/src/Pages/ProfilePage.css +++ b/packages/app/src/Pages/ProfilePage.css @@ -75,7 +75,6 @@ .profile .nip05 { display: flex; font-size: 16px; - margin: 0 0 12px 0; } .profile-wrapper > .avatar-wrapper { @@ -196,6 +195,10 @@ align-items: center; } +.profile .copy { + margin-top: 12px; +} + .qr-modal .modal-body { width: unset; margin-top: -120px; @@ -255,3 +258,18 @@ .profile .nip05 .domain { display: unset; } + +.badge-card .badge-icon { + width: 48px; + height: 48px; + margin-right: 0.3em; +} + +.badge-card .header { + align-items: center; + flex-direction: row; +} + +.badge-card .body { + margin-bottom: 0; +} diff --git a/packages/app/src/Pages/ProfilePage.tsx b/packages/app/src/Pages/ProfilePage.tsx index 98155a6e..51905a86 100644 --- a/packages/app/src/Pages/ProfilePage.tsx +++ b/packages/app/src/Pages/ProfilePage.tsx @@ -18,6 +18,7 @@ import usePinnedFeed from "Feed/PinnedFeed"; import useBookmarkFeed from "Feed/BookmarkFeed"; import useFollowersFeed from "Feed/FollowersFeed"; import useFollowsFeed from "Feed/FollowsFeed"; +import useProfileBadges from "Feed/BadgesFeed"; import { useUserProfile } from "Hooks/useUserProfile"; import useModeration from "Hooks/useModeration"; import useZapsFeed from "Feed/ZapsFeed"; @@ -39,6 +40,7 @@ import { RootState } from "State/Store"; import FollowsYou from "Element/FollowsYou"; import QrCode from "Element/QrCode"; import Modal from "Element/Modal"; +import BadgeList from "Element/BadgeList"; import { ProxyImg } from "Element/ProxyImg"; import useHorizontalScroll from "Hooks/useHorizontalScroll"; import messages from "./messages"; @@ -77,6 +79,7 @@ export default function ProfilePage() { const website_url = user?.website && !user.website.startsWith("http") ? "https://" + user.website : user?.website || ""; // feeds + const badges = useProfileBadges(id); const { blocked } = useModeration(); const { notes: pinned, related: pinRelated } = usePinnedFeed(id); const { notes: bookmarks, related: bookmarkRelated } = useBookmarkFeed(id); @@ -126,6 +129,7 @@ export default function ProfilePage() { {user?.nip05 && } + {links()} @@ -256,6 +260,7 @@ export default function ProfilePage() { {showProfileQr && ( setShowProfileQr(false)}> + (arr: T[], length: number) { + const result = []; + let idx = 0; + let n = arr.length / length; + while (n > 0) { + result.push(arr.slice(idx, idx + length)); + idx += length; + n -= 1; + } + return result; +} + +export function findTag(e: TaggedRawEvent, tag: string) { + const maybeTag = e.tags.find(evTag => { + return evTag[0] === tag; + }); + return maybeTag && maybeTag[1]; +} diff --git a/packages/nostr/src/legacy/EventKind.ts b/packages/nostr/src/legacy/EventKind.ts index 5b4bb0d2..b8d1e79b 100644 --- a/packages/nostr/src/legacy/EventKind.ts +++ b/packages/nostr/src/legacy/EventKind.ts @@ -8,12 +8,15 @@ enum EventKind { Deletion = 5, // NIP-09 Repost = 6, // NIP-18 Reaction = 7, // NIP-25 + BadgeAward = 8, // NIP-58 Relays = 10002, // NIP-65 Ephemeral = 20_000, Auth = 22242, // NIP-42 PubkeyLists = 30000, // NIP-51a NoteLists = 30001, // NIP-51b TagLists = 30002, // NIP-51c + Badge = 30009, // NIP-58 + ProfileBadges = 30008, // NIP-58 ZapRequest = 9734, // NIP 57 ZapReceipt = 9735, // NIP 57 } diff --git a/packages/nostr/src/legacy/index.ts b/packages/nostr/src/legacy/index.ts index 735dc7dd..b52f16ed 100644 --- a/packages/nostr/src/legacy/index.ts +++ b/packages/nostr/src/legacy/index.ts @@ -78,6 +78,7 @@ export enum Lists { Pinned = "pin", Bookmarked = "bookmark", Followed = "follow", + Badges = "profile_badges", } export interface FullRelaySettings { -- 2.45.2 From a050d87bcb20c4fa7b3e25af29727640b1565c66 Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Sat, 4 Mar 2023 19:06:03 +0100 Subject: [PATCH 02/18] max 7 badges --- packages/app/src/Element/BadgeList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/app/src/Element/BadgeList.tsx b/packages/app/src/Element/BadgeList.tsx index 95a6a14e..62166d24 100644 --- a/packages/app/src/Element/BadgeList.tsx +++ b/packages/app/src/Element/BadgeList.tsx @@ -28,7 +28,7 @@ export default function BadgeList({ badges }: { badges: TaggedRawEvent[] }) { return ( <>
setShowModal(!showModal)}> - {badgeMetadata.map(({ id, name, img }) => ( + {badgeMetadata.slice(0, 7).map(({ id, name, img }) => ( {name} ))}
-- 2.45.2 From dfff55b8de5e78d8a17e63e2642fb390d427016e Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Sat, 4 Mar 2023 19:10:01 +0100 Subject: [PATCH 03/18] fix: more margin --- packages/app/src/Element/BadgeList.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/app/src/Element/BadgeList.css b/packages/app/src/Element/BadgeList.css index fe173a8e..91fce4f9 100644 --- a/packages/app/src/Element/BadgeList.css +++ b/packages/app/src/Element/BadgeList.css @@ -11,7 +11,7 @@ } .badge-item:not(:last-child) { - margin-right: 4px; + margin-right: 8px; } .badge-info { -- 2.45.2 From 07b070d9b7f1fcbc41b90bbe5fc8a6a9d00aea22 Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Sat, 4 Mar 2023 23:46:56 +0100 Subject: [PATCH 04/18] img proxy --- packages/app/src/Element/BadgeList.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/app/src/Element/BadgeList.tsx b/packages/app/src/Element/BadgeList.tsx index 62166d24..7d2b518b 100644 --- a/packages/app/src/Element/BadgeList.tsx +++ b/packages/app/src/Element/BadgeList.tsx @@ -5,6 +5,7 @@ import { FormattedMessage } from "react-intl"; import { TaggedRawEvent } from "@snort/nostr"; +import { ProxyImg } from "Element/ProxyImg"; import Icon from "Icons/Icon"; import Modal from "Element/Modal"; import Username from "Element/Username"; @@ -29,7 +30,7 @@ export default function BadgeList({ badges }: { badges: TaggedRawEvent[] }) { <>
setShowModal(!showModal)}> {badgeMetadata.slice(0, 7).map(({ id, name, img }) => ( - {name} + ))}
{showModal && ( @@ -47,7 +48,7 @@ export default function BadgeList({ badges }: { badges: TaggedRawEvent[] }) { {badgeMetadata.map(({ id, name, pubkey, description, img }) => { return (
- {name} +

{name}

{description}

-- 2.45.2 From ba7fc5f6303033742a552e9daae6791b2a6586a9 Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Sun, 5 Mar 2023 11:47:17 +0100 Subject: [PATCH 05/18] refactor: address review comments --- packages/app/src/Element/BadgeList.css | 1 + packages/app/src/Element/BadgeList.tsx | 2 +- packages/app/src/Feed/BadgesFeed.ts | 19 ++++++++++--------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/app/src/Element/BadgeList.css b/packages/app/src/Element/BadgeList.css index 91fce4f9..79a6fbc2 100644 --- a/packages/app/src/Element/BadgeList.css +++ b/packages/app/src/Element/BadgeList.css @@ -8,6 +8,7 @@ width: 32px; height: 32px; object-fit: contain; + cursor: pointer; } .badge-item:not(:last-child) { diff --git a/packages/app/src/Element/BadgeList.tsx b/packages/app/src/Element/BadgeList.tsx index 7d2b518b..bc24cb95 100644 --- a/packages/app/src/Element/BadgeList.tsx +++ b/packages/app/src/Element/BadgeList.tsx @@ -29,7 +29,7 @@ export default function BadgeList({ badges }: { badges: TaggedRawEvent[] }) { return ( <>
setShowModal(!showModal)}> - {badgeMetadata.slice(0, 7).map(({ id, name, img }) => ( + {badgeMetadata.slice(0, 8).map(({ id, name, img }) => ( ))}
diff --git a/packages/app/src/Feed/BadgesFeed.ts b/packages/app/src/Feed/BadgesFeed.ts index 95b2a894..3036fa1a 100644 --- a/packages/app/src/Feed/BadgesFeed.ts +++ b/packages/app/src/Feed/BadgesFeed.ts @@ -12,13 +12,13 @@ export default function useProfileBadges(pubkey?: HexKey) { const sub = useMemo(() => { if (!pubkey) return null; const s = new Subscriptions(); - s.Id = `profile_badges:${pubkey.slice(0, 12)}`; + s.Id = `badges:${pubkey.slice(0, 12)}`; s.Kinds = new Set([EventKind.ProfileBadges]); s.DTags = new Set([Lists.Badges]); s.Authors = new Set([pubkey]); return s; }, [pubkey]); - const profileBadges = useSubscription(sub, { leaveOpen: true, cache: false }); + const profileBadges = useSubscription(sub, { leaveOpen: false, cache: false }); const profile = useMemo(() => { const sorted = [...profileBadges.store.notes]; @@ -36,16 +36,17 @@ export default function useProfileBadges(pubkey?: HexKey) { }, {}); } return {}; - }, [pubkey, profileBadges.store.notes]); + }, [pubkey, profileBadges.store]); const awardsSub = useMemo(() => { - if (!pubkey) return null; + const ids = Object.keys(profile); + if (!pubkey || ids.length === 0) return null; const s = new Subscriptions(); s.Id = `profile_awards:${pubkey.slice(0, 12)}`; s.Kinds = new Set([EventKind.BadgeAward]); - s.Ids = new Set(Object.keys(profile)); + s.Ids = new Set(ids); return s; - }, [pubkey, profileBadges.store.notes]); + }, [pubkey, profileBadges.store]); const awards = useSubscription(awardsSub); @@ -64,14 +65,14 @@ export default function useProfileBadges(pubkey?: HexKey) { const badgesSub = useMemo(() => { if (!pubkey) return null; const s = new Subscriptions(); - s.Id = `profile_awards:${pubkey.slice(0, 12)}`; + s.Id = `profile_badges:${pubkey.slice(0, 12)}`; s.Kinds = new Set([EventKind.Badge]); s.DTags = new Set(ds); s.Authors = new Set(pubkeys); return s; }, [pubkey, profile]); - const badges = useSubscription(badgesSub, { leaveOpen: true, cache: false }); + const badges = useSubscription(badgesSub, { leaveOpen: false, cache: false }); const result = useMemo(() => { return awards.store.notes @@ -93,7 +94,7 @@ export default function useProfileBadges(pubkey?: HexKey) { badge && award.pubkey === badge.pubkey && award.tags.find(t => t[0] === "p" && t[1] === pubkey) ) .map(({ badge }) => unwrap(badge)); - }, [pubkey, awards.store.notes, badges.store.notes]); + }, [pubkey, awards.store, badges.store]); return result; } -- 2.45.2 From debefa087307cc25605206a23894db277557cb59 Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Sun, 5 Mar 2023 11:54:32 +0100 Subject: [PATCH 06/18] alignment --- packages/app/src/Element/BadgeList.css | 4 +++ packages/app/src/Element/BadgeList.tsx | 2 +- packages/app/src/Feed/BadgesFeed.ts | 34 +++++++++++++------------- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/packages/app/src/Element/BadgeList.css b/packages/app/src/Element/BadgeList.css index 79a6fbc2..79e017e6 100644 --- a/packages/app/src/Element/BadgeList.css +++ b/packages/app/src/Element/BadgeList.css @@ -28,3 +28,7 @@ .badge-info h3 { margin: 0; } + +.badges-item { + align-items: flex-start; +} diff --git a/packages/app/src/Element/BadgeList.tsx b/packages/app/src/Element/BadgeList.tsx index bc24cb95..53ecd4f2 100644 --- a/packages/app/src/Element/BadgeList.tsx +++ b/packages/app/src/Element/BadgeList.tsx @@ -47,7 +47,7 @@ export default function BadgeList({ badges }: { badges: TaggedRawEvent[] }) {
{badgeMetadata.map(({ id, name, pubkey, description, img }) => { return ( -
+

{name}

diff --git a/packages/app/src/Feed/BadgesFeed.ts b/packages/app/src/Feed/BadgesFeed.ts index 3036fa1a..f8babbc4 100644 --- a/packages/app/src/Feed/BadgesFeed.ts +++ b/packages/app/src/Feed/BadgesFeed.ts @@ -38,18 +38,6 @@ export default function useProfileBadges(pubkey?: HexKey) { return {}; }, [pubkey, profileBadges.store]); - const awardsSub = useMemo(() => { - const ids = Object.keys(profile); - if (!pubkey || ids.length === 0) return null; - const s = new Subscriptions(); - s.Id = `profile_awards:${pubkey.slice(0, 12)}`; - s.Kinds = new Set([EventKind.BadgeAward]); - s.Ids = new Set(ids); - return s; - }, [pubkey, profileBadges.store]); - - const awards = useSubscription(awardsSub); - const { ds, pubkeys } = useMemo(() => { return Object.values(profile).reduce( (acc: BadgeAwards, addr) => { @@ -62,8 +50,20 @@ export default function useProfileBadges(pubkey?: HexKey) { ) as BadgeAwards; }, [profile]); + const awardsSub = useMemo(() => { + const ids = Object.keys(profile); + if (!pubkey || ids.length === 0) return null; + const s = new Subscriptions(); + s.Id = `profile_awards:${pubkey.slice(0, 12)}`; + s.Kinds = new Set([EventKind.BadgeAward]); + s.Ids = new Set(ids); + return s; + }, [pubkey, profileBadges.store]); + + const awards = useSubscription(awardsSub).store.notes; + const badgesSub = useMemo(() => { - if (!pubkey) return null; + if (!pubkey || pubkeys.length === 0) return null; const s = new Subscriptions(); s.Id = `profile_badges:${pubkey.slice(0, 12)}`; s.Kinds = new Set([EventKind.Badge]); @@ -72,17 +72,17 @@ export default function useProfileBadges(pubkey?: HexKey) { return s; }, [pubkey, profile]); - const badges = useSubscription(badgesSub, { leaveOpen: false, cache: false }); + const badges = useSubscription(badgesSub, { leaveOpen: false, cache: false }).store.notes; const result = useMemo(() => { - return awards.store.notes + return awards .map((award: TaggedRawEvent) => { const [, pubkey, d] = award.tags .find(t => t[0] === "a") ?.at(1) ?.split(":") ?? []; - const badge = badges.store.notes.find(b => b.pubkey === pubkey && findTag(b, "d") === d); + const badge = badges.find(b => b.pubkey === pubkey && findTag(b, "d") === d); return { award, @@ -94,7 +94,7 @@ export default function useProfileBadges(pubkey?: HexKey) { badge && award.pubkey === badge.pubkey && award.tags.find(t => t[0] === "p" && t[1] === pubkey) ) .map(({ badge }) => unwrap(badge)); - }, [pubkey, awards.store, badges.store]); + }, [pubkey, awards, badges]); return result; } -- 2.45.2 From dde729a1d2a30c1b0d9bdecbe6bdd98e5c79392e Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Sun, 5 Mar 2023 23:27:13 +0100 Subject: [PATCH 07/18] fix: only use thumb if non empty string --- packages/app/src/Element/BadgeList.tsx | 2 +- packages/app/src/Pages/ProfilePage.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/app/src/Element/BadgeList.tsx b/packages/app/src/Element/BadgeList.tsx index 53ecd4f2..58c0b6b0 100644 --- a/packages/app/src/Element/BadgeList.tsx +++ b/packages/app/src/Element/BadgeList.tsx @@ -23,7 +23,7 @@ export default function BadgeList({ badges }: { badges: TaggedRawEvent[] }) { pubkey: b.pubkey, name, description, - img: thumb || image, + img: thumb?.length > 0 ? thumb : image, }; }); return ( diff --git a/packages/app/src/Pages/ProfilePage.tsx b/packages/app/src/Pages/ProfilePage.tsx index 51905a86..d56d4f71 100644 --- a/packages/app/src/Pages/ProfilePage.tsx +++ b/packages/app/src/Pages/ProfilePage.tsx @@ -79,7 +79,6 @@ export default function ProfilePage() { const website_url = user?.website && !user.website.startsWith("http") ? "https://" + user.website : user?.website || ""; // feeds - const badges = useProfileBadges(id); const { blocked } = useModeration(); const { notes: pinned, related: pinRelated } = usePinnedFeed(id); const { notes: bookmarks, related: bookmarkRelated } = useBookmarkFeed(id); @@ -89,6 +88,7 @@ export default function ProfilePage() { const followers = useFollowersFeed(id); const follows = useFollowsFeed(id); const muted = useMutedFeed(id); + const badges = useProfileBadges(id); // tabs const ProfileTab = { Notes: { text: formatMessage(messages.Notes), value: NOTES }, -- 2.45.2 From 4c05da34ab1a785454eb8de9a82a07ffae198cdf Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Mon, 6 Mar 2023 00:15:46 +0100 Subject: [PATCH 08/18] fix warning --- packages/app/src/Element/BadgeList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/app/src/Element/BadgeList.tsx b/packages/app/src/Element/BadgeList.tsx index 58c0b6b0..26dc9bb5 100644 --- a/packages/app/src/Element/BadgeList.tsx +++ b/packages/app/src/Element/BadgeList.tsx @@ -23,7 +23,7 @@ export default function BadgeList({ badges }: { badges: TaggedRawEvent[] }) { pubkey: b.pubkey, name, description, - img: thumb?.length > 0 ? thumb : image, + img: thumb?.length ?? 0 > 0 ? thumb : image, }; }); return ( -- 2.45.2 From 98b8ba36bc576bf1fbdd415b3764d3d84b72b159 Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Mon, 6 Mar 2023 18:14:45 +0100 Subject: [PATCH 09/18] filter empty d --- packages/app/src/Feed/BadgesFeed.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/app/src/Feed/BadgesFeed.ts b/packages/app/src/Feed/BadgesFeed.ts index f8babbc4..a2c7fec0 100644 --- a/packages/app/src/Feed/BadgesFeed.ts +++ b/packages/app/src/Feed/BadgesFeed.ts @@ -43,7 +43,9 @@ export default function useProfileBadges(pubkey?: HexKey) { (acc: BadgeAwards, addr) => { const [, pubkey, d] = (addr as string).split(":"); acc.pubkeys.push(pubkey); - acc.ds.push(d); + if (d?.length > 0) { + acc.ds.push(d); + } return acc; }, { pubkeys: [], ds: [] } as BadgeAwards -- 2.45.2 From 32df23be2f4b2dd9fd8cce2dd64f185a5cc1e6a7 Mon Sep 17 00:00:00 2001 From: Kieran Date: Tue, 7 Mar 2023 12:16:26 +0000 Subject: [PATCH 10/18] New Crowdin updates (#391) * New translations en.json (Arabic) * New translations en.json (French) * New translations en.json (Hungarian) * New translations en.json (Hungarian) --- packages/app/src/translations/ar.json | 46 ++++++++++---------- packages/app/src/translations/fr.json | 60 +++++++++++++-------------- packages/app/src/translations/hu.json | 44 ++++++++++---------- 3 files changed, 75 insertions(+), 75 deletions(-) diff --git a/packages/app/src/translations/ar.json b/packages/app/src/translations/ar.json index 3a827d2e..5bdf54e7 100644 --- a/packages/app/src/translations/ar.json +++ b/packages/app/src/translations/ar.json @@ -2,7 +2,7 @@ "+D82kt": "هل أنت متأكد من إعادة النشر: {id}", "+aZY2h": "تخصيص الومضة", "+vIQlC": "يرجى التأكد من حفظ كلمة المرور لتتمكن من إدارة المعرّف الخاص بك في المستقبل", - "+vVZ/G": "Connect", + "+vVZ/G": "اتصال", "/4tOwT": "تخطي", "/JE/X+": "دعم الحساب", "/PCavi": "علنية", @@ -15,13 +15,13 @@ "0yO7wF": "{n} ثانية", "1A7TZk": "ما هو سنورت وكيف يعمل؟", "1Mo59U": "هل أنت متأكد من حذف هذا المنشور من المنشورات المرجعية؟", - "1c4YST": "Connected to: {node} 🎉", + "1c4YST": "متصل بـ: {node}🎉", "1nYUGC": "المتابَعون {n}", "1udzha": "المحادثات", "2/2yg+": "اضافة", "25V4l1": "الخلفية", "2IFGap": "تبرع", - "2LbrkB": "Enter password", + "2LbrkB": "أدخل كلمة المرور", "2a2YiP": "المنشورات المرجعية {n}", "2k0Cv+": "الاستهجان ({n})", "3cc4Ct": "فاتح", @@ -29,7 +29,7 @@ "3t3kok": "{n,plural,=1{{n} منشور جديد}other{{n} منشورات جديدة}}", "3tVy+Z": "المتابِعون {n}", "3xCwbZ": "أو", - "3yk8fB": "Wallet", + "3yk8fB": "المحفظة", "450Fty": "لا أحد", "47FYwb": "الغاء", "4IPzdn": "المطورون الأساسيون", @@ -49,7 +49,7 @@ "8E9muH": "استيراد متابعات تويتر (اختياري)", "8QDesP": "أومض {n} ساتوشي", "8g2vyB": "الاسم طويل جدا", - "8v1NN+": "Pairing phrase", + "8v1NN+": "عبارة الاقتران", "9+Ddtu": "التالي", "9HU8vw": "رد", "9SvQep": "يتابع {n}", @@ -88,7 +88,7 @@ "FfYsOb": "حدث خطأ!", "FmXUJg": "متابع لك", "G/yZLu": "حذف", - "G1BGCg": "Select Wallet", + "G1BGCg": "اختر محفظة", "GFOoEE": "ملح", "GL8aXW": "المنشورات المرجعية ({n})", "Gcn9NQ": "Magnet Link", @@ -103,13 +103,13 @@ "IEwZvs": "هل أنت متأكد من ازالة تثبيت هذا المنشور؟", "INSqIz": "اسم مستخدم تويتر...", "IUZC+0": "هذا يعني أنه لا يمكن لأي شخص تعديل المنشورات التي قمت بإنشائها ويمكن للجميع بسهولة التحقق من أن المنشورات التي يقرؤونها تم انشاؤها من حسابك.", - "Iwm6o2": "NIP-05 Shop", + "Iwm6o2": "سوق NIP-05", "JCIgkj": "اسم المستخدم", "JHEHCk": "وميض ({n})", "JkLHGw": "موقع إلكتروني", "K3r6DQ": "مسح", "K7AkdL": "عرض", - "KAhAcM": "Enter LNDHub config", + "KAhAcM": "أدخل معلومات التهيئة لـ LNDHub", "KQvWvD": "تم الحذف", "KWuDfz": "لقد حفظت مفاتيحي ، استمرار", "KahimY": "نوع الحدث غير معروف: {kind}", @@ -119,7 +119,7 @@ "M3Oirc": "قوائم التصحيح", "MBAYRO": "عرض خيار \"نسخ المعرف\" و \"النسخ بصيغة JSON\" في قائمة الخيارات المنسدلة لكل منشور", "MI2jkA": "غير متاح:", - "MP54GY": "Wallet password", + "MP54GY": "كلمة مرور المحفظة", "MRp6Ly": "اسم مستخدم تويتر", "MWTx65": "العرض الافتراضي", "MzRYWH": "شراء {item}", @@ -139,7 +139,7 @@ "QTdJfH": "إنشاء حساب", "QawghE": "بإمكانك تغيير اسم المستخدم في أي وقت.", "QxCuTo": "الفن بواسطة {name}", - "R2OqnW": "Delete Account", + "R2OqnW": "حذف الحساب", "RDZVQL": "فحص", "RahCRH": "منتهي الصلاحية", "RhDAoS": "هل أنت متأكد أنك تريد حذف {id}", @@ -149,7 +149,7 @@ "TpgeGw": "Hex Salt..", "UQ3pOC": "على نوستر ، كثير من الحسابات يحملون نفس اسم المستخدم. أسم المستخدم يختلف عن عن معرف الحساب. يمكنك الحصول على معرّف فريد في الخطوة التالية.", "Up5U7K": "حظر", - "VN0+Fz": "Balance: {amount} sats", + "VN0+Fz": "الرصيد: {amount} ساتوشي", "VOjC1i": "اختر خدمة التحميل التي تريد رفع المرفقات إليها", "VlJkSk": "تم كتم {n}", "VnXp8Z": "صورة الحساب ", @@ -163,7 +163,7 @@ "Y31HTH": "ساعد في تمويل تطوير سنورت", "YDURw6": "رابط الخدمة", "YXA3AH": "تمكين التفاعل", - "Z4BMCZ": "Enter pairing phrase", + "Z4BMCZ": "أدخل عبارة الاقتران", "ZKORll": "نشط الآن", "ZLmyG9": "المساهمون", "ZUZedV": "تبرع البرق:", @@ -175,10 +175,10 @@ "cPIKU2": "المتابَعون", "cQfLWb": "URL ..", "cWx9t8": "كتم الكل", - "cg1VJ2": "Connect Wallet", + "cg1VJ2": "ربط المحفظة", "cuV2gK": "الاسم مسجل", "cyR7Kh": "الخلف", - "d6CyG5": "History", + "d6CyG5": "التاريخ", "d7d0/x": "عنوان البرق", "dOQCL8": "اسم العرض", "e7qqly": "تمت قراءة الكل", @@ -214,14 +214,14 @@ "jzgQ2z": "التفاعل {n}", "k2veDA": "يكتب", "k7sKNy": "تساعد خدمة التوثيق NIP-05 الخاصة بنا في دعم تطوير هذا الموقع والحصول على شارة خاصة لامعة على موقعنا!", - "kaaf1E": "now", + "kaaf1E": "الآن", "lCILNz": "اشتر الآن", "lD3+8a": "دفع", - "lTbT3s": "Wallet password", + "lTbT3s": "كلمة مرور المحفظة", "lgg1KN": "صفحة الحساب", "ll3xBp": "خدمة وكيل الصور", "lnaT9F": "المتابَعون {n}", - "lsNFM1": "Click to load content from {link}", + "lsNFM1": "انقر لتحميل المحتوى من {link}", "lvlPhZ": "دفع البرقية", "mH91FY": "سيحصل كل مساهم على نسبة مئوية من جميع التبرعات وأوامر NIP-05 ، يمكنك رؤية المبالغ المقسمة أدناه", "mKAr6h": "تابع الكل", @@ -241,14 +241,14 @@ "oxCa4R": "يساعد الحصول على معرّف في تأكيد هويتك للأشخاص الذين يعرفونك. يمكن أن يكون لدى العديد من الأشخاص اسم مستخدمjack ، ولكن لا يوجد سوى jack@cash.app.", "puLNUJ": "تثبيت", "pzTOmv": "المتابِعون", - "qDwvZ4": "Unknown error", + "qDwvZ4": "خطأ غير معروف", "qMx1sA": "قيمة الومضة الافتراضية", "qUJTsT": "محظور", "qdGuQo": "مفتاحك الخاص هو (لا تشارك هذا مع أي شخص)", "qkvYUb": "أضف إلى الملف الشخصي", "qmJ8kD": "فشلت الترجمة", "r3C4x/": "برنامج", - "r5srDR": "Enter wallet password", + "r5srDR": "أدخل كلمة مرور المحفظة", "rT14Ow": "إضافة موصّلات", "reJ6SM": "يوصى باستخدام أحد ملحقات المستعرض التالية إذا كنت تستخدم جهاز كمبيوتر لتأمين مفتاحك:", "rfuMjE": "(افتراضي)", @@ -265,22 +265,22 @@ "usAvMr": "تعديل الملف الشخصي", "ut+2Cd": "احصل على معرف الشريك", "vOKedj": "{n,plural,=1{و{n} آخر}other{و{n} آخرون}}", - "vU71Ez": "Paying with {wallet}", + "vU71Ez": "الدفع باستخدام {wallet}", "vZ4quW": "NIP-05 هو أحد طرق التحقق المستندة إلى DNS والتي تساعد في التحقق من هويتك كمستخدم حقيقي.", - "vrTOHJ": "{amount} sats", + "vrTOHJ": "{amount} ساتوشي", "wEQDC6": "تحرير", "wLtRCF": "مفتاحك", "wWLwvh": "هوية مخفية", "wih7iJ": "الاسم محظور", "wqyN/i": "اكتشف المزيد من المعلومات حول {service} على {link}", "wtLjP6": "نسخ المعرف", - "wvFw6Y": "Hey, it looks like you dont have a NIP-05 handle yet, you should get one! Check out {link}", + "wvFw6Y": "مرحبا، يبدو أنك لا تملك معرف NIP-05 حتى الآن، يمكنك الحصول على معرف فريد! استعرض {link}", "x82IOl": "كتم", "xIoGG9": "اذهب إلى", "xJ9n2N": "مفتاحك العام", "xKdNPm": "ارسال", "xKflGN": "يتابع {username} على نوستر", - "xQtL3v": "Unlock", + "xQtL3v": "فتح القفل", "xbVgIm": "تحميل الوسائط تلقائيًا", "xmcVZ0": "البحث", "y1Z3or": "اللغة", diff --git a/packages/app/src/translations/fr.json b/packages/app/src/translations/fr.json index 6d28efc7..0637b7de 100644 --- a/packages/app/src/translations/fr.json +++ b/packages/app/src/translations/fr.json @@ -1,27 +1,27 @@ { "+D82kt": "Êtes-vous sûr que vous voulez republier: {id}", - "+aZY2h": "Zap Type", + "+aZY2h": "Type de Zap", "+vIQlC": "Assurez-vous d'enregistrer le mot de passe suivant afin de gérer votre identifiant à l'avenir", - "+vVZ/G": "Connect", - "/4tOwT": "Sauter", + "+vVZ/G": "Connexion", + "/4tOwT": "Passer", "/JE/X+": "Prise en charge du compte", - "/PCavi": "Public", + "/PCavi": "Publique", "/RD0e2": "Nostr utilise la technologie de signature numérique pour fournir des notes inviolables qui peuvent être répliquées en toute sécurité sur de nombreux relais pour fournir un stockage redondant de votre contenu.", "/d6vEc": "Rendez votre profil plus facile à trouver et à partager", "/n5KSF": "{n} ms", "0BUTMv": "Chercher...", - "0jOEtS": "Invalid LNURL", + "0jOEtS": "LNURL invalide", "0mch2Y": "le nom contient des caractères non autorisés", "0yO7wF": "{n} secondes", "1A7TZk": "Qu'est-ce que Snort et comment ça marche ?", "1Mo59U": "Êtes-vous sûr de vouloir supprimer cette note de vos favoris ?", - "1c4YST": "Connected to: {node} 🎉", + "1c4YST": "Connecté à : {node} 🎉", "1nYUGC": "{n} Abonnements", "1udzha": "Conversations", "2/2yg+": "Ajouter", "25V4l1": "Bannière", "2IFGap": "Faire un don", - "2LbrkB": "Enter password", + "2LbrkB": "Saisissez le mot de passe", "2a2YiP": "{n} Favoris", "2k0Cv+": "N'aime pas ({n})", "3cc4Ct": "Clair", @@ -29,7 +29,7 @@ "3t3kok": "{n,plural,=1{{n} nouvelle note} other{{n} nouvelles notes}}", "3tVy+Z": "{n} Abonnés", "3xCwbZ": "OU", - "3yk8fB": "Wallet", + "3yk8fB": "Portefeuille", "450Fty": "Aucun", "47FYwb": "Annuler", "4IPzdn": "Développeurs principaux", @@ -49,7 +49,7 @@ "8E9muH": "Importer les suivis Twitter (facultatif)", "8QDesP": "Zapper {n} sats", "8g2vyB": "le nom est trop long", - "8v1NN+": "Pairing phrase", + "8v1NN+": "Phrase d'appairage", "9+Ddtu": "Suivant", "9HU8vw": "Répondre", "9SvQep": "Suit {n}", @@ -88,10 +88,10 @@ "FfYsOb": "Une erreur est survenue!", "FmXUJg": "vous suit", "G/yZLu": "Retirer", - "G1BGCg": "Select Wallet", + "G1BGCg": "Sélectionnez un portefeuille", "GFOoEE": "Sel", "GL8aXW": "Favoris ({n})", - "Gcn9NQ": "Magnet Link", + "Gcn9NQ": "Lien Magnet", "GspYR7": "{n} N'aime pas", "H+vHiz": "Clé hexagonale..", "H0JBH6": "Se Déconnecter", @@ -109,19 +109,19 @@ "JkLHGw": "Site Internet", "K3r6DQ": "Supprimer", "K7AkdL": "Montrer", - "KAhAcM": "Enter LNDHub config", + "KAhAcM": "Entrez la configuration LNDHub", "KQvWvD": "Supprimé", "KWuDfz": "J'ai enregistré mes clés, continuer", "KahimY": "Type d'événement inconnu : {kind}", - "LXxsbk": "Anonymous", + "LXxsbk": "Anonyme", "LgbKvU": "Commenter", "LxY9tW": "Générer la clé", "M3Oirc": "Menus de débogage", "MBAYRO": "Affiche \"Copy ID\" et \"Copy Event JSON\" dans le menu contextuel de chaque message", "MI2jkA": "Pas disponible:", - "MP54GY": "Wallet password", + "MP54GY": "Mot de passe du portefeuille", "MRp6Ly": "Nom d'utilisateur Twitter", - "MWTx65": "Default Page", + "MWTx65": "Page par défaut", "MzRYWH": "Acheter {item}", "N2IrpM": "Confirmer", "NdOYJJ": "Hmm rien ici .. Essayez {newUsersPage} pour suivre quelques recommandations de naustriches!", @@ -139,7 +139,7 @@ "QTdJfH": "Créer un compte", "QawghE": "Vous pouvez modifier votre nom d'utilisateur à tout moment.", "QxCuTo": "Illustration par {name}", - "R2OqnW": "Delete Account", + "R2OqnW": "Supprimer le compte", "RDZVQL": "Vérifier", "RahCRH": "Expiré", "RhDAoS": "Êtes-vous sûr que vous voulez supprimer {id}", @@ -149,7 +149,7 @@ "TpgeGw": "Sel Hex..", "UQ3pOC": "Sur Nostr, de nombreuses personnes ont le même nom d'utilisateur. Les noms d'utilisateur et l'identité sont des choses distinctes. Vous pouvez obtenir un identifiant unique à l'étape suivante.", "Up5U7K": "Bloquer", - "VN0+Fz": "Balance: {amount} sats", + "VN0+Fz": "Solde : {amount} sats", "VOjC1i": "Choisissez le service d'hébergement vers lequel vous souhaitez héberger les pièces jointes", "VlJkSk": "{n} mis en sourdine", "VnXp8Z": "Avatar", @@ -163,7 +163,7 @@ "Y31HTH": "Aidez à financer le développement de Snort", "YDURw6": "URL de service", "YXA3AH": "Activer les réactions", - "Z4BMCZ": "Enter pairing phrase", + "Z4BMCZ": "Entrez la phrase d'appairage", "ZKORll": "Activer Maintenant", "ZLmyG9": "Contributeurs", "ZUZedV": "Don éclair :", @@ -175,10 +175,10 @@ "cPIKU2": "Abonnements", "cQfLWb": "URL..", "cWx9t8": "Tout mettre en sourdine", - "cg1VJ2": "Connect Wallet", + "cg1VJ2": "Connecter un portefeuille", "cuV2gK": "le nom est enregistré", "cyR7Kh": "Retourner", - "d6CyG5": "History", + "d6CyG5": "Historique", "d7d0/x": "Adresse LN", "dOQCL8": "Nom à afficher", "e7qqly": "Marquer tout comme lu", @@ -214,14 +214,14 @@ "jzgQ2z": "{n} Réactions", "k2veDA": "Écrire", "k7sKNy": "Notre propre service de vérification NIP-05, aidez à soutenir le développement de ce site et obtenez un badge spécial brillant sur notre site !", - "kaaf1E": "now", + "kaaf1E": "maintenant", "lCILNz": "Acheter Maintenant", "lD3+8a": "Payer", - "lTbT3s": "Wallet password", + "lTbT3s": "Mot de passe du portefeuille", "lgg1KN": "compte", "ll3xBp": "Service proxy d'images", "lnaT9F": "Abonnements {n}", - "lsNFM1": "Click to load content from {link}", + "lsNFM1": "Cliquez pour afficher le contenu de {link}", "lvlPhZ": "Payer Facture", "mH91FY": "Chaque contributeur recevra un pourcentage de tous les dons et commandes NIP-05, vous pouvez voir les montants répartis ci-dessous", "mKAr6h": "Suivre tout", @@ -241,14 +241,14 @@ "oxCa4R": "L'obtention d'un identifiant permet de confirmer votre identité réelle aux personnes qui vous connaissent. De nombreuses personnes peuvent avoir un nom d'utilisateur @jack, mais il n'y a qu'un seul jack@cash.app.", "puLNUJ": "Épingler", "pzTOmv": "Abonnés", - "qDwvZ4": "Unknown error", - "qMx1sA": "Default Zap amount", + "qDwvZ4": "Une erreur inconnue s'est produite", + "qMx1sA": "Montant des Zaps par défaut", "qUJTsT": "Bloqué", "qdGuQo": "Votre Clé Privée Est (ne la partagez avec personne)", "qkvYUb": "Ajouter au Profil", "qmJ8kD": "La traduction a échoué", "r3C4x/": "Logiciel", - "r5srDR": "Enter wallet password", + "r5srDR": "Entrez le mot de passe du portefeuille", "rT14Ow": "Ajouter Relais", "reJ6SM": "Il est recommandé d'utiliser l'une des extensions de navigateur suivantes si vous êtes sur un ordinateur de bureau pour sécuriser votre clé :", "rfuMjE": "(Défaut)", @@ -265,7 +265,7 @@ "usAvMr": "Modifier le Profil", "ut+2Cd": "Obtenir un identifiant partenaire", "vOKedj": "{n,plural,=1{& {n} autre} other{& {n} autres}}", - "vU71Ez": "Paying with {wallet}", + "vU71Ez": "Payer avec {wallet}", "vZ4quW": "NIP-05 est une spécification de vérification basée sur DNS qui permet de vous valider en tant qu'utilisateur réel.", "vrTOHJ": "{amount} sats", "wEQDC6": "Modifier", @@ -274,16 +274,16 @@ "wih7iJ": "le nom est bloqué", "wqyN/i": "En savoir plus sur {service} sur {link}", "wtLjP6": "Copier Identifiant", - "wvFw6Y": "Hey, it looks like you dont have a NIP-05 handle yet, you should get one! Check out {link}", + "wvFw6Y": "Hey, il semble que vous n'avez pas de NIP-05, vous pourriez en obtenir un, jetez un œil à {link}", "x82IOl": "Mode Sourdine", "xIoGG9": "Aller à", "xJ9n2N": "Votre clé publique", "xKdNPm": "Envoyer", "xKflGN": "{username}'' suit sur Nostr", - "xQtL3v": "Unlock", + "xQtL3v": "Déverrouiller", "xbVgIm": "Charger automatiquement le média", "xmcVZ0": "Chercher", - "y1Z3or": "Language", + "y1Z3or": "Langue", "yCmnnm": "Lire le flux global depuis", "zFegDD": "Contacted", "zINlao": "Propriétaire", diff --git a/packages/app/src/translations/hu.json b/packages/app/src/translations/hu.json index 71cd0f49..601e05b3 100644 --- a/packages/app/src/translations/hu.json +++ b/packages/app/src/translations/hu.json @@ -2,7 +2,7 @@ "+D82kt": "Biztos hogy ezt meg akarod osztani: {id}", "+aZY2h": "Zap típusa", "+vIQlC": "Ahhoz hogy a jövőben is hozzáférj a fiókodhoz, kérlek mindenképp győződj meg róla hogy a következő jelszót elmentetted", - "+vVZ/G": "Connect", + "+vVZ/G": "Kapcsolódás", "/4tOwT": "Kihagyás", "/JE/X+": "Segítség", "/PCavi": "Nyilvános", @@ -15,13 +15,13 @@ "0yO7wF": "{n} másodperc", "1A7TZk": "Mi a Snort és hogyan működik?", "1Mo59U": "Biztos hogy a kedvencekből ezt a bejegyzést el akarod távolítani?", - "1c4YST": "Connected to: {node} 🎉", + "1c4YST": "Kapcsolódás a: {node} 🎉", "1nYUGC": "{n} Követek", "1udzha": "Beszélgetések", "2/2yg+": "Hozzáad", "25V4l1": "Banner", "2IFGap": "Adományoz", - "2LbrkB": "Enter password", + "2LbrkB": "Add meg jelszavad", "2a2YiP": "{n} könyvjelző", "2k0Cv+": "Nemtetszések ({n})", "3cc4Ct": "Világos", @@ -29,7 +29,7 @@ "3t3kok": "{n,plural,one {}=1{{n} új bejegyzés} other{{n} új bejegyzések}}", "3tVy+Z": "{n} Követő", "3xCwbZ": "VAGY", - "3yk8fB": "Wallet", + "3yk8fB": "Pénztárca", "450Fty": "Nincs", "47FYwb": "Törlés", "4IPzdn": "Elsődleges Fejlesztők", @@ -49,7 +49,7 @@ "8E9muH": "Twitter követők importálása (opcionális)", "8QDesP": "Zap {n} sats", "8g2vyB": "név túl hosszú", - "8v1NN+": "Pairing phrase", + "8v1NN+": "Párosító kifejezés", "9+Ddtu": "Következő", "9HU8vw": "Válasz", "9SvQep": "{n} követek", @@ -88,10 +88,10 @@ "FfYsOb": "Hiba történt!", "FmXUJg": "követ téged", "G/yZLu": "Eltávolítás", - "G1BGCg": "Select Wallet", + "G1BGCg": "Tárca kiválasztása", "GFOoEE": "Salt", "GL8aXW": "Könyvjelzők ({n})", - "Gcn9NQ": "Magnet Link", + "Gcn9NQ": "Mágnes Link", "GspYR7": "{n} Nem tetszik", "H+vHiz": "Hex kulcs..", "H0JBH6": "Kijelentkezés", @@ -103,13 +103,13 @@ "IEwZvs": "Biztos hogy a bejegyzés kiemelését visszavonod?", "INSqIz": "Twitter felhasználónév...", "IUZC+0": "Ez azt jelenti, hogy a te általad létrehozott bejegyzéseket senki sem tudja módosítani és bárki ellenőrizheti hogy tényleg te írtad.", - "Iwm6o2": "NIP-05 Shop", + "Iwm6o2": "NIP-05 Bolt", "JCIgkj": "Felhasználónév", "JHEHCk": "Zap-ek ({n})", "JkLHGw": "Weboldal", "K3r6DQ": "Törlés", "K7AkdL": "Mutat", - "KAhAcM": "Enter LNDHub config", + "KAhAcM": "Az LNDHub konfiguráció megadása", "KQvWvD": "Törölve", "KWuDfz": "Lementettem a kulcsaimat, folytatás", "KahimY": "Ismeretlen esemény: {kind}", @@ -119,7 +119,7 @@ "M3Oirc": "Hibaelhárító menü", "MBAYRO": "Mutasd az \"Egyedi azonosítót\" és a \"JSON esetet\" minden üzenet szövegmezőjében", "MI2jkA": "Nem elérhető:", - "MP54GY": "Wallet password", + "MP54GY": "Pénztárca jelszava", "MRp6Ly": "Twitter felhasználónév", "MWTx65": "Alapértelmezett oldal", "MzRYWH": "{item} megveszem", @@ -139,7 +139,7 @@ "QTdJfH": "Hozzon létre egy fiókot", "QawghE": "A felhasználónevedet bármikor megváltoztathatod.", "QxCuTo": "Művészet: {name}", - "R2OqnW": "Delete Account", + "R2OqnW": "Fiók törlése", "RDZVQL": "Ellenőrzés", "RahCRH": "Lejárt", "RhDAoS": "Biztos hogy törölni akarod a {id}", @@ -149,7 +149,7 @@ "TpgeGw": "Hex Salt..", "UQ3pOC": "A Nostr-án sok embernek ugyanaz a felhasználóneve. A felhasználónév és a személyazonosság két különböző dolog. A következő lépésben tudsz magadnak egyedi azonosítót szerezni.", "Up5U7K": "Tiltás", - "VN0+Fz": "Balance: {amount} sats", + "VN0+Fz": "Egyenleg: {amount} sats", "VOjC1i": "Válaszd ki mely szolgáltatóhoz legyenek a fájlok feltöltve", "VlJkSk": "{n} némított", "VnXp8Z": "Avatar", @@ -163,7 +163,7 @@ "Y31HTH": "Segítsen finanszírozni a Snort fejlesztését", "YDURw6": "Szervíz cím", "YXA3AH": "Reakciók engedélyezése", - "Z4BMCZ": "Enter pairing phrase", + "Z4BMCZ": "Párosító kifejezés megadása", "ZKORll": "Aktiválás", "ZLmyG9": "Közreműködők", "ZUZedV": "Lightning adomány:", @@ -175,10 +175,10 @@ "cPIKU2": "Követek", "cQfLWb": "Cím..", "cWx9t8": "Mind némítása", - "cg1VJ2": "Connect Wallet", + "cg1VJ2": "Pénztárca csatlakoztatása", "cuV2gK": "név már foglalt", "cyR7Kh": "Vissza", - "d6CyG5": "History", + "d6CyG5": "Előzmények", "d7d0/x": "LN cím", "dOQCL8": "Megjelenítendő név", "e7qqly": "Mind olvasottnak jelölni", @@ -214,10 +214,10 @@ "jzgQ2z": "{n} Reakció", "k2veDA": "Írás", "k7sKNy": "A mi saját NIP-05 azonosítási szolgáltatásunk, amelynek a használatával ennek az oldalnak a fejlesztését segítheted és ezzel egy speciális kitüntetést is szerezhetsz!", - "kaaf1E": "now", + "kaaf1E": "most", "lCILNz": "Vásárlás", "lD3+8a": "Fizetem", - "lTbT3s": "Wallet password", + "lTbT3s": "Pénztárca jelszava", "lgg1KN": "Felhasználói felület", "ll3xBp": "Képmegosztó szolgáltató", "lnaT9F": "Követek {n}", @@ -241,14 +241,14 @@ "oxCa4R": "Egy azonosító megszerzésével segítesz másoknak a te valós fiókod könnyebb megtalálásában. Sokaknak lehet @jack felhasználóneve, de csak egy jack@cash.app létezik.", "puLNUJ": "Kiemel", "pzTOmv": "Követők", - "qDwvZ4": "Unknown error", + "qDwvZ4": "Ismeretlen hiba", "qMx1sA": "Alapértelmezett Zap összeg", "qUJTsT": "Tiltva", "qdGuQo": "A te privát kulcsod (senkivel se oszd meg)", "qkvYUb": "Hozzáadás a profilhoz", "qmJ8kD": "Fordítás nem sikerült", "r3C4x/": "Szoftver", - "r5srDR": "Enter wallet password", + "r5srDR": "Add meg a pénztárcád jelszavát", "rT14Ow": "Csomópont hozzáadása", "reJ6SM": "Ahhoz hogy a privát kulcsod biztonságban legyen, javasolt a következő böngésző kiegészítők valamelyikét használni:", "rfuMjE": "(Alapértelmezett)", @@ -265,7 +265,7 @@ "usAvMr": "Profil módosítása", "ut+2Cd": "Szerezz egy partner azonosítót", "vOKedj": "{n,plural,=1{& {n} egyéb} other{& {n} egyebek}}", - "vU71Ez": "Paying with {wallet}", + "vU71Ez": "Fizetés {wallet}", "vZ4quW": "A NIP-05 egy DNS alapú azonosítási specifikáció, ami segít a valós személyed bizonyításában.", "vrTOHJ": "{amount} sats", "wEQDC6": "Módosítás", @@ -274,13 +274,13 @@ "wih7iJ": "név tiltva", "wqyN/i": "Több információ a {service} itt {link}", "wtLjP6": "Egyedi azonosító", - "wvFw6Y": "Hey, it looks like you dont have a NIP-05 handle yet, you should get one! Check out {link}", + "wvFw6Y": "Úgy néz ki nem rendelkezel még NIP-05 azonosítóval, érdemes lenne szerezned egyett! Ezt nézd {link}", "x82IOl": "Némítás", "xIoGG9": "Menj ide", "xJ9n2N": "A te publikus kulcsod", "xKdNPm": "Küldés", "xKflGN": "{username} a Nostr-án követ", - "xQtL3v": "Unlock", + "xQtL3v": "Feloldás", "xbVgIm": "Média automatikus betöltése", "xmcVZ0": "Keresés", "y1Z3or": "Nyelv", -- 2.45.2 From a8df079e714c3dbfaae8d73f123c10a94939a0e0 Mon Sep 17 00:00:00 2001 From: Lukas Jakob Date: Sat, 4 Mar 2023 12:18:21 -0600 Subject: [PATCH 11/18] fix(BackButton): vertical align styles --- packages/app/src/Element/BackButton.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/app/src/Element/BackButton.css b/packages/app/src/Element/BackButton.css index e94ae1ba..99b93224 100644 --- a/packages/app/src/Element/BackButton.css +++ b/packages/app/src/Element/BackButton.css @@ -4,6 +4,8 @@ color: var(--highlight); font-weight: 400; font-size: var(--font-size); + display: flex; + align-items: center; } .back-button svg { -- 2.45.2 From cb91b16dc8f751efcb7879e697d83535747f0805 Mon Sep 17 00:00:00 2001 From: Lukas Jakob Date: Sat, 4 Mar 2023 12:09:11 -0600 Subject: [PATCH 12/18] feat(note): open note in new tab on cmd press --- packages/app/src/Element/Note.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/app/src/Element/Note.tsx b/packages/app/src/Element/Note.tsx index e8d1aa79..cc204e3f 100644 --- a/packages/app/src/Element/Note.tsx +++ b/packages/app/src/Element/Note.tsx @@ -175,7 +175,12 @@ export default function Note(props: NoteProps) { function goToEvent(e: React.MouseEvent, id: u256) { e.stopPropagation(); - navigate(eventLink(id)); + // detect cmd key and open in new tab + if (e.metaKey) { + window.open(eventLink(id), "_blank"); + } else { + navigate(eventLink(id)); + } } function replyTag() { -- 2.45.2 From 7bb534c68f5b0d257d9d9a570d22c309a0391c0b Mon Sep 17 00:00:00 2001 From: Lukas Jakob Date: Sat, 4 Mar 2023 11:33:57 -0600 Subject: [PATCH 13/18] fix(skeleton): dark theme styles --- packages/app/src/Element/Skeleton.css | 30 +++++++++++++++------------ 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/packages/app/src/Element/Skeleton.css b/packages/app/src/Element/Skeleton.css index 09213ac4..a05f8955 100644 --- a/packages/app/src/Element/Skeleton.css +++ b/packages/app/src/Element/Skeleton.css @@ -3,10 +3,14 @@ height: 1em; position: relative; overflow: hidden; - background-color: #dddbdd; + background-color: var(--note-bg); border-radius: 16px; } +html.light .skeleton { + background-color: var(--gray-secondary); +} + .skeleton::after { position: absolute; top: 0; @@ -17,26 +21,26 @@ background-image: linear-gradient( 90deg, rgba(255, 255, 255, 0) 0, - rgba(255, 255, 255, 0.2) 20%, - rgba(255, 255, 255, 0.5) 60%, + rgba(255, 255, 255, 0.02) 20%, + rgba(255, 255, 255, 0.05) 60%, rgba(255, 255, 255, 0) ); animation: shimmer 2s infinite; content: ""; } +html.light .skeleton::after { + background-image: linear-gradient( + 90deg, + rgba(255, 255, 255, 0) 0, + rgba(255, 255, 255, 0.2) 20%, + rgba(255, 255, 255, 0.5) 60%, + rgba(255, 255, 255, 0) + ); +} + @keyframes shimmer { 100% { transform: translateX(100%); } } - -@media screen and (prefers-color-scheme: dark) { - .skeleton { - background-color: #50535a; - } - - .skeleton::after { - background-image: linear-gradient(90deg, #50535a 0%, #656871 20%, #50535a 40%, #50535a 100%); - } -} -- 2.45.2 From 683d9a0c401bddb9bb7e213ea4604d37f9894577 Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Tue, 7 Mar 2023 22:35:40 +0900 Subject: [PATCH 14/18] fix HyperText matching --- packages/app/src/Element/Text.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/app/src/Element/Text.tsx b/packages/app/src/Element/Text.tsx index 05c99978..eba63cc2 100644 --- a/packages/app/src/Element/Text.tsx +++ b/packages/app/src/Element/Text.tsx @@ -35,7 +35,7 @@ export default function Text({ content, tags, creator }: TextProps) { .map(f => { if (typeof f === "string") { return splitByUrl(f).map(a => { - if (a.startsWith("http")) { + if (a.match(/^https?:\/\//)) { return ; } return a; -- 2.45.2 From 80607b91d9873946ebacd8431d61c8ea1389b37e Mon Sep 17 00:00:00 2001 From: d-r-w Date: Mon, 27 Feb 2023 19:16:43 -0600 Subject: [PATCH 15/18] Makes entire note clickable --- packages/app/src/Element/Note.css | 7 +++++-- packages/app/src/Element/Note.tsx | 9 +++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/app/src/Element/Note.css b/packages/app/src/Element/Note.css index 828caccf..cc2845bf 100644 --- a/packages/app/src/Element/Note.css +++ b/packages/app/src/Element/Note.css @@ -2,6 +2,10 @@ min-height: 110px; } +.note:hover { + cursor: pointer; +} + .note > .header .reply { font-size: 13px; color: var(--font-secondary-color); @@ -134,8 +138,7 @@ } .note > .header img:hover, -.note > .header .name > .reply:hover, -.note .body:hover { +.note > .header .name > .reply:hover { cursor: pointer; } diff --git a/packages/app/src/Element/Note.tsx b/packages/app/src/Element/Note.tsx index cc204e3f..29f75954 100644 --- a/packages/app/src/Element/Note.tsx +++ b/packages/app/src/Element/Note.tsx @@ -173,7 +173,11 @@ export default function Note(props: NoteProps) { } }, [inView, entry, extendable]); - function goToEvent(e: React.MouseEvent, id: u256) { + function goToEvent(e: React.MouseEvent, id: u256, isTargetAllowed: boolean = e.target === e.currentTarget) { + if (!isTargetAllowed) { + return; + } + e.stopPropagation(); // detect cmd key and open in new tab if (e.metaKey) { @@ -282,7 +286,7 @@ export default function Note(props: NoteProps) { )}
)} -
goToEvent(e, ev.Id)}> +
goToEvent(e, ev.Id, true)}> {transformBody()} {translation()} {options.showReactionsLink && ( @@ -315,6 +319,7 @@ export default function Note(props: NoteProps) { const note = (
goToEvent(e, ev.Id)} ref={ref}> {content()}
-- 2.45.2 From 18cdae69924889f581b2952969533cb89becd25f Mon Sep 17 00:00:00 2001 From: d-r-w Date: Tue, 7 Mar 2023 08:59:38 -0600 Subject: [PATCH 16/18] Fixes Prettier issue --- packages/app/src/Element/Note.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/app/src/Element/Note.tsx b/packages/app/src/Element/Note.tsx index 29f75954..815573d1 100644 --- a/packages/app/src/Element/Note.tsx +++ b/packages/app/src/Element/Note.tsx @@ -177,7 +177,7 @@ export default function Note(props: NoteProps) { if (!isTargetAllowed) { return; } - + e.stopPropagation(); // detect cmd key and open in new tab if (e.metaKey) { -- 2.45.2 From d46ac977094e77f45caca817f83f12c2c5a5701d Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Thu, 9 Mar 2023 11:00:00 +0100 Subject: [PATCH 17/18] fix: use main image for badge list --- packages/app/src/Element/BadgeList.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/app/src/Element/BadgeList.tsx b/packages/app/src/Element/BadgeList.tsx index 26dc9bb5..31c270df 100644 --- a/packages/app/src/Element/BadgeList.tsx +++ b/packages/app/src/Element/BadgeList.tsx @@ -23,14 +23,15 @@ export default function BadgeList({ badges }: { badges: TaggedRawEvent[] }) { pubkey: b.pubkey, name, description, - img: thumb?.length ?? 0 > 0 ? thumb : image, + thumb, + image, }; }); return ( <>
setShowModal(!showModal)}> - {badgeMetadata.slice(0, 8).map(({ id, name, img }) => ( - + {badgeMetadata.slice(0, 8).map(({ id, name, thumb }) => ( + ))}
{showModal && ( @@ -45,10 +46,10 @@ export default function BadgeList({ badges }: { badges: TaggedRawEvent[] }) {
- {badgeMetadata.map(({ id, name, pubkey, description, img }) => { + {badgeMetadata.map(({ id, name, pubkey, description, image }) => { return (
- +

{name}

{description}

-- 2.45.2 From 6a987bd585018dec1986c53ff23a68a68d57588a Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Thu, 9 Mar 2023 11:02:24 +0100 Subject: [PATCH 18/18] fix: use image if thumb not available --- packages/app/src/Element/BadgeList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/app/src/Element/BadgeList.tsx b/packages/app/src/Element/BadgeList.tsx index 31c270df..9eec2784 100644 --- a/packages/app/src/Element/BadgeList.tsx +++ b/packages/app/src/Element/BadgeList.tsx @@ -23,7 +23,7 @@ export default function BadgeList({ badges }: { badges: TaggedRawEvent[] }) { pubkey: b.pubkey, name, description, - thumb, + thumb: thumb?.length ?? 0 > 0 ? thumb : image, image, }; }); -- 2.45.2