Merge branch 'main' into new-ui
This commit is contained in:
@ -14,7 +14,7 @@ declare global {
|
||||
nostr: {
|
||||
getPublicKey: () => Promise<HexKey>,
|
||||
signEvent: (event: RawEvent) => Promise<RawEvent>,
|
||||
getRelays: () => Promise<[[string, { read: boolean, write: boolean }]]>,
|
||||
getRelays: () => Promise<Record<string, { read: boolean, write: boolean }>>,
|
||||
nip04: {
|
||||
encrypt: (pubkey: HexKey, content: string) => Promise<string>,
|
||||
decrypt: (pubkey: HexKey, content: string) => Promise<string>
|
||||
@ -72,12 +72,22 @@ export default function useEventPublisher() {
|
||||
return match;
|
||||
}
|
||||
const content = msg.replace(/@npub[a-z0-9]+/g, replaceNpub)
|
||||
.replace(/note[a-z0-9]+/g, replaceNoteId)
|
||||
.replace(HashtagRegex, replaceHashtag);
|
||||
.replace(/note[a-z0-9]+/g, replaceNoteId)
|
||||
.replace(HashtagRegex, replaceHashtag);
|
||||
ev.Content = content;
|
||||
}
|
||||
|
||||
return {
|
||||
nip42Auth: async (challenge: string, relay:string) => {
|
||||
if(pubKey) {
|
||||
const ev = NEvent.ForPubKey(pubKey);
|
||||
ev.Kind = EventKind.Auth;
|
||||
ev.Content = "";
|
||||
ev.Tags.push(new Tag(["relay", relay], 0));
|
||||
ev.Tags.push(new Tag(["challenge", challenge], 1));
|
||||
return await signEvent(ev);
|
||||
}
|
||||
},
|
||||
broadcast: (ev: NEvent | undefined) => {
|
||||
if (ev) {
|
||||
console.debug("Sending event: ", ev);
|
||||
@ -90,8 +100,8 @@ export default function useEventPublisher() {
|
||||
* When they open the site again we wont see that updated relay list and so it will appear to reset back to the previous state
|
||||
*/
|
||||
broadcastForBootstrap: (ev: NEvent | undefined) => {
|
||||
if(ev) {
|
||||
for(let [k, _] of DefaultRelays) {
|
||||
if (ev) {
|
||||
for (let [k, _] of DefaultRelays) {
|
||||
System.WriteOnceToRelay(k, ev);
|
||||
}
|
||||
}
|
||||
@ -205,6 +215,9 @@ export default function useEventPublisher() {
|
||||
temp.add(pkAdd);
|
||||
}
|
||||
for (let pk of temp) {
|
||||
if (pk.length !== 64) {
|
||||
continue;
|
||||
}
|
||||
ev.Tags.push(new Tag(["p", pk], ev.Tags.length));
|
||||
}
|
||||
|
||||
@ -217,7 +230,7 @@ export default function useEventPublisher() {
|
||||
ev.Kind = EventKind.ContactList;
|
||||
ev.Content = JSON.stringify(relays);
|
||||
for (let pk of follows) {
|
||||
if (pk === pkRemove) {
|
||||
if (pk === pkRemove || pk.length !== 64) {
|
||||
continue;
|
||||
}
|
||||
ev.Tags.push(new Tag(["p", pk], ev.Tags.length));
|
||||
|
@ -7,12 +7,14 @@ import EventKind from "Nostr/EventKind";
|
||||
import Event from "Nostr/Event";
|
||||
import { Subscriptions } from "Nostr/Subscriptions";
|
||||
import { addDirectMessage, setFollows, setRelays, setMuted, setBlocked, sendNotification } from "State/Login";
|
||||
import type { RootState } from "State/Store";
|
||||
import { db } from "Db";
|
||||
import { barierNip07 } from "Feed/EventPublisher";
|
||||
import { RootState } from "State/Store";
|
||||
import { mapEventToProfile, MetadataCache } from "State/Users";
|
||||
import { getDb } from "State/Users/Db";
|
||||
import useSubscription from "Feed/Subscription";
|
||||
import { getDisplayName } from "Element/ProfileImage";
|
||||
import { barierNip07 } from "Feed/EventPublisher";
|
||||
import { getMutedKeys, getNewest } from "Feed/MuteList";
|
||||
import { mapEventToProfile, MetadataCache } from "Db/User";
|
||||
import { MentionRegex } from "Const";
|
||||
import useModeration from "Hooks/useModeration";
|
||||
|
||||
/**
|
||||
@ -105,9 +107,10 @@ export default function useLoginFeed() {
|
||||
return acc;
|
||||
}, { created: 0, profile: null as MetadataCache | null });
|
||||
if (maxProfile.profile) {
|
||||
let existing = await db.users.get(maxProfile.profile.pubkey);
|
||||
const db = getDb()
|
||||
let existing = await db.find(maxProfile.profile.pubkey);
|
||||
if ((existing?.created ?? 0) < maxProfile.created) {
|
||||
await db.users.put(maxProfile.profile);
|
||||
await db.put(maxProfile.profile);
|
||||
}
|
||||
}
|
||||
})().catch(console.warn);
|
||||
@ -152,6 +155,7 @@ export default function useLoginFeed() {
|
||||
}, [dispatch, dmsFeed.store]);
|
||||
}
|
||||
|
||||
|
||||
async function decryptBlocked(raw: TaggedRawEvent, pubKey: HexKey, privKey?: HexKey) {
|
||||
const ev = new Event(raw)
|
||||
if (pubKey && privKey) {
|
||||
|
@ -1,27 +1,13 @@
|
||||
import { useLiveQuery } from "dexie-react-hooks";
|
||||
import { useEffect } from "react";
|
||||
import { db } from "Db";
|
||||
import { MetadataCache } from "Db/User";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { RootState } from "State/Store";
|
||||
import { MetadataCache } from "State/Users";
|
||||
import { useKey, useKeys } from "State/Users/Hooks";
|
||||
import { HexKey } from "Nostr";
|
||||
import { System } from "Nostr/System";
|
||||
|
||||
export default function useProfile(pubKey?: HexKey | Array<HexKey> | undefined): Map<HexKey, MetadataCache> | undefined {
|
||||
const user = useLiveQuery(async () => {
|
||||
let userList = new Map<HexKey, MetadataCache>();
|
||||
if (pubKey) {
|
||||
if (Array.isArray(pubKey)) {
|
||||
let ret = await db.users.bulkGet(pubKey);
|
||||
let filtered = ret.filter(a => a !== undefined).map(a => a!);
|
||||
return new Map(filtered.map(a => [a.pubkey, a]))
|
||||
} else {
|
||||
let ret = await db.users.get(pubKey);
|
||||
if (ret) {
|
||||
userList.set(ret.pubkey, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
return userList;
|
||||
}, [pubKey]);
|
||||
export function useUserProfile(pubKey: HexKey): MetadataCache | undefined {
|
||||
const users = useKey(pubKey);
|
||||
|
||||
useEffect(() => {
|
||||
if (pubKey) {
|
||||
@ -30,5 +16,19 @@ export default function useProfile(pubKey?: HexKey | Array<HexKey> | undefined):
|
||||
}
|
||||
}, [pubKey]);
|
||||
|
||||
return user;
|
||||
}
|
||||
return users;
|
||||
}
|
||||
|
||||
|
||||
export function useUserProfiles(pubKeys: Array<HexKey>): Map<HexKey, MetadataCache> | undefined {
|
||||
const users = useKeys(pubKeys);
|
||||
|
||||
useEffect(() => {
|
||||
if (pubKeys) {
|
||||
System.TrackMetadata(pubKeys);
|
||||
return () => System.UntrackMetadata(pubKeys);
|
||||
}
|
||||
}, [pubKeys]);
|
||||
|
||||
return users;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ export interface TimelineFeedOptions {
|
||||
}
|
||||
|
||||
export interface TimelineSubject {
|
||||
type: "pubkey" | "hashtag" | "global" | "ptag",
|
||||
type: "pubkey" | "hashtag" | "global" | "ptag" | "keyword",
|
||||
items: string[]
|
||||
}
|
||||
|
||||
@ -47,6 +47,11 @@ export default function useTimelineFeed(subject: TimelineSubject, options: Timel
|
||||
sub.PTags = new Set(subject.items);
|
||||
break;
|
||||
}
|
||||
case "keyword": {
|
||||
sub.Kinds.add(EventKind.SetMetadata);
|
||||
sub.Search = subject.items[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sub;
|
||||
}, [subject.type, subject.items]);
|
||||
@ -72,6 +77,7 @@ export default function useTimelineFeed(subject: TimelineSubject, options: Timel
|
||||
latestSub.Authors = sub.Authors;
|
||||
latestSub.HashTags = sub.HashTags;
|
||||
latestSub.Kinds = sub.Kinds;
|
||||
latestSub.Search = sub.Search;
|
||||
latestSub.Limit = 1;
|
||||
latestSub.Since = Math.floor(new Date().getTime() / 1000);
|
||||
sub.AddSubscription(latestSub);
|
||||
@ -123,7 +129,7 @@ export default function useTimelineFeed(subject: TimelineSubject, options: Timel
|
||||
if (main.store.notes.length > 0) {
|
||||
setTrackingEvent(s => {
|
||||
let ids = main.store.notes.map(a => a.id);
|
||||
if(ids.some(a => !s.includes(a))) {
|
||||
if (ids.some(a => !s.includes(a))) {
|
||||
return Array.from(new Set([...s, ...ids]));
|
||||
}
|
||||
return s;
|
||||
@ -165,4 +171,4 @@ export default function useTimelineFeed(subject: TimelineSubject, options: Timel
|
||||
latest.clear();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import * as secp from "@noble/secp256k1";
|
||||
import { VoidCatHost } from "Const";
|
||||
|
||||
/**
|
||||
* Upload file to void.cat
|
||||
@ -8,7 +9,7 @@ export default async function VoidUpload(file: File | Blob, filename: string) {
|
||||
const buf = await file.arrayBuffer();
|
||||
const digest = await crypto.subtle.digest("SHA-256", buf);
|
||||
|
||||
let req = await fetch(`https://void.cat/upload`, {
|
||||
let req = await fetch(`${VoidCatHost}/upload`, {
|
||||
mode: "cors",
|
||||
method: "POST",
|
||||
body: buf,
|
||||
@ -17,7 +18,8 @@ export default async function VoidUpload(file: File | Blob, filename: string) {
|
||||
"V-Content-Type": file.type,
|
||||
"V-Filename": filename,
|
||||
"V-Full-Digest": secp.utils.bytesToHex(new Uint8Array(digest)),
|
||||
"V-Description": "Upload from https://snort.social"
|
||||
"V-Description": "Upload from https://snort.social",
|
||||
"V-Strip-Metadata": "true"
|
||||
}
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user