Skip to content

Commit

Permalink
Display NIP-89 client tags on events
Browse files Browse the repository at this point in the history
  • Loading branch information
hzrd149 committed Aug 30, 2024
1 parent 8bb7fc1 commit 085e12a
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .changeset/beige-falcons-shake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"nostrudel": minor
---

Display NIP-89 client tags on events
1 change: 1 addition & 0 deletions dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions src/components/note/note-published-using.tsx
Original file line number Diff line number Diff line change
@@ -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>
);
}
2 changes: 2 additions & 0 deletions src/components/note/timeline-note/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 && (
Expand Down
9 changes: 9 additions & 0 deletions src/const.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { kinds } from "nostr-tools";
import { safeRelayUrl, safeRelayUrls } from "./helpers/relay";

export const DEFAULT_SEARCH_RELAYS = safeRelayUrls([
Expand Down Expand Up @@ -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",
];
11 changes: 11 additions & 0 deletions src/providers/global/publish-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
Expand Down Expand Up @@ -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;

Expand Down
7 changes: 5 additions & 2 deletions src/services/local-settings.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -53,6 +55,7 @@ const localSettings = {
webRtcLocalIdentity,
webRtcSignalingRelays,
webRtcRecentConnections,
addClientTag,
};

if (import.meta.env.DEV) {
Expand Down
25 changes: 25 additions & 0 deletions src/views/settings/post/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
AlertTitle,
AlertDescription,
Heading,
Switch,
} from "@chakra-ui/react";
import { matchSorter } from "match-sorter";

Expand All @@ -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();
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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"
Expand Down
35 changes: 20 additions & 15 deletions src/views/thread/components/thread-post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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"
Expand All @@ -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>
);

Expand Down Expand Up @@ -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 &&
Expand Down

0 comments on commit 085e12a

Please sign in to comment.