mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-03-29 11:12:12 +01:00
Display NIP-89 client tags on events
This commit is contained in:
parent
8bb7fc1cee
commit
085e12a699
5
.changeset/beige-falcons-shake.md
Normal file
5
.changeset/beige-falcons-shake.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"nostrudel": minor
|
||||
---
|
||||
|
||||
Display NIP-89 client tags on events
|
@ -13,6 +13,7 @@ COPY . .
|
||||
|
||||
ENV VITE_COMMIT_HASH=""
|
||||
ENV VITE_APP_VERSION="custom"
|
||||
ENV ENABLE_CLIENT_TAG="false"
|
||||
RUN yarn build
|
||||
|
||||
FROM nginx:stable-alpine-slim AS main
|
||||
|
13
src/components/note/note-published-using.tsx
Normal file
13
src/components/note/note-published-using.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import { Text } from "@chakra-ui/react";
|
||||
import { NostrEvent } from "nostr-tools";
|
||||
|
||||
export default function NotePublishedUsing({ event }: { event: NostrEvent }) {
|
||||
const clientTag = event.tags.find((t) => t[0] === "client");
|
||||
if (!clientTag) return;
|
||||
|
||||
return (
|
||||
<Text as="span" fontStyle="italic" fontSize="sm">
|
||||
using {clientTag[1]}
|
||||
</Text>
|
||||
);
|
||||
}
|
@ -47,6 +47,7 @@ import ZapBubbles from "./components/zap-bubbles";
|
||||
import useEventIntersectionRef from "../../../hooks/use-event-intersection-ref";
|
||||
import relayHintService from "../../../services/event-relay-hint";
|
||||
import localSettings from "../../../services/local-settings";
|
||||
import NotePublishedUsing from "../note-published-using";
|
||||
|
||||
export type TimelineNoteProps = Omit<CardProps, "children"> & {
|
||||
event: NostrEvent;
|
||||
@ -108,6 +109,7 @@ export function TimelineNote({
|
||||
<Timestamp timestamp={event.created_at} />
|
||||
</Link>
|
||||
<POWIcon event={event} boxSize={5} />
|
||||
<NotePublishedUsing event={event} />
|
||||
<Flex grow={1} />
|
||||
{showSignatureVerification && <EventVerificationIcon event={event} />}
|
||||
{!hideDrawerButton && (
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { kinds } from "nostr-tools";
|
||||
import { safeRelayUrl, safeRelayUrls } from "./helpers/relay";
|
||||
|
||||
export const DEFAULT_SEARCH_RELAYS = safeRelayUrls([
|
||||
@ -45,3 +46,11 @@ export const NOSTR_CONNECT_PERMISSIONS = [
|
||||
"sign_event:6",
|
||||
"sign_event:7",
|
||||
];
|
||||
|
||||
export const NEVER_ATTACH_CLIENT_TAG = [kinds.EncryptedDirectMessage];
|
||||
export const ENABLE_CLIENT_TAG = import.meta.env.VITE_ENABLE_CLIENT_TAG !== "false";
|
||||
export const NIP_89_CLIENT_TAG = [
|
||||
"client",
|
||||
"noStrudel",
|
||||
"31990:266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5:1686066542546",
|
||||
];
|
||||
|
@ -13,6 +13,8 @@ import eventReactionsService from "../../services/event-reactions";
|
||||
import { localRelay } from "../../services/local-relay";
|
||||
import deleteEventService from "../../services/delete-events";
|
||||
import userMailboxesService from "../../services/user-mailboxes";
|
||||
import localSettings from "../../services/local-settings";
|
||||
import { NEVER_ATTACH_CLIENT_TAG, NIP_89_CLIENT_TAG } from "../../const";
|
||||
|
||||
type PublishContextType = {
|
||||
log: PublishAction[];
|
||||
@ -78,7 +80,16 @@ export default function PublishProvider({ children }: PropsWithChildren) {
|
||||
let signed: NostrEvent;
|
||||
if (!Object.hasOwn(event, "sig")) {
|
||||
let draft: EventTemplate = event as EventTemplate;
|
||||
|
||||
// add pubkey relay hints
|
||||
draft = userMailboxesService.addPubkeyRelayHints(draft);
|
||||
|
||||
// add client tag
|
||||
if (localSettings.addClientTag.value && !NEVER_ATTACH_CLIENT_TAG.includes(event.kind)) {
|
||||
draft.tags = [...draft.tags.filter((t) => t[0] !== "client"), NIP_89_CLIENT_TAG];
|
||||
}
|
||||
|
||||
// request signature
|
||||
signed = await requestSignature(draft);
|
||||
} else signed = event as NostrEvent;
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { generateSecretKey } from "nostr-tools";
|
||||
import { bytesToHex, hexToBytes } from "@noble/hashes/utils";
|
||||
|
||||
import { PersistentSubject } from "../classes/subject";
|
||||
import { DEFAULT_SIGNAL_RELAYS } from "../const";
|
||||
import { ENABLE_CLIENT_TAG, DEFAULT_SIGNAL_RELAYS } from "../const";
|
||||
import {
|
||||
BooleanLocalStorageEntry,
|
||||
NullableNumberLocalStorageEntry,
|
||||
@ -45,6 +44,9 @@ const webRtcRecentConnections = new LocalStorageEntry(
|
||||
(value) => value.join(","),
|
||||
);
|
||||
|
||||
// posting
|
||||
const addClientTag = new BooleanLocalStorageEntry("add-client-tag", ENABLE_CLIENT_TAG);
|
||||
|
||||
const localSettings = {
|
||||
idbMaxEvents,
|
||||
wasmPersistForDays,
|
||||
@ -53,6 +55,7 @@ const localSettings = {
|
||||
webRtcLocalIdentity,
|
||||
webRtcSignalingRelays,
|
||||
webRtcRecentConnections,
|
||||
addClientTag,
|
||||
};
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
AlertTitle,
|
||||
AlertDescription,
|
||||
Heading,
|
||||
Switch,
|
||||
} from "@chakra-ui/react";
|
||||
import { matchSorter } from "match-sorter";
|
||||
|
||||
@ -28,6 +29,8 @@ import useUsersMediaServers from "../../../hooks/use-user-media-servers";
|
||||
import useCurrentAccount from "../../../hooks/use-current-account";
|
||||
import useSettingsForm from "../use-settings-form";
|
||||
import VerticalPageLayout from "../../../components/vertical-page-layout";
|
||||
import localSettings from "../../../services/local-settings";
|
||||
import useSubject from "../../../hooks/use-subject";
|
||||
|
||||
export default function PostSettings() {
|
||||
const account = useCurrentAccount();
|
||||
@ -64,6 +67,8 @@ export default function PostSettings() {
|
||||
);
|
||||
};
|
||||
|
||||
const addClientTag = useSubject(localSettings.addClientTag);
|
||||
|
||||
return (
|
||||
<VerticalPageLayout as="form" onSubmit={submit} flex={1}>
|
||||
<Heading size="md">Post Settings</Heading>
|
||||
@ -158,6 +163,26 @@ export default function PostSettings() {
|
||||
<span>How much Proof of work to mine when writing notes. setting this to 0 will disable it</span>
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
<FormControl>
|
||||
<Flex alignItems="center">
|
||||
<FormLabel htmlFor="autoShowMedia" mb="0">
|
||||
Add client tag
|
||||
</FormLabel>
|
||||
<Switch
|
||||
id="autoShowMedia"
|
||||
isChecked={addClientTag}
|
||||
onChange={() => localSettings.addClientTag.next(!localSettings.addClientTag.value)}
|
||||
/>
|
||||
</Flex>
|
||||
<FormHelperText>
|
||||
Enabled: Attach the{" "}
|
||||
<Link isExternal href="https://github.com/nostr-protocol/nips/blob/master/89.md#client-tag">
|
||||
NIP-89
|
||||
</Link>{" "}
|
||||
client tag to events
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
</Flex>
|
||||
<Button
|
||||
ml="auto"
|
||||
|
@ -30,6 +30,7 @@ import ZapBubbles from "../../../components/note/timeline-note/components/zap-bu
|
||||
import DetailsTabs from "./details-tabs";
|
||||
import useEventIntersectionRef from "../../../hooks/use-event-intersection-ref";
|
||||
import relayHintService from "../../../services/event-relay-hint";
|
||||
import NotePublishedUsing from "../../../components/note/note-published-using";
|
||||
|
||||
export type ThreadItemProps = {
|
||||
post: ThreadItem;
|
||||
@ -45,6 +46,7 @@ function ThreadPost({ post, initShowReplies, focusId, level = -1 }: ThreadItemPr
|
||||
|
||||
const muteFilter = useClientSideMuteFilter();
|
||||
|
||||
const isFocused = level === -1;
|
||||
const replies = post.replies.filter((r) => !muteFilter(r.event));
|
||||
const numberOfReplies = countReplies(replies);
|
||||
const isMuted = muteFilter(post.event);
|
||||
@ -67,7 +69,6 @@ function ThreadPost({ post, initShowReplies, focusId, level = -1 }: ThreadItemPr
|
||||
<UserAvatarLink pubkey={post.event.pubkey} size="sm" />
|
||||
<UserLink pubkey={post.event.pubkey} fontWeight="bold" isTruncated />
|
||||
<UserDnsIdentity pubkey={post.event.pubkey} onlyIcon />
|
||||
<POWIcon event={post.event} boxSize={5} />
|
||||
<Link
|
||||
as={RouterLink}
|
||||
whiteSpace="nowrap"
|
||||
@ -76,19 +77,23 @@ function ThreadPost({ post, initShowReplies, focusId, level = -1 }: ThreadItemPr
|
||||
>
|
||||
<Timestamp timestamp={post.event.created_at} />
|
||||
</Link>
|
||||
{replies.length > 0 ? (
|
||||
<Button variant="ghost" onClick={expanded.onToggle} rightIcon={expanded.isOpen ? <Minus /> : <Expand01 />}>
|
||||
({numberOfReplies})
|
||||
</Button>
|
||||
) : (
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
onClick={expanded.onToggle}
|
||||
icon={expanded.isOpen ? <Minus /> : <Expand01 />}
|
||||
aria-label={expanded.isOpen ? "Collapse" : "Expand"}
|
||||
title={expanded.isOpen ? "Collapse" : "Expand"}
|
||||
/>
|
||||
)}
|
||||
<POWIcon event={post.event} boxSize={5} />
|
||||
<NotePublishedUsing event={post.event} />
|
||||
<Spacer />
|
||||
{!isFocused &&
|
||||
(replies.length > 0 ? (
|
||||
<Button variant="ghost" onClick={expanded.onToggle} rightIcon={expanded.isOpen ? <Minus /> : <Expand01 />}>
|
||||
({numberOfReplies})
|
||||
</Button>
|
||||
) : (
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
onClick={expanded.onToggle}
|
||||
icon={expanded.isOpen ? <Minus /> : <Expand01 />}
|
||||
aria-label={expanded.isOpen ? "Collapse" : "Expand"}
|
||||
title={expanded.isOpen ? "Collapse" : "Expand"}
|
||||
/>
|
||||
))}
|
||||
</Flex>
|
||||
);
|
||||
|
||||
@ -153,7 +158,7 @@ function ThreadPost({ post, initShowReplies, focusId, level = -1 }: ThreadItemPr
|
||||
)}
|
||||
</Flex>
|
||||
{replyForm.isOpen && <ReplyForm item={post} onCancel={replyForm.onClose} onSubmitted={replyForm.onClose} />}
|
||||
{level === -1 ? (
|
||||
{isFocused ? (
|
||||
<DetailsTabs post={post} />
|
||||
) : (
|
||||
expanded.isOpen &&
|
||||
|
Loading…
x
Reference in New Issue
Block a user