adding short note creation
This commit is contained in:
parent
b7590b8ca2
commit
d8f9ea6d40
4
.env
4
.env
@ -1,7 +1,7 @@
|
||||
# S3 data storage
|
||||
S3_BUCKET_NAME="flockstr"
|
||||
MY_AWS_ACCESS_KEY="AKIAT2UDOJMC6K25RFFN"
|
||||
MY_AWS_SECRET_KEY="secret"
|
||||
MY_AWS_ACCESS_KEY="AKIAT2UDOJMC4RSXQO5Y"
|
||||
MY_AWS_SECRET_KEY="SwS8fm1+pKlrWU8pzuRCUYqyJ5roNwu9AZRhbWMu"
|
||||
REGION="us-east-1"
|
||||
S3_BUCKET_URL="https://flockstr.s3.amazonaws.com"
|
||||
NEXT_PUBLIC_S3_BUCKET_URL="https://flockstr.s3.amazonaws.com"
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -26,7 +26,7 @@ yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
# .env
|
||||
.env
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
@ -47,7 +47,6 @@ export default function LiveStreamingSection() {
|
||||
if (bParticipants) return 1;
|
||||
return -1;
|
||||
});
|
||||
console.log(processedEvents);
|
||||
return (
|
||||
<Section className="max-sm:-mx-5">
|
||||
<SectionHeader>
|
||||
|
@ -228,9 +228,15 @@ export default function FormModal<TSchema extends FieldValues>({
|
||||
{fieldProps.options?.map((o) => (
|
||||
<CommandItem
|
||||
key={o.value}
|
||||
onClick={() =>
|
||||
console.log("Captured", o.value)
|
||||
}
|
||||
onSelect={() => {
|
||||
setValue(
|
||||
field.name,
|
||||
o.value as PathValue<
|
||||
TSchema,
|
||||
Path<TSchema>
|
||||
>,
|
||||
);
|
||||
}}
|
||||
className="teamaspace-y-1 flex flex-col items-start px-4 py-2"
|
||||
>
|
||||
<p>{o.label}</p>
|
||||
|
@ -2,17 +2,19 @@ import { useEffect, useState } from "react";
|
||||
import FormModal from "./FormModal";
|
||||
import { z } from "zod";
|
||||
import useEvents from "@/lib/hooks/useEvents";
|
||||
import { updateList } from "@/lib/actions/create";
|
||||
import { createEventHandler } from "@/lib/actions/create";
|
||||
import { unixTimeNowInSeconds } from "@/lib/nostr/dates";
|
||||
import { useModal } from "@/app/_providers/modal/provider";
|
||||
import { toast } from "sonner";
|
||||
import { useNDK } from "@/app/_providers/ndk";
|
||||
import { NostrEvent } from "@nostr-dev-kit/ndk";
|
||||
import { useSigner, type SignerStoreItem } from "@/app/_providers/signer";
|
||||
import { getTagValues } from "@/lib/nostr/utils";
|
||||
import useCurrentUser from "@/lib/hooks/useCurrentUser";
|
||||
import { saveEphemeralSigner } from "@/lib/actions/ephemeral";
|
||||
import useLists from "@/lib/hooks/useLists";
|
||||
|
||||
const ShortTextNoteSchema = z.object({
|
||||
content: z.string(),
|
||||
image: z.string().optional(),
|
||||
list: z.string().optional(),
|
||||
isPrivate: z.boolean().optional(),
|
||||
});
|
||||
@ -21,18 +23,19 @@ type ShortTextNoteType = z.infer<typeof ShortTextNoteSchema>;
|
||||
|
||||
export default function ShortTextNoteModal() {
|
||||
const modal = useModal();
|
||||
const { lists, init } = useLists();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { currentUser } = useCurrentUser();
|
||||
const [sent, setSent] = useState(false);
|
||||
const { ndk } = useNDK();
|
||||
// const { events } = useEvents({
|
||||
// filter: {
|
||||
// kinds: [listEvent.kind as number],
|
||||
// authors: [listEvent.pubkey],
|
||||
// since: unixTimeNowInSeconds() - 10,
|
||||
// limit: 1,
|
||||
// },
|
||||
// enabled: sent,
|
||||
// });
|
||||
const { getSigner } = useSigner()!;
|
||||
|
||||
useEffect(() => {
|
||||
if (currentUser) {
|
||||
void init(currentUser.pubkey);
|
||||
}
|
||||
}, [currentUser]);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (events.length) {
|
||||
// console.log("Done!");
|
||||
@ -42,11 +45,69 @@ export default function ShortTextNoteModal() {
|
||||
// }
|
||||
// }, [events]);
|
||||
|
||||
async function handleSubmit(listData: ShortTextNoteType) {
|
||||
async function handleSubmit(data: ShortTextNoteType) {
|
||||
setIsLoading(true);
|
||||
const newTags = Object.entries(listData);
|
||||
setSent(true);
|
||||
// const result = await updateList(ndk!, listEvent, newTags);
|
||||
if (!ndk) {
|
||||
toast.error("Error connecting");
|
||||
return;
|
||||
}
|
||||
if (data.list) {
|
||||
const list = lists.find((l) => getTagValues("d", l.tags) === data.list);
|
||||
if (!list) {
|
||||
toast.error("No list found");
|
||||
return;
|
||||
}
|
||||
let listSigner: SignerStoreItem | undefined = undefined;
|
||||
if (data.isPrivate) {
|
||||
listSigner = await getSigner(list);
|
||||
if (!listSigner?.signer) {
|
||||
toast.error("Error creating signer");
|
||||
return;
|
||||
}
|
||||
if (!listSigner?.saved) {
|
||||
console.log("Saving delegate...");
|
||||
await saveEphemeralSigner(ndk!, listSigner.signer, {
|
||||
associatedEvent: list,
|
||||
keyProfile: {
|
||||
name: listSigner.title,
|
||||
picture: currentUser?.profile?.image,
|
||||
lud06: currentUser?.profile?.lud06,
|
||||
lud16: currentUser?.profile?.lud16,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const result = await createEventHandler(
|
||||
ndk,
|
||||
{
|
||||
content: data.content,
|
||||
kind: 1,
|
||||
tags: [],
|
||||
},
|
||||
data.isPrivate,
|
||||
list,
|
||||
listSigner?.signer,
|
||||
);
|
||||
if (result) {
|
||||
toast.success("Note added!");
|
||||
modal?.hide();
|
||||
}
|
||||
} else {
|
||||
const result = await createEventHandler(
|
||||
ndk,
|
||||
{
|
||||
content: data.content,
|
||||
kind: 1,
|
||||
tags: [],
|
||||
},
|
||||
data.isPrivate,
|
||||
);
|
||||
if (result) {
|
||||
toast.success("Note added!");
|
||||
modal?.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
@ -63,20 +124,23 @@ export default function ShortTextNoteModal() {
|
||||
type: "select-search",
|
||||
placeholder: "Search your lists",
|
||||
slug: "list",
|
||||
options: [
|
||||
{
|
||||
label: "Spicy Takes 🌶️",
|
||||
value: "325grg ",
|
||||
},
|
||||
{
|
||||
label: "Public reading list",
|
||||
value: "grherh ",
|
||||
},
|
||||
{
|
||||
label: "Radnosm other",
|
||||
value: "grhfaggferh ",
|
||||
},
|
||||
],
|
||||
options: lists
|
||||
.map((l) => {
|
||||
console.log("MApping", l);
|
||||
const title =
|
||||
getTagValues("title", l.tags) ??
|
||||
getTagValues("name", l.tags) ??
|
||||
"Untitled";
|
||||
const description = getTagValues("description", l.tags);
|
||||
const value = getTagValues("d", l.tags);
|
||||
if (!value) return;
|
||||
return {
|
||||
label: title,
|
||||
description,
|
||||
value: value,
|
||||
};
|
||||
})
|
||||
.filter(Boolean),
|
||||
},
|
||||
{
|
||||
label: "Private",
|
||||
|
@ -41,6 +41,90 @@ export async function createEvent(
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export async function createEventHandler(
|
||||
ndk: NDK,
|
||||
event: {
|
||||
content: string;
|
||||
kind: number;
|
||||
tags: string[][];
|
||||
},
|
||||
isPrivate?: boolean,
|
||||
list?: NDKList,
|
||||
delegateSigner?: NDKPrivateKeySigner,
|
||||
) {
|
||||
const pubkey = await window.nostr?.getPublicKey();
|
||||
if (!pubkey || !window.nostr) {
|
||||
throw new Error("No public key provided!");
|
||||
}
|
||||
const eventToPublish = new NDKEvent(ndk, {
|
||||
...event,
|
||||
tags: [...event.tags, ["client", "ordstr"]],
|
||||
pubkey,
|
||||
created_at: unixTimeNowInSeconds(),
|
||||
} as NostrEvent);
|
||||
|
||||
await eventToPublish.sign();
|
||||
|
||||
let publishedEvent: NDKEvent | null = null;
|
||||
// Check if is private event
|
||||
if (isPrivate) {
|
||||
const rawEventString = JSON.stringify(eventToPublish.rawEvent());
|
||||
const passphrase = generateRandomString();
|
||||
const encryptedRawEventString = await encryptMessage(
|
||||
rawEventString,
|
||||
passphrase,
|
||||
);
|
||||
const signer = delegateSigner ?? ndk.signer!;
|
||||
const user = await signer.user();
|
||||
const newEvent = new NDKEvent(ndk, {
|
||||
content: encryptedRawEventString,
|
||||
kind: 3745,
|
||||
tags: [
|
||||
["kind", event.kind.toString()],
|
||||
["client", "ordstr"],
|
||||
],
|
||||
pubkey: user.pubkey,
|
||||
} as NostrEvent);
|
||||
await newEvent.sign(signer);
|
||||
await newEvent.publish();
|
||||
|
||||
if (list) {
|
||||
// Send DMs to subscribers
|
||||
const subscribers = getTagsValues("p", list.tags);
|
||||
for (const subscriber of subscribers) {
|
||||
const messageEvent = new NDKEvent(ndk, {
|
||||
content: passphrase,
|
||||
kind: 4,
|
||||
tags: [
|
||||
["p", subscriber],
|
||||
["e", newEvent.id],
|
||||
["client", "ordstr"],
|
||||
],
|
||||
pubkey: user.pubkey,
|
||||
} as NostrEvent);
|
||||
await messageEvent.encrypt(
|
||||
new NDKUser({ hexpubkey: subscriber }),
|
||||
signer,
|
||||
);
|
||||
await messageEvent.sign(signer);
|
||||
await messageEvent.publish();
|
||||
}
|
||||
}
|
||||
publishedEvent = newEvent;
|
||||
} else {
|
||||
await eventToPublish.publish();
|
||||
publishedEvent = eventToPublish;
|
||||
}
|
||||
if (list) {
|
||||
const tag = publishedEvent.tagReference();
|
||||
if (!tag) return;
|
||||
// Add event to list
|
||||
await list.addItem(tag, undefined, false);
|
||||
await list.sign();
|
||||
await list.publish();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
export async function createEncryptedEventOnPrivateList(
|
||||
ndk: NDK,
|
||||
event: {
|
||||
@ -64,7 +148,6 @@ export async function createEncryptedEventOnPrivateList(
|
||||
await eventToPublish.sign();
|
||||
const rawEventString = JSON.stringify(eventToPublish.rawEvent());
|
||||
const passphrase = generateRandomString();
|
||||
// const passphrase = "test";
|
||||
const encryptedRawEventString = await encryptMessage(
|
||||
rawEventString,
|
||||
passphrase,
|
||||
@ -79,7 +162,7 @@ export async function createEncryptedEventOnPrivateList(
|
||||
["kind", event.kind.toString()],
|
||||
["client", "ordstr"],
|
||||
],
|
||||
pubkey: user.hexpubkey,
|
||||
pubkey: user.pubkey,
|
||||
} as NostrEvent);
|
||||
|
||||
await newEvent.sign(signer);
|
||||
|
@ -5,7 +5,7 @@ import currentUserStore from "@/lib/stores/currentUser";
|
||||
import { UserSchema } from "@/types";
|
||||
import { useNDK } from "@/app/_providers/ndk";
|
||||
import { nip19 } from "nostr-tools";
|
||||
|
||||
import useLists from "./useLists";
|
||||
export default function useCurrentUser() {
|
||||
const {
|
||||
currentUser,
|
||||
@ -15,30 +15,7 @@ export default function useCurrentUser() {
|
||||
follows,
|
||||
} = currentUserStore();
|
||||
const { loginWithNip07, getProfile, ndk } = useNDK();
|
||||
|
||||
// const {
|
||||
// events: contactList,
|
||||
// isLoading,
|
||||
// onEvent,
|
||||
// } = useEvents({
|
||||
// filter: {
|
||||
// kinds: [3],
|
||||
// authors: [currentUser?.pubkey ?? ""],
|
||||
// limit: 1,
|
||||
// },
|
||||
// enabled: !!currentUser,
|
||||
// });
|
||||
// onEvent((event) => {
|
||||
// console.log("EVENT", event);
|
||||
// const foundFollows = event.tags
|
||||
// .filter(([key]) => key === "p")
|
||||
// .map(([key, pubkey]) => pubkey);
|
||||
// console.log("Found follows", foundFollows);
|
||||
// if (follows.length !== foundFollows.length) {
|
||||
// setFollows(follows);
|
||||
// }
|
||||
// });
|
||||
|
||||
const { init } = useLists();
|
||||
async function attemptLogin() {
|
||||
try {
|
||||
const shouldReconnect = localStorage.getItem("shouldReconnect");
|
||||
@ -86,6 +63,7 @@ export default function useCurrentUser() {
|
||||
console.log("user", user);
|
||||
await user.fetchProfile();
|
||||
setCurrentUser(user);
|
||||
void init(user.pubkey);
|
||||
}
|
||||
|
||||
return {
|
||||
|
33
lib/hooks/useLists.ts
Normal file
33
lib/hooks/useLists.ts
Normal file
@ -0,0 +1,33 @@
|
||||
"use client";
|
||||
|
||||
import listsStore from "@/lib/stores/lists";
|
||||
import { useNDK } from "@/app/_providers/ndk";
|
||||
import { useState } from "react";
|
||||
import { NDKList } from "@nostr-dev-kit/ndk";
|
||||
|
||||
export default function useLists() {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { lists, setLists, follows } = listsStore();
|
||||
const { fetchEvents, ndk } = useNDK();
|
||||
async function init(pubkey: string) {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const listEvents = await fetchEvents({
|
||||
kinds: [30001],
|
||||
authors: [pubkey],
|
||||
});
|
||||
setLists(listEvents.map((l) => new NDKList(ndk, l.rawEvent())));
|
||||
} catch (err) {
|
||||
console.log("error in init", err);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
lists,
|
||||
isLoading,
|
||||
init,
|
||||
follows,
|
||||
};
|
||||
}
|
18
lib/stores/lists.ts
Normal file
18
lib/stores/lists.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { create } from "zustand";
|
||||
import { type NDKList } from "@nostr-dev-kit/ndk";
|
||||
|
||||
interface CurrentUserState {
|
||||
lists: NDKList[];
|
||||
follows: string[];
|
||||
setLists: (lists: NDKList[]) => void;
|
||||
setFollows: (follows: string[]) => void;
|
||||
}
|
||||
|
||||
const listsStore = create<CurrentUserState>()((set) => ({
|
||||
lists: [],
|
||||
follows: [],
|
||||
setLists: (lists) => set((state) => ({ ...state, lists: lists })),
|
||||
setFollows: (follows) => set((state) => ({ ...state, follows: follows })),
|
||||
}));
|
||||
|
||||
export default listsStore;
|
Loading…
x
Reference in New Issue
Block a user