feat: client tags
This commit is contained in:
@ -1,16 +1,3 @@
|
|||||||
.note > .header .reply {
|
|
||||||
font-size: 13px;
|
|
||||||
color: var(--font-secondary-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.note > .header .reply a {
|
|
||||||
color: var(--highlight);
|
|
||||||
}
|
|
||||||
|
|
||||||
.note > .header .reply a:hover {
|
|
||||||
text-decoration-color: var(--highlight);
|
|
||||||
}
|
|
||||||
|
|
||||||
.note .header .info {
|
.note .header .info {
|
||||||
font-size: var(--font-size);
|
font-size: var(--font-size);
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
@ -57,8 +44,7 @@
|
|||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note > .header img:hover,
|
.note > .header img:hover {
|
||||||
.note > .header .name > .reply:hover {
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
21
packages/app/src/Components/Event/Note/ClientTag.tsx
Normal file
21
packages/app/src/Components/Event/Note/ClientTag.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { NostrLink, TaggedNostrEvent } from "@snort/system";
|
||||||
|
import { FormattedMessage } from "react-intl";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
export function ClientTag({ ev }: { ev: TaggedNostrEvent }) {
|
||||||
|
const tag = ev.tags.find(a => a[0] === "client");
|
||||||
|
if (!tag) return;
|
||||||
|
const link = tag[2] ? NostrLink.fromTag(["a", tag[2]]) : undefined;
|
||||||
|
return (
|
||||||
|
<span className="text-xs text-gray-light">
|
||||||
|
{" "}
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="via {client}"
|
||||||
|
description="via {client name} tag"
|
||||||
|
values={{
|
||||||
|
client: link ? <Link to={`/${link.encode()}`}>{tag[1]}</Link> : tag[1],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
@ -9,11 +9,13 @@ import DisplayName from "@/Components/User/DisplayName";
|
|||||||
import { ProfileLink } from "@/Components/User/ProfileLink";
|
import { ProfileLink } from "@/Components/User/ProfileLink";
|
||||||
import { hexToBech32 } from "@/Utils";
|
import { hexToBech32 } from "@/Utils";
|
||||||
|
|
||||||
|
import { ClientTag } from "./ClientTag";
|
||||||
|
|
||||||
export default function ReplyTag({ ev }: { ev: TaggedNostrEvent }) {
|
export default function ReplyTag({ ev }: { ev: TaggedNostrEvent }) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const thread = EventExt.extractThread(ev);
|
const thread = EventExt.extractThread(ev);
|
||||||
if (thread === undefined) {
|
if (thread === undefined) {
|
||||||
return undefined;
|
return <ClientTag ev={ev} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxMentions = 2;
|
const maxMentions = 2;
|
||||||
@ -33,7 +35,7 @@ export default function ReplyTag({ ev }: { ev: TaggedNostrEvent }) {
|
|||||||
name: u?.name ?? shortNpub,
|
name: u?.name ?? shortNpub,
|
||||||
link: (
|
link: (
|
||||||
<ProfileLink pubkey={pk} user={u}>
|
<ProfileLink pubkey={pk} user={u}>
|
||||||
<DisplayName pubkey={pk} user={u} />{" "}
|
<DisplayName pubkey={pk} user={u} className="text-highlight" />
|
||||||
</ProfileLink>
|
</ProfileLink>
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
@ -53,7 +55,7 @@ export default function ReplyTag({ ev }: { ev: TaggedNostrEvent }) {
|
|||||||
const others = mentions.length > maxMentions ? formatMessage(messages.Others, { n: othersLength }) : "";
|
const others = mentions.length > maxMentions ? formatMessage(messages.Others, { n: othersLength }) : "";
|
||||||
const link = replyLink?.encode(CONFIG.eventLinkPrefix);
|
const link = replyLink?.encode(CONFIG.eventLinkPrefix);
|
||||||
return (
|
return (
|
||||||
<div className="reply">
|
<small className="text-xs">
|
||||||
re:
|
re:
|
||||||
{(mentions?.length ?? 0) > 0 ? (
|
{(mentions?.length ?? 0) > 0 ? (
|
||||||
<>
|
<>
|
||||||
@ -62,6 +64,7 @@ export default function ReplyTag({ ev }: { ev: TaggedNostrEvent }) {
|
|||||||
) : (
|
) : (
|
||||||
replyLink && <Link to={`/${link}`}>{link?.substring(0, 12)}</Link>
|
replyLink && <Link to={`/${link}`}>{link?.substring(0, 12)}</Link>
|
||||||
)}
|
)}
|
||||||
</div>
|
<ClientTag ev={ev} />
|
||||||
|
</small>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -179,6 +179,10 @@ a.ext {
|
|||||||
-webkit-text-stroke: 1px black;
|
-webkit-text-stroke: 1px black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-highlight {
|
||||||
|
color: var(--highlight);
|
||||||
|
}
|
||||||
|
|
||||||
.br {
|
.br {
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
}
|
}
|
||||||
|
@ -773,6 +773,10 @@
|
|||||||
"GspYR7": {
|
"GspYR7": {
|
||||||
"defaultMessage": "{n} Dislike"
|
"defaultMessage": "{n} Dislike"
|
||||||
},
|
},
|
||||||
|
"GtIxzZ": {
|
||||||
|
"defaultMessage": "via {client}",
|
||||||
|
"description": "via {client name} tag"
|
||||||
|
},
|
||||||
"Gxcr08": {
|
"Gxcr08": {
|
||||||
"defaultMessage": "Broadcast Event"
|
"defaultMessage": "Broadcast Event"
|
||||||
},
|
},
|
||||||
|
@ -256,6 +256,7 @@
|
|||||||
"GpkNYn": "Torrent",
|
"GpkNYn": "Torrent",
|
||||||
"GqQeu/": "Invalid Lightning Address",
|
"GqQeu/": "Invalid Lightning Address",
|
||||||
"GspYR7": "{n} Dislike",
|
"GspYR7": "{n} Dislike",
|
||||||
|
"GtIxzZ": "via {client}",
|
||||||
"Gxcr08": "Broadcast Event",
|
"Gxcr08": "Broadcast Event",
|
||||||
"H+vHiz": "Hex Key..",
|
"H+vHiz": "Hex Key..",
|
||||||
"H/oroO": "Dealing with Unknown Events",
|
"H/oroO": "Dealing with Unknown Events",
|
||||||
|
@ -243,8 +243,8 @@ export function isHex(s?: string) {
|
|||||||
// 48-57 = 0-9
|
// 48-57 = 0-9
|
||||||
// 65-90 = A-Z
|
// 65-90 = A-Z
|
||||||
// 97-122 = a-z
|
// 97-122 = a-z
|
||||||
return s.length % 2 == 0 &&
|
return (
|
||||||
[...s]
|
s.length % 2 == 0 &&
|
||||||
.map(v => v.charCodeAt(0))
|
[...s].map(v => v.charCodeAt(0)).every(v => (v >= 48 && v <= 57) || (v >= 65 && v <= 90) || v >= 97 || v <= 122)
|
||||||
.every(v => (v >= 48 && v <= 57) || (v >= 65 && v <= 90) || v >= 97 || v <= 122);
|
);
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,11 @@ export class NostrLink implements ToNostrEventTag {
|
|||||||
const ifSetCheck = <T>(a: T | undefined, b: T) => {
|
const ifSetCheck = <T>(a: T | undefined, b: T) => {
|
||||||
return !Boolean(a) || a === b;
|
return !Boolean(a) || a === b;
|
||||||
};
|
};
|
||||||
return (EventExt.isReplaceable(ev.kind) || ifSetCheck(this.id, ev.id)) && ifSetCheck(this.author, ev.pubkey) && ifSetCheck(this.kind, ev.kind);
|
return (
|
||||||
|
(EventExt.isReplaceable(ev.kind) || ifSetCheck(this.id, ev.id)) &&
|
||||||
|
ifSetCheck(this.author, ev.pubkey) &&
|
||||||
|
ifSetCheck(this.kind, ev.kind)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -74,13 +74,19 @@ export class UserState<TAppData> extends EventEmitter<UserStateEvents> {
|
|||||||
this.#stateObj = stateObj;
|
this.#stateObj = stateObj;
|
||||||
this.#standardLists = pubkey ? new Map() : undefined;
|
this.#standardLists = pubkey ? new Map() : undefined;
|
||||||
|
|
||||||
this.#profile = pubkey ? new JsonEventSync<UserMetadata | undefined>(
|
this.#profile = pubkey
|
||||||
|
? new JsonEventSync<UserMetadata | undefined>(
|
||||||
undefined,
|
undefined,
|
||||||
new NostrLink(NostrPrefix.Event, pubkey, EventKind.SetMetadata, pubkey),
|
new NostrLink(NostrPrefix.Event, pubkey, EventKind.SetMetadata, pubkey),
|
||||||
false,
|
false,
|
||||||
) : undefined;
|
)
|
||||||
this.#contacts = pubkey ? new DiffSyncTags(new NostrLink(NostrPrefix.Event, pubkey, EventKind.ContactList, pubkey), false) : undefined;
|
: undefined;
|
||||||
this.#relays = pubkey ? new DiffSyncTags(new NostrLink(NostrPrefix.Event, pubkey, EventKind.Relays, pubkey), false) : undefined;
|
this.#contacts = pubkey
|
||||||
|
? new DiffSyncTags(new NostrLink(NostrPrefix.Event, pubkey, EventKind.ContactList, pubkey), false)
|
||||||
|
: undefined;
|
||||||
|
this.#relays = pubkey
|
||||||
|
? new DiffSyncTags(new NostrLink(NostrPrefix.Event, pubkey, EventKind.Relays, pubkey), false)
|
||||||
|
: undefined;
|
||||||
if (options?.appdataId && options.initAppdata) {
|
if (options?.appdataId && options.initAppdata) {
|
||||||
const link = new NostrLink(NostrPrefix.Address, options.appdataId, EventKind.AppData, pubkey);
|
const link = new NostrLink(NostrPrefix.Address, options.appdataId, EventKind.AppData, pubkey);
|
||||||
this.#appdata = new JsonEventSync<TAppData>(options.initAppdata, link, options.encryptAppdata ?? false);
|
this.#appdata = new JsonEventSync<TAppData>(options.initAppdata, link, options.encryptAppdata ?? false);
|
||||||
|
@ -13433,7 +13433,6 @@ __metadata:
|
|||||||
prettier: "npm:^3.0.3"
|
prettier: "npm:^3.0.3"
|
||||||
typedoc: "npm:^0.25.7"
|
typedoc: "npm:^0.25.7"
|
||||||
typescript: "npm:^5.2.2"
|
typescript: "npm:^5.2.2"
|
||||||
vite-plugin-version-mark: "npm:^0.1.4"
|
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user