From 1099d342fea9b7129b0479408fca67b835de3496 Mon Sep 17 00:00:00 2001 From: BlowaterNostr <127284497+BlowaterNostr@users.noreply.github.com> Date: Fri, 14 Jul 2023 18:59:25 +0800 Subject: [PATCH] add Profile_Nostr_Event (#78) --- UI/app.tsx | 8 ++--- UI/app_update.ts | 12 ++++---- UI/contact-list.ts | 17 ++++++++--- UI/contact-list.tsx | 4 +-- UI/dm.ts | 8 ++--- UI/dm.tsx | 4 +-- UI/message-panel.tsx | 2 +- UI/search_model.ts | 2 +- features/profile.ts | 69 +++++++++++++++++++++++++++++--------------- features/social.ts | 4 +-- nostr.ts | 6 +++- 11 files changed, 85 insertions(+), 51 deletions(-) diff --git a/UI/app.tsx b/UI/app.tsx index 2957d54..b3e8da9 100644 --- a/UI/app.tsx +++ b/UI/app.tsx @@ -184,7 +184,7 @@ export class App { this.model.social.threads = getSocialPosts(this.database, this.model.allUsersInfo); /* my profile */ - this.model.myProfile = this.model.allUsersInfo.get(accountContext.publicKey.hex)?.profile?.content; + this.model.myProfile = this.model.allUsersInfo.get(accountContext.publicKey.hex)?.profile?.profile; /* contacts */ for (const contact of this.model.allUsersInfo.values()) { @@ -198,8 +198,8 @@ export class App { contact.pubkey.hex, new_DM_EditorModel({ pubkey, - name: contact.profile?.content.name, - picture: contact.profile?.content.picture, + name: contact.profile?.profile.name, + picture: contact.profile?.profile.picture, }), ); } @@ -438,7 +438,7 @@ export function getFocusedContent( return; } if (focusedContent instanceof PublicKey) { - const profileData = allUserInfo.get(focusedContent.hex)?.profile?.content; + const profileData = allUserInfo.get(focusedContent.hex)?.profile?.profile; return { type: "ProfileData" as "ProfileData", data: profileData, diff --git a/UI/app_update.ts b/UI/app_update.ts index 8659a2e..2dfcedc 100644 --- a/UI/app_update.ts +++ b/UI/app_update.ts @@ -165,7 +165,7 @@ export async function* UI_Interaction_Update( const profile = getProfileEvent(model.app.database, pubkey); model.dm.search.searchResults = [{ pubkey: pubkey, - profile: profile?.content, + profile: profile?.profile, }]; } else { const profiles = getProfilesByName(model.app.database, event.text); @@ -176,7 +176,7 @@ export async function* UI_Interaction_Update( } return { pubkey: pubkey, - profile: p.content, + profile: p.profile, }; }); } @@ -499,7 +499,7 @@ export async function* Database_Update( const profileEvent = getProfileEvent(database, profile.pubkey); return { pubkey: profile.pubkey, - profile: profileEvent?.content, + profile: profileEvent?.profile, }; }); } @@ -509,7 +509,7 @@ export async function* Database_Update( if (newProfile == undefined) { throw new Error("impossible"); } - model.myProfile = newProfile.content; + model.myProfile = newProfile.profile; } } else if (e.kind == NostrKind.DIRECT_MESSAGE) { const pubkey = PublicKey.FromHex(e.pubkey); @@ -520,9 +520,9 @@ export async function* Database_Update( const author = getProfileEvent(database, pubkey); if (e.pubkey != ctx.publicKey.hex) { notify( - author?.content.name ? author.content.name : "", + author?.profile.name ? author.profile.name : "", "new message", - author?.content.picture ? author.content.picture : "", + author?.profile.picture ? author.profile.picture : "", () => { const k = PublicKey.FromHex(e.pubkey); if (k instanceof Error) { diff --git a/UI/contact-list.ts b/UI/contact-list.ts index e5d6e75..cceac34 100644 --- a/UI/contact-list.ts +++ b/UI/contact-list.ts @@ -1,5 +1,5 @@ import { Database_Contextual_View } from "../database.ts"; -import { ProfileEvent, ProfileFromNostrEvent, profilesStream } from "../features/profile.ts"; +import { ProfileFromNostrEvent, profilesStream } from "../features/profile.ts"; import { Channel } from "https://raw.githubusercontent.com/BlowaterNostr/csp/master/csp.ts"; import { ContactGroup } from "./contact-list.tsx"; @@ -13,12 +13,12 @@ import { ConnectionPool, newSubID, } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/relay.ts"; -import { CustomAppData, getTags } from "../nostr.ts"; +import { CustomAppData, getTags, Profile_Nostr_Event } from "../nostr.ts"; import { assertEquals } from "https://deno.land/std@0.176.0/testing/asserts.ts"; export interface UserInfo { pubkey: PublicKey; - profile: ProfileEvent | undefined; // todo: maybe change it to ProfileEvent + profile: Profile_Nostr_Event | undefined; // todo: maybe change it to ProfileEvent newestEventSendByMe: NostrEvent | undefined; newestEventReceivedByMe: NostrEvent | undefined; pinEvent: { @@ -109,7 +109,16 @@ export function getAllUsersInformation( case NostrKind.META_DATA: { const userInfo = res.get(event.pubkey); - const profileEvent = ProfileFromNostrEvent(event); + const profileEvent = ProfileFromNostrEvent({ + content: event.content, + created_at: event.created_at, + id: event.id, + kind: event.kind, + parsedTags: event.parsedTags, + pubkey: event.pubkey, + sig: event.sig, + tags: event.tags, + }); if (userInfo) { if (userInfo.profile) { if (profileEvent.created_at > userInfo.profile?.created_at) { diff --git a/UI/contact-list.tsx b/UI/contact-list.tsx index 047144e..6af69ac 100644 --- a/UI/contact-list.tsx +++ b/UI/contact-list.tsx @@ -285,13 +285,13 @@ function ConversationListItem(props: ListItemProps) {

- {props.userInfo.profile?.content.name || props.userInfo.pubkey.bech32()} + {props.userInfo.profile?.profile.name || props.userInfo.pubkey.bech32()}

{props.userInfo.newestEventReceivedByMe !== undefined ? ( diff --git a/UI/dm.ts b/UI/dm.ts index c46dbf4..52352b3 100644 --- a/UI/dm.ts +++ b/UI/dm.ts @@ -45,8 +45,8 @@ export function convertEventsToChatMessages( created_at: new Date(textEvents[i].created_at * 1000), author: { pubkey, - name: author?.profile?.content.name, - picture: author?.profile?.content.picture, + name: author?.profile?.profile.name, + picture: author?.profile?.profile.picture, }, lamport: getTags(textEvents[i]).lamport_timestamp, }); @@ -70,8 +70,8 @@ export function convertEventsToChatMessages( created_at: new Date(imageEvents[0].created_at * 1000), author: { pubkey: pubkey, - name: author?.profile?.content.name, - picture: author?.profile?.content.picture, + name: author?.profile?.profile.name, + picture: author?.profile?.profile.picture, }, lamport: getTags(imageEvents[0]).lamport_timestamp, }); diff --git a/UI/dm.tsx b/UI/dm.tsx index 248ed33..fb6c833 100644 --- a/UI/dm.tsx +++ b/UI/dm.tsx @@ -50,8 +50,8 @@ export function DirectMessageContainer(props: DirectMessageContainerProps) { const profile = getProfileEvent(props.db, currentConversation); currentEditorModel.target.receiver = { pubkey: currentConversation, - name: profile?.content.name, - picture: profile?.content.picture, + name: profile?.profile.name, + picture: profile?.profile.picture, }; } } diff --git a/UI/message-panel.tsx b/UI/message-panel.tsx index 20159fc..2375103 100644 --- a/UI/message-panel.tsx +++ b/UI/message-panel.tsx @@ -476,7 +476,7 @@ export function ParseMessageContent( } const profile = getProfileEvent(db, pubkey); if (profile) { - vnode.push(ProfileCard(profile.content, pubkey, eventEmitter)); + vnode.push(ProfileCard(profile.profile, pubkey, eventEmitter)); } else { profilesSyncer.add(pubkey.hex); } diff --git a/UI/search_model.ts b/UI/search_model.ts index 88ebcf7..5251233 100644 --- a/UI/search_model.ts +++ b/UI/search_model.ts @@ -1,5 +1,5 @@ import { PublicKey } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/key.ts"; -import { ProfileData, ProfileEvent } from "../features/profile.ts"; +import { ProfileData } from "../features/profile.ts"; export type SearchUpdate = Cancel | SearchPublicKey | SelectProfile | Start; export type Start = { diff --git a/features/profile.ts b/features/profile.ts index 4aad917..1fcb8ed 100644 --- a/features/profile.ts +++ b/features/profile.ts @@ -15,7 +15,7 @@ import { NostrKind, prepareNormalNostrEvent, } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nostr.ts"; -import { Tag } from "../nostr.ts"; +import { ParsedTag_Nostr_Event, PlainText_Nostr_Event, Profile_Nostr_Event, Tag } from "../nostr.ts"; // nip01 meta data // https://github.com/nostr-protocol/nips/blob/master/05.md @@ -71,10 +71,25 @@ export async function saveProfile( pool.sendEvent(event); } -export function getProfileEvent(db: Database_Contextual_View, pubkey: PublicKey): ProfileEvent | undefined { - const events = Array.from(db.filterEvents((e) => { - return e.kind === NostrKind.META_DATA && e.pubkey === pubkey.hex; - })); +export function getProfileEvent( + db: Database_Contextual_View, + pubkey: PublicKey, +): Profile_Nostr_Event | undefined { + const events: ParsedTag_Nostr_Event[] = []; + for (const e of db.events) { + if (e.kind === NostrKind.META_DATA && e.pubkey === pubkey.hex) { + events.push({ + content: e.content, + kind: e.kind, + created_at: e.created_at, + id: e.id, + parsedTags: e.parsedTags, + pubkey: e.pubkey, + sig: e.sig, + tags: e.tags, + }); + } + } if (events.length == 0) { return undefined; } @@ -83,10 +98,22 @@ export function getProfileEvent(db: Database_Contextual_View, pubkey: PublicKey) return ProfileFromNostrEvent(newest); } -export function getProfilesByName(db: Database_Contextual_View, name: string): ProfileEvent[] { - const events = Array.from(db.filterEvents((e) => { - return e.kind === NostrKind.META_DATA; - })); +export function getProfilesByName(db: Database_Contextual_View, name: string): Profile_Nostr_Event[] { + const events: ParsedTag_Nostr_Event[] = []; + for (const e of db.events) { + if (e.kind === NostrKind.META_DATA) { + events.push({ + content: e.content, + kind: e.kind, + created_at: e.created_at, + id: e.id, + parsedTags: e.parsedTags, + pubkey: e.pubkey, + sig: e.sig, + tags: e.tags, + }); + } + } if (events.length == 0) { return []; } @@ -96,7 +123,7 @@ export function getProfilesByName(db: Database_Contextual_View, name: string): P for (const events of profilesPerUser.values()) { events.sort((e1, e2) => e2.created_at - e1.created_at); const p = ProfileFromNostrEvent(events[0]); - if (p.content.name && p.content.name?.toLocaleLowerCase().indexOf(name.toLowerCase()) != -1) { + if (p.profile.name && p.profile.name?.toLocaleLowerCase().indexOf(name.toLowerCase()) != -1) { result.push(p); } } @@ -106,8 +133,8 @@ export function getProfilesByName(db: Database_Contextual_View, name: string): P export function getProfiles( db: Database_Contextual_View, pubkeys: Set, -): Map { - const contacts: Map = new Map(); +): Map { + const contacts: Map = new Map(); for (const key of pubkeys) { const event = getProfileEvent(db, PublicKey.FromHex(key) as PublicKey); contacts.set(key, event); @@ -125,17 +152,9 @@ export interface ProfileData { [key: string]: string | undefined; } -export interface ProfileEvent { - kind: NostrKind; - id: string; - sig: string; - created_at: number; - pubkey: string; - tags: Tag[]; - content: ProfileData; -} - -export function ProfileFromNostrEvent(event: NostrEvent): ProfileEvent { +export function ProfileFromNostrEvent( + event: ParsedTag_Nostr_Event, +): Profile_Nostr_Event { let profileData: ProfileData = {}; try { profileData = JSON.parse(event.content); @@ -149,6 +168,8 @@ export function ProfileFromNostrEvent(event: NostrEvent): ProfileEvent { created_at: event.created_at, pubkey: event.pubkey, tags: event.tags, - content: profileData, + content: event.content, + parsedTags: event.parsedTags, + profile: profileData, }; } diff --git a/features/social.ts b/features/social.ts index cabd533..e767380 100644 --- a/features/social.ts +++ b/features/social.ts @@ -30,8 +30,8 @@ export function getSocialPosts( event: event, author: { pubkey: pubkey, - name: userInfo?.profile?.content.name, - picture: userInfo?.profile?.content.picture, + name: userInfo?.profile?.profile.name, + picture: userInfo?.profile?.profile.picture, }, content: event.content, created_at: new Date(event.created_at * 1000), diff --git a/nostr.ts b/nostr.ts index d536393..7889306 100644 --- a/nostr.ts +++ b/nostr.ts @@ -10,6 +10,7 @@ import { prepareNormalNostrEvent, TagPubKey, } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nostr.ts"; +import { ProfileData } from "./features/profile.ts"; type TotolChunks = string; type ChunkIndex = string; // 0-indexed @@ -283,8 +284,11 @@ export type Decrypted_Nostr_Event = ParsedTag_Nostr_Event; export type PlainText_Nostr_Event = ParsedTag_Nostr_Event< - Exclude + Exclude // todo: exclude DM as well >; +export type Profile_Nostr_Event = ParsedTag_Nostr_Event & { + profile: ProfileData; +}; export type CustomAppData = PinContact | UnpinContact | UserLogin; export type PinContact = {