feat: make sig checks optional
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
87bb9dafeb
commit
93e8e0bbae
@ -19,7 +19,7 @@ export interface DMProps {
|
|||||||
|
|
||||||
export default function DM(props: DMProps) {
|
export default function DM(props: DMProps) {
|
||||||
const { publicKey } = useLogin(s => ({ publicKey: s.publicKey }));
|
const { publicKey } = useLogin(s => ({ publicKey: s.publicKey }));
|
||||||
const publisher = useEventPublisher();
|
const { publisher } = useEventPublisher();
|
||||||
const msg = props.data;
|
const msg = props.data;
|
||||||
const [content, setContent] = useState<string>();
|
const [content, setContent] = useState<string>();
|
||||||
const { ref, inView } = useInView({ triggerOnce: true });
|
const { ref, inView } = useInView({ triggerOnce: true });
|
||||||
|
@ -6,7 +6,6 @@ import { useState } from "react";
|
|||||||
import useFileUpload from "Upload";
|
import useFileUpload from "Upload";
|
||||||
import { openFile } from "SnortUtils";
|
import { openFile } from "SnortUtils";
|
||||||
import Textarea from "../Textarea";
|
import Textarea from "../Textarea";
|
||||||
import { System } from "index";
|
|
||||||
import { Chat } from "chat";
|
import { Chat } from "chat";
|
||||||
|
|
||||||
export default function WriteMessage({ chat }: { chat: Chat }) {
|
export default function WriteMessage({ chat }: { chat: Chat }) {
|
||||||
@ -15,7 +14,7 @@ export default function WriteMessage({ chat }: { chat: Chat }) {
|
|||||||
const [uploading, setUploading] = useState(false);
|
const [uploading, setUploading] = useState(false);
|
||||||
const [otherEvents, setOtherEvents] = useState<Array<NostrEvent>>([]);
|
const [otherEvents, setOtherEvents] = useState<Array<NostrEvent>>([]);
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
const uploader = useFileUpload();
|
const uploader = useFileUpload();
|
||||||
|
|
||||||
async function attachFile() {
|
async function attachFile() {
|
||||||
@ -59,7 +58,7 @@ export default function WriteMessage({ chat }: { chat: Chat }) {
|
|||||||
if (msg && publisher && chat) {
|
if (msg && publisher && chat) {
|
||||||
setSending(true);
|
setSending(true);
|
||||||
const ev = await chat.createMessage(msg, publisher);
|
const ev = await chat.createMessage(msg, publisher);
|
||||||
await chat.sendMessage(ev, System);
|
await chat.sendMessage(ev, system);
|
||||||
setMsg("");
|
setMsg("");
|
||||||
setSending(false);
|
setSending(false);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ import { WalletInvoiceState } from "Wallet";
|
|||||||
export default function PubkeyList({ ev, className }: { ev: NostrEvent; className?: string }) {
|
export default function PubkeyList({ ev, className }: { ev: NostrEvent; className?: string }) {
|
||||||
const wallet = useWallet();
|
const wallet = useWallet();
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
const publisher = useEventPublisher();
|
const { publisher } = useEventPublisher();
|
||||||
const ids = dedupe(ev.tags.filter(a => a[0] === "p").map(a => a[1]));
|
const ids = dedupe(ev.tags.filter(a => a[0] === "p").map(a => a[1]));
|
||||||
|
|
||||||
async function zapAll() {
|
async function zapAll() {
|
||||||
|
@ -6,7 +6,6 @@ import { NostrEvent, OkResponse } from "@snort/system";
|
|||||||
import AsyncButton from "Element/AsyncButton";
|
import AsyncButton from "Element/AsyncButton";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "Icons/Icon";
|
||||||
import { getRelayName, sanitizeRelayUrl } from "SnortUtils";
|
import { getRelayName, sanitizeRelayUrl } from "SnortUtils";
|
||||||
import { System } from "index";
|
|
||||||
import { removeRelay } from "Login";
|
import { removeRelay } from "Login";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "Hooks/useLogin";
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "Hooks/useEventPublisher";
|
||||||
@ -23,7 +22,7 @@ export function NoteBroadcaster({
|
|||||||
const [results, setResults] = useState<Array<OkResponse>>([]);
|
const [results, setResults] = useState<Array<OkResponse>>([]);
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
|
|
||||||
async function sendEventToRelays(ev: NostrEvent) {
|
async function sendEventToRelays(ev: NostrEvent) {
|
||||||
if (customRelays) {
|
if (customRelays) {
|
||||||
@ -31,7 +30,7 @@ export function NoteBroadcaster({
|
|||||||
await Promise.all(
|
await Promise.all(
|
||||||
customRelays.map(async r => {
|
customRelays.map(async r => {
|
||||||
try {
|
try {
|
||||||
return await System.WriteOnceToRelay(r, ev);
|
return await system.WriteOnceToRelay(r, ev);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
@ -39,7 +38,7 @@ export function NoteBroadcaster({
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return await System.BroadcastEvent(ev, r => setResults(x => [...x, r]));
|
return await system.BroadcastEvent(ev, r => setResults(x => [...x, r]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +57,7 @@ export function NoteBroadcaster({
|
|||||||
if (publisher) {
|
if (publisher) {
|
||||||
removeRelay(login, unwrap(sanitizeRelayUrl(r.relay)));
|
removeRelay(login, unwrap(sanitizeRelayUrl(r.relay)));
|
||||||
const ev = await publisher.contactList(login.follows.item, login.relays.item);
|
const ev = await publisher.contactList(login.follows.item, login.relays.item);
|
||||||
await System.BroadcastEvent(ev);
|
await system.BroadcastEvent(ev);
|
||||||
setResults(s => s.filter(a => a.relay !== r.relay));
|
setResults(s => s.filter(a => a.relay !== r.relay));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,7 +65,7 @@ export function NoteBroadcaster({
|
|||||||
async function retryPublish(r: OkResponse) {
|
async function retryPublish(r: OkResponse) {
|
||||||
const ev = evs.find(a => a.id === r.id);
|
const ev = evs.find(a => a.id === r.id);
|
||||||
if (ev) {
|
if (ev) {
|
||||||
const rsp = await System.WriteOnceToRelay(unwrap(sanitizeRelayUrl(r.relay)), ev);
|
const rsp = await system.WriteOnceToRelay(unwrap(sanitizeRelayUrl(r.relay)), ev);
|
||||||
setResults(s =>
|
setResults(s =>
|
||||||
s.map(x => {
|
s.map(x => {
|
||||||
if (x.relay === r.relay && x.id === r.id) {
|
if (x.relay === r.relay && x.id === r.id) {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
import { useState } from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import { HexKey, Lists, NostrLink, TaggedNostrEvent } from "@snort/system";
|
import { HexKey, Lists, NostrLink, TaggedNostrEvent } from "@snort/system";
|
||||||
import { Menu, MenuItem } from "@szhsin/react-menu";
|
import { Menu, MenuItem } from "@szhsin/react-menu";
|
||||||
|
|
||||||
import { TranslateHost } from "Const";
|
import { TranslateHost } from "Const";
|
||||||
import { System } from "index";
|
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "Icons/Icon";
|
||||||
import { setPinned, setBookmarked } from "Login";
|
import { setPinned, setBookmarked } from "Login";
|
||||||
import messages from "Element/messages";
|
import messages from "Element/messages";
|
||||||
@ -11,7 +11,6 @@ import useLogin from "Hooks/useLogin";
|
|||||||
import useModeration from "Hooks/useModeration";
|
import useModeration from "Hooks/useModeration";
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "Hooks/useEventPublisher";
|
||||||
import { ReBroadcaster } from "../ReBroadcaster";
|
import { ReBroadcaster } from "../ReBroadcaster";
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
export interface NoteTranslation {
|
export interface NoteTranslation {
|
||||||
text: string;
|
text: string;
|
||||||
@ -30,7 +29,7 @@ export function NoteContextMenu({ ev, ...props }: NosteContextMenuProps) {
|
|||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
const { mute, block } = useModeration();
|
const { mute, block } = useModeration();
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
const [showBroadcast, setShowBroadcast] = useState(false);
|
const [showBroadcast, setShowBroadcast] = useState(false);
|
||||||
const lang = window.navigator.language;
|
const lang = window.navigator.language;
|
||||||
const langNames = new Intl.DisplayNames([...window.navigator.languages], {
|
const langNames = new Intl.DisplayNames([...window.navigator.languages], {
|
||||||
@ -41,7 +40,7 @@ export function NoteContextMenu({ ev, ...props }: NosteContextMenuProps) {
|
|||||||
async function deleteEvent() {
|
async function deleteEvent() {
|
||||||
if (window.confirm(formatMessage(messages.ConfirmDeletion, { id: ev.id.substring(0, 8) })) && publisher) {
|
if (window.confirm(formatMessage(messages.ConfirmDeletion, { id: ev.id.substring(0, 8) })) && publisher) {
|
||||||
const evDelete = await publisher.delete(ev.id);
|
const evDelete = await publisher.delete(ev.id);
|
||||||
System.BroadcastEvent(evDelete);
|
system.BroadcastEvent(evDelete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +89,7 @@ export function NoteContextMenu({ ev, ...props }: NosteContextMenuProps) {
|
|||||||
if (publisher) {
|
if (publisher) {
|
||||||
const es = [...login.pinned.item, id];
|
const es = [...login.pinned.item, id];
|
||||||
const ev = await publisher.noteList(es, Lists.Pinned);
|
const ev = await publisher.noteList(es, Lists.Pinned);
|
||||||
System.BroadcastEvent(ev);
|
system.BroadcastEvent(ev);
|
||||||
setPinned(login, es, ev.created_at * 1000);
|
setPinned(login, es, ev.created_at * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,7 +98,7 @@ export function NoteContextMenu({ ev, ...props }: NosteContextMenuProps) {
|
|||||||
if (publisher) {
|
if (publisher) {
|
||||||
const es = [...login.bookmarked.item, id];
|
const es = [...login.bookmarked.item, id];
|
||||||
const ev = await publisher.noteList(es, Lists.Bookmarked);
|
const ev = await publisher.noteList(es, Lists.Bookmarked);
|
||||||
System.BroadcastEvent(ev);
|
system.BroadcastEvent(ev);
|
||||||
setBookmarked(login, es, ev.created_at * 1000);
|
setBookmarked(login, es, ev.created_at * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,8 @@ export function NoteCreator() {
|
|||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const uploader = useFileUpload();
|
const uploader = useFileUpload();
|
||||||
const login = useLogin(s => ({ relays: s.relays, publicKey: s.publicKey, pow: s.preferences.pow }));
|
const login = useLogin(s => ({ relays: s.relays, publicKey: s.publicKey, pow: s.preferences.pow }));
|
||||||
const publisher = login.pow ? useEventPublisher()?.pow(login.pow, GetPowWorker()) : useEventPublisher();
|
const { publisher: pub } = useEventPublisher();
|
||||||
|
const publisher = login.pow ? pub?.pow(login.pow, GetPowWorker()) : pub;
|
||||||
const note = useNoteCreator();
|
const note = useNoteCreator();
|
||||||
const relays = login.relays;
|
const relays = login.relays;
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React, { HTMLProps, useContext, useEffect, useState } from "react";
|
import React, { HTMLProps, useEffect, useState } from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import { useLongPress } from "use-long-press";
|
import { useLongPress } from "use-long-press";
|
||||||
import { TaggedNostrEvent, ParsedZap, countLeadingZeros, NostrLink } from "@snort/system";
|
import { TaggedNostrEvent, ParsedZap, countLeadingZeros, NostrLink } from "@snort/system";
|
||||||
import { SnortContext, useUserProfile } from "@snort/system-react";
|
import { useUserProfile } from "@snort/system-react";
|
||||||
import { Menu, MenuItem } from "@szhsin/react-menu";
|
import { Menu, MenuItem } from "@szhsin/react-menu";
|
||||||
|
|
||||||
import { formatShort } from "Number";
|
import { formatShort } from "Number";
|
||||||
@ -17,7 +17,6 @@ import { useWallet } from "Wallet";
|
|||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "Hooks/useLogin";
|
||||||
import { useInteractionCache } from "Hooks/useInteractionCache";
|
import { useInteractionCache } from "Hooks/useInteractionCache";
|
||||||
import { ZapPoolController } from "ZapPoolController";
|
import { ZapPoolController } from "ZapPoolController";
|
||||||
import { System } from "index";
|
|
||||||
import { Zapper, ZapTarget } from "Zapper";
|
import { Zapper, ZapTarget } from "Zapper";
|
||||||
import { getDisplayName } from "Element/User/DisplayName";
|
import { getDisplayName } from "Element/User/DisplayName";
|
||||||
import { useNoteCreator } from "State/NoteCreator";
|
import { useNoteCreator } from "State/NoteCreator";
|
||||||
@ -48,7 +47,6 @@ export interface NoteFooterProps {
|
|||||||
|
|
||||||
export default function NoteFooter(props: NoteFooterProps) {
|
export default function NoteFooter(props: NoteFooterProps) {
|
||||||
const { ev, positive, reposts, zaps } = props;
|
const { ev, positive, reposts, zaps } = props;
|
||||||
const system = useContext(SnortContext);
|
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const {
|
const {
|
||||||
publicKey,
|
publicKey,
|
||||||
@ -57,7 +55,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
|||||||
} = useLogin(s => ({ preferences: s.preferences, publicKey: s.publicKey, readonly: s.readonly }));
|
} = useLogin(s => ({ preferences: s.preferences, publicKey: s.publicKey, readonly: s.readonly }));
|
||||||
const author = useUserProfile(ev.pubkey);
|
const author = useUserProfile(ev.pubkey);
|
||||||
const interactionCache = useInteractionCache(publicKey, ev.id);
|
const interactionCache = useInteractionCache(publicKey, ev.id);
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
const note = useNoteCreator(n => ({ show: n.show, replyTo: n.replyTo, update: n.update, quote: n.quote }));
|
const note = useNoteCreator(n => ({ show: n.show, replyTo: n.replyTo, update: n.update, quote: n.quote }));
|
||||||
const willRenderNoteCreator = note.show && (note.replyTo?.id === ev.id || note.quote);
|
const willRenderNoteCreator = note.show && (note.replyTo?.id === ev.id || note.quote);
|
||||||
const [tip, setTip] = useState(false);
|
const [tip, setTip] = useState(false);
|
||||||
@ -93,7 +91,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
|||||||
async function react(content: string) {
|
async function react(content: string) {
|
||||||
if (!hasReacted(content) && publisher) {
|
if (!hasReacted(content) && publisher) {
|
||||||
const evLike = await publisher.react(ev, content);
|
const evLike = await publisher.react(ev, content);
|
||||||
System.BroadcastEvent(evLike);
|
system.BroadcastEvent(evLike);
|
||||||
await interactionCache.react();
|
await interactionCache.react();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,7 +100,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
|||||||
if (!hasReposted() && publisher) {
|
if (!hasReposted() && publisher) {
|
||||||
if (!prefs.confirmReposts || window.confirm(formatMessage(messages.ConfirmRepost, { id: ev.id }))) {
|
if (!prefs.confirmReposts || window.confirm(formatMessage(messages.ConfirmRepost, { id: ev.id }))) {
|
||||||
const evRepost = await publisher.repost(ev);
|
const evRepost = await publisher.repost(ev);
|
||||||
System.BroadcastEvent(evRepost);
|
system.BroadcastEvent(evRepost);
|
||||||
await interactionCache.repost();
|
await interactionCache.repost();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import useEventPublisher from "Hooks/useEventPublisher";
|
|||||||
import { NoteContextMenu, NoteTranslation } from "./NoteContextMenu";
|
import { NoteContextMenu, NoteTranslation } from "./NoteContextMenu";
|
||||||
import { UserCache } from "../../Cache";
|
import { UserCache } from "../../Cache";
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
import { System } from "../../index";
|
|
||||||
import { setBookmarked, setPinned } from "../../Login";
|
import { setBookmarked, setPinned } from "../../Login";
|
||||||
import Text from "../Text";
|
import Text from "../Text";
|
||||||
import Reveal from "./Reveal";
|
import Reveal from "./Reveal";
|
||||||
@ -37,7 +36,7 @@ export function NoteInner(props: NoteProps) {
|
|||||||
const { reactions, reposts, deletions, zaps } = useEventReactions(ev, related);
|
const { reactions, reposts, deletions, zaps } = useEventReactions(ev, related);
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
const { pinned, bookmarked } = login;
|
const { pinned, bookmarked } = login;
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
const [translated, setTranslated] = useState<NoteTranslation>();
|
const [translated, setTranslated] = useState<NoteTranslation>();
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
@ -58,7 +57,7 @@ export function NoteInner(props: NoteProps) {
|
|||||||
if (window.confirm(formatMessage(messages.ConfirmUnpin))) {
|
if (window.confirm(formatMessage(messages.ConfirmUnpin))) {
|
||||||
const es = pinned.item.filter(e => e !== id);
|
const es = pinned.item.filter(e => e !== id);
|
||||||
const ev = await publisher.noteList(es, Lists.Pinned);
|
const ev = await publisher.noteList(es, Lists.Pinned);
|
||||||
System.BroadcastEvent(ev);
|
system.BroadcastEvent(ev);
|
||||||
setPinned(login, es, ev.created_at * 1000);
|
setPinned(login, es, ev.created_at * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +68,7 @@ export function NoteInner(props: NoteProps) {
|
|||||||
if (window.confirm(formatMessage(messages.ConfirmUnbookmark))) {
|
if (window.confirm(formatMessage(messages.ConfirmUnbookmark))) {
|
||||||
const es = bookmarked.item.filter(e => e !== id);
|
const es = bookmarked.item.filter(e => e !== id);
|
||||||
const ev = await publisher.noteList(es, Lists.Bookmarked);
|
const ev = await publisher.noteList(es, Lists.Bookmarked);
|
||||||
System.BroadcastEvent(ev);
|
system.BroadcastEvent(ev);
|
||||||
setBookmarked(login, es, ev.created_at * 1000);
|
setBookmarked(login, es, ev.created_at * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ type PollTally = "zaps" | "pubkeys";
|
|||||||
|
|
||||||
export default function Poll(props: PollProps) {
|
export default function Poll(props: PollProps) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const publisher = useEventPublisher();
|
const { publisher } = useEventPublisher();
|
||||||
const { wallet } = useWallet();
|
const { wallet } = useWallet();
|
||||||
const { preferences: prefs, publicKey: myPubKey, relays } = useLogin();
|
const { preferences: prefs, publicKey: myPubKey, relays } = useLogin();
|
||||||
const pollerProfile = useUserProfile(props.ev.pubkey);
|
const pollerProfile = useUserProfile(props.ev.pubkey);
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
|
import { mapEventToProfile } from "@snort/system";
|
||||||
|
import { useUserProfile } from "@snort/system-react";
|
||||||
|
|
||||||
import AccountName from "./AccountName";
|
import AccountName from "./AccountName";
|
||||||
import useLogin from "../../Hooks/useLogin";
|
import useLogin from "../../Hooks/useLogin";
|
||||||
import { useUserProfile } from "@snort/system-react";
|
|
||||||
import { System } from "../../index";
|
|
||||||
import { UserCache } from "../../Cache";
|
import { UserCache } from "../../Cache";
|
||||||
import useEventPublisher from "../../Hooks/useEventPublisher";
|
import useEventPublisher from "../../Hooks/useEventPublisher";
|
||||||
import { mapEventToProfile } from "@snort/system";
|
|
||||||
import FormattedMessage from "Element/FormattedMessage";
|
import FormattedMessage from "Element/FormattedMessage";
|
||||||
|
|
||||||
export default function ActiveAccount({ name = "", setAsPrimary = () => {} }) {
|
export default function ActiveAccount({ name = "", setAsPrimary = () => {} }) {
|
||||||
@ -13,7 +13,7 @@ export default function ActiveAccount({ name = "", setAsPrimary = () => {} }) {
|
|||||||
readonly: s.readonly,
|
readonly: s.readonly,
|
||||||
}));
|
}));
|
||||||
const profile = useUserProfile(publicKey);
|
const profile = useUserProfile(publicKey);
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
|
|
||||||
async function saveProfile(nip05: string) {
|
async function saveProfile(nip05: string) {
|
||||||
if (readonly) {
|
if (readonly) {
|
||||||
@ -35,7 +35,7 @@ export default function ActiveAccount({ name = "", setAsPrimary = () => {} }) {
|
|||||||
|
|
||||||
if (publisher) {
|
if (publisher) {
|
||||||
const ev = await publisher.metadata(userCopy);
|
const ev = await publisher.metadata(userCopy);
|
||||||
System.BroadcastEvent(ev);
|
system.BroadcastEvent(ev);
|
||||||
|
|
||||||
const newProfile = mapEventToProfile(ev);
|
const newProfile = mapEventToProfile(ev);
|
||||||
if (newProfile) {
|
if (newProfile) {
|
||||||
|
@ -25,7 +25,6 @@ import SnortServiceProvider from "Nip05/SnortServiceProvider";
|
|||||||
import { UserCache } from "Cache";
|
import { UserCache } from "Cache";
|
||||||
|
|
||||||
import messages from "./messages";
|
import messages from "./messages";
|
||||||
import { System } from "index";
|
|
||||||
|
|
||||||
type Nip05ServiceProps = {
|
type Nip05ServiceProps = {
|
||||||
name: string;
|
name: string;
|
||||||
@ -45,7 +44,7 @@ export default function Nip5Service(props: Nip05ServiceProps) {
|
|||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const { publicKey } = useLogin(s => ({ publicKey: s.publicKey }));
|
const { publicKey } = useLogin(s => ({ publicKey: s.publicKey }));
|
||||||
const user = useUserProfile(publicKey);
|
const user = useUserProfile(publicKey);
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
const svc = useMemo(() => new ServiceProvider(props.service), [props.service]);
|
const svc = useMemo(() => new ServiceProvider(props.service), [props.service]);
|
||||||
const [serviceConfig, setServiceConfig] = useState<ServiceConfig>();
|
const [serviceConfig, setServiceConfig] = useState<ServiceConfig>();
|
||||||
const [error, setError] = useState<ServiceError>();
|
const [error, setError] = useState<ServiceError>();
|
||||||
@ -216,7 +215,7 @@ export default function Nip5Service(props: Nip05ServiceProps) {
|
|||||||
nip05,
|
nip05,
|
||||||
} as UserMetadata;
|
} as UserMetadata;
|
||||||
const ev = await publisher.metadata(newProfile);
|
const ev = await publisher.metadata(newProfile);
|
||||||
System.BroadcastEvent(ev);
|
system.BroadcastEvent(ev);
|
||||||
if (props.onSuccess) {
|
if (props.onSuccess) {
|
||||||
props.onSuccess(nip05);
|
props.onSuccess(nip05);
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ export function PinPrompt({
|
|||||||
|
|
||||||
export function LoginUnlock() {
|
export function LoginUnlock() {
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
const publisher = useEventPublisher();
|
const { publisher } = useEventPublisher();
|
||||||
|
|
||||||
async function encryptMigration(pin: string) {
|
async function encryptMigration(pin: string) {
|
||||||
const k = unwrap(login.privateKey);
|
const k = unwrap(login.privateKey);
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import "./Relay.css";
|
import "./Relay.css";
|
||||||
import { useMemo } from "react";
|
import { useContext, useMemo } from "react";
|
||||||
import FormattedMessage from "Element/FormattedMessage";
|
import FormattedMessage from "Element/FormattedMessage";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { RelaySettings } from "@snort/system";
|
import { RelaySettings } from "@snort/system";
|
||||||
import { unixNowMs } from "@snort/shared";
|
import { unixNowMs } from "@snort/shared";
|
||||||
|
|
||||||
import useRelayState from "Feed/RelayState";
|
import useRelayState from "Feed/RelayState";
|
||||||
import { System } from "index";
|
import { SnortContext } from "@snort/system-react";
|
||||||
import { getRelayName, unwrap } from "SnortUtils";
|
import { getRelayName, unwrap } from "SnortUtils";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "Hooks/useLogin";
|
||||||
import { setRelays } from "Login";
|
import { setRelays } from "Login";
|
||||||
@ -20,9 +20,11 @@ export interface RelayProps {
|
|||||||
|
|
||||||
export default function Relay(props: RelayProps) {
|
export default function Relay(props: RelayProps) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const system = useContext(SnortContext);
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
|
|
||||||
const relaySettings = unwrap(
|
const relaySettings = unwrap(
|
||||||
login.relays.item[props.addr] ?? System.Sockets.find(a => a.address === props.addr)?.settings ?? {},
|
login.relays.item[props.addr] ?? system.Sockets.find(a => a.address === props.addr)?.settings ?? {},
|
||||||
);
|
);
|
||||||
const state = useRelayState(props.addr);
|
const state = useRelayState(props.addr);
|
||||||
const name = useMemo(() => getRelayName(props.addr), [props.addr]);
|
const name = useMemo(() => getRelayName(props.addr), [props.addr]);
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import "./SendSats.css";
|
import "./SendSats.css";
|
||||||
import React, { ReactNode, useContext, useEffect, useState } from "react";
|
import React, { ReactNode, useEffect, useState } from "react";
|
||||||
import { useIntl, FormattedMessage } from "react-intl";
|
import { useIntl, FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
import { HexKey } from "@snort/system";
|
import { HexKey } from "@snort/system";
|
||||||
import { SnortContext } from "@snort/system-react";
|
|
||||||
import { LNURLSuccessAction } from "@snort/shared";
|
import { LNURLSuccessAction } from "@snort/shared";
|
||||||
|
|
||||||
import { formatShort } from "Number";
|
import { formatShort } from "Number";
|
||||||
@ -48,8 +47,7 @@ export default function SendSats(props: SendSatsProps) {
|
|||||||
const [success, setSuccess] = useState<LNURLSuccessAction>();
|
const [success, setSuccess] = useState<LNURLSuccessAction>();
|
||||||
const [amount, setAmount] = useState<SendSatsInputSelection>();
|
const [amount, setAmount] = useState<SendSatsInputSelection>();
|
||||||
|
|
||||||
const system = useContext(SnortContext);
|
const { publisher, system } = useEventPublisher();
|
||||||
const publisher = useEventPublisher();
|
|
||||||
const walletState = useWallet();
|
const walletState = useWallet();
|
||||||
const wallet = walletState.wallet;
|
const wallet = walletState.wallet;
|
||||||
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
.sub-debug {
|
|
||||||
display: block;
|
|
||||||
position: fixed;
|
|
||||||
top: 5px;
|
|
||||||
left: 5px;
|
|
||||||
opacity: 0.8;
|
|
||||||
border: 1px solid;
|
|
||||||
padding: 5px;
|
|
||||||
font-family: monospace;
|
|
||||||
font-size: x-small;
|
|
||||||
background-color: black;
|
|
||||||
z-index: 999999;
|
|
||||||
color: white;
|
|
||||||
}
|
|
@ -1,99 +0,0 @@
|
|||||||
import "./SubDebug.css";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { ReqFilter } from "@snort/system";
|
|
||||||
import { useSystemState } from "@snort/system-react";
|
|
||||||
|
|
||||||
import useRelayState from "Feed/RelayState";
|
|
||||||
import Tabs, { Tab } from "Element/Tabs";
|
|
||||||
import { unwrap } from "SnortUtils";
|
|
||||||
import { useCopy } from "useCopy";
|
|
||||||
import { System } from "index";
|
|
||||||
|
|
||||||
function RelayInfo({ id }: { id: string }) {
|
|
||||||
const state = useRelayState(id);
|
|
||||||
return <div key={id}>{state?.connected ? <>{id}</> : <s>{id}</s>}</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Queries() {
|
|
||||||
const qs = useSystemState(System);
|
|
||||||
const { copy } = useCopy();
|
|
||||||
|
|
||||||
function countElements(filters: Array<ReqFilter>) {
|
|
||||||
let total = 0;
|
|
||||||
for (const f of filters) {
|
|
||||||
for (const v of Object.values(f)) {
|
|
||||||
if (Array.isArray(v)) {
|
|
||||||
total += v.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
function queryInfo(q: { id: string; filters: Array<ReqFilter>; subFilters: Array<ReqFilter> }) {
|
|
||||||
return (
|
|
||||||
<div key={q.id}>
|
|
||||||
{q.id}
|
|
||||||
<br />
|
|
||||||
<span onClick={() => copy(JSON.stringify(q.filters))} className="pointer">
|
|
||||||
Filters: {q.filters.length} ({countElements(q.filters)} elements)
|
|
||||||
</span>
|
|
||||||
<br />
|
|
||||||
<span onClick={() => copy(JSON.stringify(q.subFilters))} className="pointer">
|
|
||||||
SubQueries: {q.subFilters.length} ({countElements(q.subFilters)} elements)
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<b>Queries</b>
|
|
||||||
{qs?.queries.map(v => queryInfo(v))}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const SubDebug = () => {
|
|
||||||
const [onTab, setTab] = useState(0);
|
|
||||||
|
|
||||||
function connections() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<b>Connections:</b>
|
|
||||||
{System.Sockets.map(k => (
|
|
||||||
<RelayInfo id={k.address} />
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const tabs: Tab[] = [
|
|
||||||
{
|
|
||||||
text: "Connections",
|
|
||||||
value: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Queries",
|
|
||||||
value: 1,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="sub-debug">
|
|
||||||
<Tabs tabs={tabs} setTab={v => setTab(v.value)} tab={unwrap(tabs.find(a => a.value === onTab))} />
|
|
||||||
{(() => {
|
|
||||||
switch (onTab) {
|
|
||||||
case 0:
|
|
||||||
return connections();
|
|
||||||
case 1:
|
|
||||||
return <Queries />;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})()}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SubDebug;
|
|
@ -5,7 +5,6 @@ import useEventPublisher from "Hooks/useEventPublisher";
|
|||||||
import { parseId } from "SnortUtils";
|
import { parseId } from "SnortUtils";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "Hooks/useLogin";
|
||||||
import AsyncButton from "Element/AsyncButton";
|
import AsyncButton from "Element/AsyncButton";
|
||||||
import { System } from "index";
|
|
||||||
|
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
import { FollowsFeed } from "Cache";
|
import { FollowsFeed } from "Cache";
|
||||||
@ -16,7 +15,7 @@ export interface FollowButtonProps {
|
|||||||
}
|
}
|
||||||
export default function FollowButton(props: FollowButtonProps) {
|
export default function FollowButton(props: FollowButtonProps) {
|
||||||
const pubkey = parseId(props.pubkey);
|
const pubkey = parseId(props.pubkey);
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
const { follows, relays, readonly } = useLogin(s => ({ follows: s.follows, relays: s.relays, readonly: s.readonly }));
|
const { follows, relays, readonly } = useLogin(s => ({ follows: s.follows, relays: s.relays, readonly: s.readonly }));
|
||||||
const isFollowing = follows.item.includes(pubkey);
|
const isFollowing = follows.item.includes(pubkey);
|
||||||
const baseClassname = props.className ? `${props.className} ` : "";
|
const baseClassname = props.className ? `${props.className} ` : "";
|
||||||
@ -24,8 +23,8 @@ export default function FollowButton(props: FollowButtonProps) {
|
|||||||
async function follow(pubkey: HexKey) {
|
async function follow(pubkey: HexKey) {
|
||||||
if (publisher) {
|
if (publisher) {
|
||||||
const ev = await publisher.contactList([pubkey, ...follows.item], relays.item);
|
const ev = await publisher.contactList([pubkey, ...follows.item], relays.item);
|
||||||
System.BroadcastEvent(ev);
|
system.BroadcastEvent(ev);
|
||||||
await FollowsFeed.backFill(System, [pubkey]);
|
await FollowsFeed.backFill(system, [pubkey]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +34,7 @@ export default function FollowButton(props: FollowButtonProps) {
|
|||||||
follows.item.filter(a => a !== pubkey),
|
follows.item.filter(a => a !== pubkey),
|
||||||
relays.item,
|
relays.item,
|
||||||
);
|
);
|
||||||
System.BroadcastEvent(ev);
|
system.BroadcastEvent(ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import FormattedMessage from "Element/FormattedMessage";
|
import FormattedMessage from "Element/FormattedMessage";
|
||||||
import { HexKey } from "@snort/system";
|
import { HexKey } from "@snort/system";
|
||||||
|
import { dedupe } from "@snort/shared";
|
||||||
|
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "Hooks/useEventPublisher";
|
||||||
import ProfilePreview from "Element/User/ProfilePreview";
|
import ProfilePreview from "Element/User/ProfilePreview";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "Hooks/useLogin";
|
||||||
import { System } from "index";
|
|
||||||
|
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
import { FollowsFeed } from "Cache";
|
import { FollowsFeed } from "Cache";
|
||||||
import AsyncButton from "../AsyncButton";
|
import AsyncButton from "../AsyncButton";
|
||||||
import { setFollows } from "Login";
|
import { setFollows } from "Login";
|
||||||
import { dedupe } from "@snort/shared";
|
|
||||||
|
|
||||||
export interface FollowListBaseProps {
|
export interface FollowListBaseProps {
|
||||||
pubkeys: HexKey[];
|
pubkeys: HexKey[];
|
||||||
@ -32,15 +31,15 @@ export default function FollowListBase({
|
|||||||
actions,
|
actions,
|
||||||
profileActions,
|
profileActions,
|
||||||
}: FollowListBaseProps) {
|
}: FollowListBaseProps) {
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
|
|
||||||
async function followAll() {
|
async function followAll() {
|
||||||
if (publisher) {
|
if (publisher) {
|
||||||
const newFollows = dedupe([...pubkeys, ...login.follows.item]);
|
const newFollows = dedupe([...pubkeys, ...login.follows.item]);
|
||||||
const ev = await publisher.contactList(newFollows, login.relays.item);
|
const ev = await publisher.contactList(newFollows, login.relays.item);
|
||||||
System.BroadcastEvent(ev);
|
system.BroadcastEvent(ev);
|
||||||
await FollowsFeed.backFill(System, pubkeys);
|
await FollowsFeed.backFill(system, pubkeys);
|
||||||
setFollows(login, newFollows, ev.created_at);
|
setFollows(login, newFollows, ev.created_at);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ import { SnortPubKey } from "Const";
|
|||||||
import { SubscriptionEvent } from "Subscription";
|
import { SubscriptionEvent } from "Subscription";
|
||||||
import useRelaysFeedFollows from "./RelaysFeedFollows";
|
import useRelaysFeedFollows from "./RelaysFeedFollows";
|
||||||
import { FollowsFeed, GiftsCache, Notifications, UserRelays } from "Cache";
|
import { FollowsFeed, GiftsCache, Notifications, UserRelays } from "Cache";
|
||||||
import { System } from "index";
|
|
||||||
import { Nip28Chats, Nip4Chats } from "chat";
|
import { Nip28Chats, Nip4Chats } from "chat";
|
||||||
import { useRefreshFeedCache } from "Hooks/useRefreshFeedcache";
|
import { useRefreshFeedCache } from "Hooks/useRefreshFeedcache";
|
||||||
|
|
||||||
@ -35,12 +34,16 @@ export default function useLoginFeed() {
|
|||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
const { publicKey: pubKey, readNotifications, follows } = login;
|
const { publicKey: pubKey, readNotifications, follows } = login;
|
||||||
const { isMuted } = useModeration();
|
const { isMuted } = useModeration();
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
|
|
||||||
useRefreshFeedCache(Notifications, true);
|
useRefreshFeedCache(Notifications, true);
|
||||||
useRefreshFeedCache(FollowsFeed, true);
|
useRefreshFeedCache(FollowsFeed, true);
|
||||||
useRefreshFeedCache(GiftsCache, true);
|
useRefreshFeedCache(GiftsCache, true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
system.checkSigs = login.preferences.checkSigs;
|
||||||
|
}, [login]);
|
||||||
|
|
||||||
const subLogin = useMemo(() => {
|
const subLogin = useMemo(() => {
|
||||||
if (!login || !pubKey) return null;
|
if (!login || !pubKey) return null;
|
||||||
|
|
||||||
@ -88,7 +91,7 @@ export default function useLoginFeed() {
|
|||||||
const pTags = contactList.tags.filter(a => a[0] === "p").map(a => a[1]);
|
const pTags = contactList.tags.filter(a => a[0] === "p").map(a => a[1]);
|
||||||
setFollows(login, pTags, contactList.created_at * 1000);
|
setFollows(login, pTags, contactList.created_at * 1000);
|
||||||
|
|
||||||
FollowsFeed.backFillIfMissing(System, pTags);
|
FollowsFeed.backFillIfMissing(system, pTags);
|
||||||
}
|
}
|
||||||
|
|
||||||
Nip4Chats.onEvent(loginFeed.data);
|
Nip4Chats.onEvent(loginFeed.data);
|
||||||
@ -202,7 +205,7 @@ export default function useLoginFeed() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
UserRelays.buffer(follows.item).catch(console.error);
|
UserRelays.buffer(follows.item).catch(console.error);
|
||||||
System.ProfileLoader.TrackMetadata(follows.item); // always track follows profiles
|
system.ProfileLoader.TrackMetadata(follows.item); // always track follows profiles
|
||||||
}, [follows.item]);
|
}, [follows.item]);
|
||||||
|
|
||||||
const fRelays = useRelaysFeedFollows(follows.item);
|
const fRelays = useRelaysFeedFollows(follows.item);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { System } from "index";
|
import { useContext } from "react";
|
||||||
|
import { SnortContext } from "@snort/system-react";
|
||||||
|
|
||||||
export default function useRelayState(addr: string) {
|
export default function useRelayState(addr: string) {
|
||||||
const c = System.Sockets.find(a => a.address === addr);
|
const system = useContext(SnortContext);
|
||||||
|
const c = system.Sockets.find(a => a.address === addr);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ export default function useTimelineFeed(subject: TimelineSubject, options: Timel
|
|||||||
const rb = createBuilder();
|
const rb = createBuilder();
|
||||||
if (rb) {
|
if (rb) {
|
||||||
if (options.method === "LIMIT_UNTIL") {
|
if (options.method === "LIMIT_UNTIL") {
|
||||||
rb.filter.until(until).limit(200);
|
rb.filter.until(until).limit(100);
|
||||||
} else {
|
} else {
|
||||||
rb.filter.since(since).until(until);
|
rb.filter.since(since).until(until);
|
||||||
if (since === undefined) {
|
if (since === undefined) {
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
import { useContext } from "react";
|
||||||
|
import { SnortContext } from "@snort/system-react";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "Hooks/useLogin";
|
||||||
import { LoginStore, createPublisher, sessionNeedsPin } from "Login";
|
import { LoginStore, createPublisher, sessionNeedsPin } from "Login";
|
||||||
|
|
||||||
export default function useEventPublisher() {
|
export default function useEventPublisher() {
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
|
const system = useContext(SnortContext);
|
||||||
|
|
||||||
let existing = LoginStore.getPublisher(login.id);
|
let existing = LoginStore.getPublisher(login.id);
|
||||||
|
|
||||||
@ -12,5 +15,8 @@ export default function useEventPublisher() {
|
|||||||
LoginStore.setPublisher(login.id, existing);
|
LoginStore.setPublisher(login.id, existing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return existing;
|
return {
|
||||||
|
publisher: existing,
|
||||||
|
system,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import { System } from "index";
|
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import useLogin from "./useLogin";
|
import useLogin from "./useLogin";
|
||||||
|
import useEventPublisher from "./useEventPublisher";
|
||||||
|
|
||||||
export function useLoginRelays() {
|
export function useLoginRelays() {
|
||||||
const { relays } = useLogin();
|
const { relays } = useLogin();
|
||||||
|
const { system } = useEventPublisher();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (relays) {
|
if (relays) {
|
||||||
(async () => {
|
(async () => {
|
||||||
for (const [k, v] of Object.entries(relays.item)) {
|
for (const [k, v] of Object.entries(relays.item)) {
|
||||||
await System.ConnectToRelay(k, v);
|
await system.ConnectToRelay(k, v);
|
||||||
}
|
}
|
||||||
for (const v of System.Sockets) {
|
for (const v of system.Sockets) {
|
||||||
if (!relays.item[v.address] && !v.ephemeral) {
|
if (!relays.item[v.address] && !v.ephemeral) {
|
||||||
System.DisconnectRelay(v.address);
|
system.DisconnectRelay(v.address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -3,17 +3,16 @@ import useEventPublisher from "Hooks/useEventPublisher";
|
|||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "Hooks/useLogin";
|
||||||
import { setBlocked, setMuted } from "Login";
|
import { setBlocked, setMuted } from "Login";
|
||||||
import { appendDedupe } from "SnortUtils";
|
import { appendDedupe } from "SnortUtils";
|
||||||
import { System } from "index";
|
|
||||||
|
|
||||||
export default function useModeration() {
|
export default function useModeration() {
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
const { muted, blocked, appData } = login;
|
const { muted, blocked, appData } = login;
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
|
|
||||||
async function setMutedList(pub: HexKey[], priv: HexKey[]) {
|
async function setMutedList(pub: HexKey[], priv: HexKey[]) {
|
||||||
if (publisher) {
|
if (publisher) {
|
||||||
const ev = await publisher.muted(pub, priv);
|
const ev = await publisher.muted(pub, priv);
|
||||||
System.BroadcastEvent(ev);
|
system.BroadcastEvent(ev);
|
||||||
return ev.created_at * 1000;
|
return ev.created_at * 1000;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { SnortContext } from "@snort/system-react";
|
import { useEffect, useMemo } from "react";
|
||||||
import { useContext, useEffect, useMemo } from "react";
|
|
||||||
import { NoopStore, RequestBuilder, TaggedNostrEvent } from "@snort/system";
|
import { NoopStore, RequestBuilder, TaggedNostrEvent } from "@snort/system";
|
||||||
|
|
||||||
import { RefreshFeedCache } from "Cache/RefreshFeedCache";
|
import { RefreshFeedCache } from "Cache/RefreshFeedCache";
|
||||||
@ -8,9 +7,8 @@ import useEventPublisher from "./useEventPublisher";
|
|||||||
import { unwrap } from "@snort/shared";
|
import { unwrap } from "@snort/shared";
|
||||||
|
|
||||||
export function useRefreshFeedCache<T>(c: RefreshFeedCache<T>, leaveOpen = false) {
|
export function useRefreshFeedCache<T>(c: RefreshFeedCache<T>, leaveOpen = false) {
|
||||||
const system = useContext(SnortContext);
|
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
|
|
||||||
const sub = useMemo(() => {
|
const sub = useMemo(() => {
|
||||||
if (login.publicKey) {
|
if (login.publicKey) {
|
||||||
|
@ -1,4 +1,12 @@
|
|||||||
import { RelaySettings, EventPublisher, Nip46Signer, Nip7Signer, PrivateKeySigner, KeyStorage } from "@snort/system";
|
import {
|
||||||
|
RelaySettings,
|
||||||
|
EventPublisher,
|
||||||
|
Nip46Signer,
|
||||||
|
Nip7Signer,
|
||||||
|
PrivateKeySigner,
|
||||||
|
KeyStorage,
|
||||||
|
SystemInterface,
|
||||||
|
} from "@snort/system";
|
||||||
import { unixNowMs } from "@snort/shared";
|
import { unixNowMs } from "@snort/shared";
|
||||||
import * as secp from "@noble/curves/secp256k1";
|
import * as secp from "@noble/curves/secp256k1";
|
||||||
import * as utils from "@noble/curves/abstract/utils";
|
import * as utils from "@noble/curves/abstract/utils";
|
||||||
@ -8,7 +16,6 @@ import { LoginStore, UserPreferences, LoginSession, LoginSessionType, SnortAppDa
|
|||||||
import { generateBip39Entropy, entropyToPrivateKey } from "nip6";
|
import { generateBip39Entropy, entropyToPrivateKey } from "nip6";
|
||||||
import { bech32ToHex, dedupeById, randomSample, sanitizeRelayUrl, unwrap } from "SnortUtils";
|
import { bech32ToHex, dedupeById, randomSample, sanitizeRelayUrl, unwrap } from "SnortUtils";
|
||||||
import { SubscriptionEvent } from "Subscription";
|
import { SubscriptionEvent } from "Subscription";
|
||||||
import { System } from "index";
|
|
||||||
import { Chats, FollowsFeed, GiftsCache, Notifications } from "Cache";
|
import { Chats, FollowsFeed, GiftsCache, Notifications } from "Cache";
|
||||||
import { Nip7OsSigner } from "./Nip7OsSigner";
|
import { Nip7OsSigner } from "./Nip7OsSigner";
|
||||||
|
|
||||||
@ -63,7 +70,7 @@ export function clearEntropy(state: LoginSession) {
|
|||||||
/**
|
/**
|
||||||
* Generate a new key and login with this generated key
|
* Generate a new key and login with this generated key
|
||||||
*/
|
*/
|
||||||
export async function generateNewLogin(pin: (key: string) => Promise<KeyStorage>) {
|
export async function generateNewLogin(system: SystemInterface, pin: (key: string) => Promise<KeyStorage>) {
|
||||||
const ent = generateBip39Entropy();
|
const ent = generateBip39Entropy();
|
||||||
const entropy = utils.bytesToHex(ent);
|
const entropy = utils.bytesToHex(ent);
|
||||||
const privateKey = entropyToPrivateKey(ent);
|
const privateKey = entropyToPrivateKey(ent);
|
||||||
@ -87,7 +94,7 @@ export async function generateNewLogin(pin: (key: string) => Promise<KeyStorage>
|
|||||||
const publicKey = utils.bytesToHex(secp.schnorr.getPublicKey(privateKey));
|
const publicKey = utils.bytesToHex(secp.schnorr.getPublicKey(privateKey));
|
||||||
const publisher = EventPublisher.privateKey(privateKey);
|
const publisher = EventPublisher.privateKey(privateKey);
|
||||||
const ev = await publisher.contactList([bech32ToHex(SnortPubKey), publicKey], newRelays);
|
const ev = await publisher.contactList([bech32ToHex(SnortPubKey), publicKey], newRelays);
|
||||||
System.BroadcastEvent(ev);
|
system.BroadcastEvent(ev);
|
||||||
LoginStore.loginWithPrivateKey(await pin(privateKey), entropy, newRelays);
|
LoginStore.loginWithPrivateKey(await pin(privateKey), entropy, newRelays);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,11 +74,12 @@ export class MultiAccountStore extends ExternalStore<LoginSession> {
|
|||||||
if (!this.#activeAccount) {
|
if (!this.#activeAccount) {
|
||||||
this.#activeAccount = this.#accounts.keys().next().value;
|
this.#activeAccount = this.#accounts.keys().next().value;
|
||||||
}
|
}
|
||||||
// reset readonly on load
|
|
||||||
for (const [, v] of this.#accounts) {
|
for (const [, v] of this.#accounts) {
|
||||||
|
// reset readonly on load
|
||||||
if (v.type === LoginSessionType.PrivateKey && v.readonly) {
|
if (v.type === LoginSessionType.PrivateKey && v.readonly) {
|
||||||
v.readonly = false;
|
v.readonly = false;
|
||||||
}
|
}
|
||||||
|
// fill possibly undefined (migrate up)
|
||||||
v.appData ??= {
|
v.appData ??= {
|
||||||
item: {
|
item: {
|
||||||
mutedWords: [],
|
mutedWords: [],
|
||||||
@ -86,6 +87,7 @@ export class MultiAccountStore extends ExternalStore<LoginSession> {
|
|||||||
timestamp: 0,
|
timestamp: 0,
|
||||||
};
|
};
|
||||||
v.extraChats ??= [];
|
v.extraChats ??= [];
|
||||||
|
v.preferences.checkSigs ??= true;
|
||||||
if (v.privateKeyData) {
|
if (v.privateKeyData) {
|
||||||
v.privateKeyData = KeyStorage.fromPayload(v.privateKeyData as object);
|
v.privateKeyData = KeyStorage.fromPayload(v.privateKeyData as object);
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,11 @@ export interface UserPreferences {
|
|||||||
* Show user status messages on profiles
|
* Show user status messages on profiles
|
||||||
*/
|
*/
|
||||||
showStatus?: boolean;
|
showStatus?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check event signatures
|
||||||
|
*/
|
||||||
|
checkSigs: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DefaultPreferences = {
|
export const DefaultPreferences = {
|
||||||
@ -105,4 +110,5 @@ export const DefaultPreferences = {
|
|||||||
telemetry: true,
|
telemetry: true,
|
||||||
showBadges: false,
|
showBadges: false,
|
||||||
showStatus: true,
|
showStatus: true,
|
||||||
|
checkSigs: true,
|
||||||
} as UserPreferences;
|
} as UserPreferences;
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
import SubDebug from "Element/SubDebug";
|
|
||||||
|
|
||||||
export default function DebugPage() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<SubDebug />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
@ -6,7 +6,6 @@ import Timeline from "Element/Feed/Timeline";
|
|||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "Hooks/useEventPublisher";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "Hooks/useLogin";
|
||||||
import { setTags } from "Login";
|
import { setTags } from "Login";
|
||||||
import { System } from "index";
|
|
||||||
|
|
||||||
const HashTagsPage = () => {
|
const HashTagsPage = () => {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
@ -15,12 +14,12 @@ const HashTagsPage = () => {
|
|||||||
const isFollowing = useMemo(() => {
|
const isFollowing = useMemo(() => {
|
||||||
return login.tags.item.includes(tag);
|
return login.tags.item.includes(tag);
|
||||||
}, [login, tag]);
|
}, [login, tag]);
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
|
|
||||||
async function followTags(ts: string[]) {
|
async function followTags(ts: string[]) {
|
||||||
if (publisher) {
|
if (publisher) {
|
||||||
const ev = await publisher.tags(ts);
|
const ev = await publisher.tags(ts);
|
||||||
System.BroadcastEvent(ev);
|
system.BroadcastEvent(ev);
|
||||||
setTags(login, ts, ev.created_at * 1000);
|
setTags(login, ts, ev.created_at * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import QrCode from "Element/QrCode";
|
|||||||
import Copy from "Element/Copy";
|
import Copy from "Element/Copy";
|
||||||
import { delay } from "SnortUtils";
|
import { delay } from "SnortUtils";
|
||||||
import { PinPrompt } from "Element/PinPrompt";
|
import { PinPrompt } from "Element/PinPrompt";
|
||||||
|
import useEventPublisher from "Hooks/useEventPublisher";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
@ -85,6 +86,7 @@ export default function LoginPage() {
|
|||||||
const { proxy } = useImgProxy();
|
const { proxy } = useImgProxy();
|
||||||
const loginHandler = useLoginHandler();
|
const loginHandler = useLoginHandler();
|
||||||
const hasNip7 = "nostr" in window;
|
const hasNip7 = "nostr" in window;
|
||||||
|
const { system } = useEventPublisher();
|
||||||
const hasSubtleCrypto = window.crypto.subtle !== undefined;
|
const hasSubtleCrypto = window.crypto.subtle !== undefined;
|
||||||
const [nostrConnect, setNostrConnect] = useState("");
|
const [nostrConnect, setNostrConnect] = useState("");
|
||||||
|
|
||||||
@ -123,7 +125,7 @@ export default function LoginPage() {
|
|||||||
|
|
||||||
async function makeRandomKey(pin?: string) {
|
async function makeRandomKey(pin?: string) {
|
||||||
try {
|
try {
|
||||||
await generateNewLogin(key => makeKeyStore(key, pin));
|
await generateNewLogin(system, key => makeKeyStore(key, pin));
|
||||||
window.plausible?.("Generate Account");
|
window.plausible?.("Generate Account");
|
||||||
navigate("/new");
|
navigate("/new");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -3,9 +3,9 @@ import { Link, Outlet, RouteObject, useParams } from "react-router-dom";
|
|||||||
import FormattedMessage from "Element/FormattedMessage";
|
import FormattedMessage from "Element/FormattedMessage";
|
||||||
import { unixNow } from "@snort/shared";
|
import { unixNow } from "@snort/shared";
|
||||||
import { NostrLink } from "@snort/system";
|
import { NostrLink } from "@snort/system";
|
||||||
|
import { SnortContext } from "@snort/system-react";
|
||||||
|
|
||||||
import Timeline from "Element/Feed/Timeline";
|
import Timeline from "Element/Feed/Timeline";
|
||||||
import { System } from "index";
|
|
||||||
import { TimelineSubject } from "Feed/TimelineFeed";
|
import { TimelineSubject } from "Feed/TimelineFeed";
|
||||||
import { debounce, getRelayName, sha256 } from "SnortUtils";
|
import { debounce, getRelayName, sha256 } from "SnortUtils";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "Hooks/useLogin";
|
||||||
@ -63,6 +63,7 @@ export const GlobalTab = () => {
|
|||||||
const [relay, setRelay] = useState<RelayOption>();
|
const [relay, setRelay] = useState<RelayOption>();
|
||||||
const [allRelays, setAllRelays] = useState<RelayOption[]>();
|
const [allRelays, setAllRelays] = useState<RelayOption[]>();
|
||||||
const [now] = useState(unixNow());
|
const [now] = useState(unixNow());
|
||||||
|
const system = useContext(SnortContext);
|
||||||
|
|
||||||
const subject: TimelineSubject = {
|
const subject: TimelineSubject = {
|
||||||
type: "global",
|
type: "global",
|
||||||
@ -111,7 +112,7 @@ export const GlobalTab = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return debounce(500, () => {
|
return debounce(500, () => {
|
||||||
const ret: RelayOption[] = [];
|
const ret: RelayOption[] = [];
|
||||||
System.Sockets.forEach(v => {
|
system.Sockets.forEach(v => {
|
||||||
ret.push({
|
ret.push({
|
||||||
url: v.address,
|
url: v.address,
|
||||||
paid: v.info?.limitation?.payment_required ?? false,
|
paid: v.info?.limitation?.payment_required ?? false,
|
||||||
|
@ -12,7 +12,7 @@ import { bech32ToHex, getRelayName, unwrap } from "SnortUtils";
|
|||||||
import { ZapPoolController, ZapPoolRecipient, ZapPoolRecipientType } from "ZapPoolController";
|
import { ZapPoolController, ZapPoolRecipient, ZapPoolRecipientType } from "ZapPoolController";
|
||||||
import AsyncButton from "Element/AsyncButton";
|
import AsyncButton from "Element/AsyncButton";
|
||||||
import { useWallet } from "Wallet";
|
import { useWallet } from "Wallet";
|
||||||
import { System } from "index";
|
import useEventPublisher from "Hooks/useEventPublisher";
|
||||||
|
|
||||||
const DataProviders = [
|
const DataProviders = [
|
||||||
{
|
{
|
||||||
@ -71,6 +71,7 @@ function ZapTarget({ target }: { target: ZapPoolRecipient }) {
|
|||||||
|
|
||||||
export default function ZapPoolPage() {
|
export default function ZapPoolPage() {
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
|
const { system } = useEventPublisher();
|
||||||
const zapPool = useSyncExternalStore(
|
const zapPool = useSyncExternalStore(
|
||||||
c => ZapPoolController.hook(c),
|
c => ZapPoolController.hook(c),
|
||||||
() => ZapPoolController.snapshot(),
|
() => ZapPoolController.snapshot(),
|
||||||
@ -78,7 +79,7 @@ export default function ZapPoolPage() {
|
|||||||
const { wallet } = useWallet();
|
const { wallet } = useWallet();
|
||||||
|
|
||||||
const relayConnections = useMemo(() => {
|
const relayConnections = useMemo(() => {
|
||||||
return System.Sockets.map(a => {
|
return system.Sockets.map(a => {
|
||||||
if (a.info?.pubkey && !a.ephemeral) {
|
if (a.info?.pubkey && !a.ephemeral) {
|
||||||
return {
|
return {
|
||||||
address: a.address,
|
address: a.address,
|
||||||
|
@ -10,7 +10,6 @@ import useLogin from "Hooks/useLogin";
|
|||||||
import { UserCache } from "Cache";
|
import { UserCache } from "Cache";
|
||||||
import AvatarEditor from "Element/User/AvatarEditor";
|
import AvatarEditor from "Element/User/AvatarEditor";
|
||||||
import { DISCOVER } from ".";
|
import { DISCOVER } from ".";
|
||||||
import { System } from "index";
|
|
||||||
|
|
||||||
import messages from "./messages";
|
import messages from "./messages";
|
||||||
|
|
||||||
@ -20,7 +19,7 @@ export default function ProfileSetup() {
|
|||||||
const [username, setUsername] = useState("");
|
const [username, setUsername] = useState("");
|
||||||
const [picture, setPicture] = useState("");
|
const [picture, setPicture] = useState("");
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -37,7 +36,7 @@ export default function ProfileSetup() {
|
|||||||
name: username,
|
name: username,
|
||||||
picture,
|
picture,
|
||||||
});
|
});
|
||||||
System.BroadcastEvent(ev);
|
system.BroadcastEvent(ev);
|
||||||
const profile = mapEventToProfile(ev);
|
const profile = mapEventToProfile(ev);
|
||||||
if (profile) {
|
if (profile) {
|
||||||
UserCache.set(profile);
|
UserCache.set(profile);
|
||||||
|
@ -176,6 +176,23 @@ const PreferencesPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex f-space w-max">
|
||||||
|
<div className="flex-column g8">
|
||||||
|
<h4>
|
||||||
|
<FormattedMessage defaultMessage="Check Signatures" />
|
||||||
|
</h4>
|
||||||
|
<small>
|
||||||
|
<FormattedMessage defaultMessage="Check all event signatures received from relays" />
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={perf.checkSigs}
|
||||||
|
onChange={e => updatePreferences(login, { ...perf, checkSigs: e.target.checked })}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="flex f-space w-max">
|
<div className="flex f-space w-max">
|
||||||
<div className="flex-column g8">
|
<div className="flex-column g8">
|
||||||
<h4>
|
<h4>
|
||||||
|
@ -5,7 +5,6 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import { mapEventToProfile } from "@snort/system";
|
import { mapEventToProfile } from "@snort/system";
|
||||||
import { useUserProfile } from "@snort/system-react";
|
import { useUserProfile } from "@snort/system-react";
|
||||||
|
|
||||||
import { System } from "index";
|
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "Hooks/useEventPublisher";
|
||||||
import { openFile } from "SnortUtils";
|
import { openFile } from "SnortUtils";
|
||||||
import useFileUpload from "Upload";
|
import useFileUpload from "Upload";
|
||||||
@ -24,7 +23,7 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { publicKey: id, readonly } = useLogin(s => ({ publicKey: s.publicKey, readonly: s.readonly }));
|
const { publicKey: id, readonly } = useLogin(s => ({ publicKey: s.publicKey, readonly: s.readonly }));
|
||||||
const user = useUserProfile(id ?? "");
|
const user = useUserProfile(id ?? "");
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
const uploader = useFileUpload();
|
const uploader = useFileUpload();
|
||||||
|
|
||||||
const [name, setName] = useState<string>();
|
const [name, setName] = useState<string>();
|
||||||
@ -70,7 +69,7 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
|||||||
|
|
||||||
if (publisher) {
|
if (publisher) {
|
||||||
const ev = await publisher.metadata(userCopy);
|
const ev = await publisher.metadata(userCopy);
|
||||||
System.BroadcastEvent(ev);
|
system.BroadcastEvent(ev);
|
||||||
|
|
||||||
const newProfile = mapEventToProfile(ev);
|
const newProfile = mapEventToProfile(ev);
|
||||||
if (newProfile) {
|
if (newProfile) {
|
||||||
|
@ -3,18 +3,19 @@ import ProfilePreview from "Element/User/ProfilePreview";
|
|||||||
import useRelayState from "Feed/RelayState";
|
import useRelayState from "Feed/RelayState";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { parseId, unwrap } from "SnortUtils";
|
import { parseId, unwrap } from "SnortUtils";
|
||||||
import { System } from "index";
|
|
||||||
import { removeRelay } from "Login";
|
import { removeRelay } from "Login";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "Hooks/useLogin";
|
||||||
|
|
||||||
import messages from "./messages";
|
import messages from "./messages";
|
||||||
|
import useEventPublisher from "Hooks/useEventPublisher";
|
||||||
|
|
||||||
const RelayInfo = () => {
|
const RelayInfo = () => {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
|
const { system } = useEventPublisher();
|
||||||
|
|
||||||
const conn = System.Sockets.find(a => a.id === params.id);
|
const conn = system.Sockets.find(a => a.id === params.id);
|
||||||
const stats = useRelayState(conn?.address ?? "");
|
const stats = useRelayState(conn?.address ?? "");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -5,7 +5,6 @@ import { unixNowMs } from "@snort/shared";
|
|||||||
import { randomSample } from "SnortUtils";
|
import { randomSample } from "SnortUtils";
|
||||||
import Relay from "Element/Relay/Relay";
|
import Relay from "Element/Relay/Relay";
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "Hooks/useEventPublisher";
|
||||||
import { System } from "index";
|
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "Hooks/useLogin";
|
||||||
import { setRelays } from "Login";
|
import { setRelays } from "Login";
|
||||||
import AsyncButton from "Element/AsyncButton";
|
import AsyncButton from "Element/AsyncButton";
|
||||||
@ -13,25 +12,25 @@ import AsyncButton from "Element/AsyncButton";
|
|||||||
import messages from "./messages";
|
import messages from "./messages";
|
||||||
|
|
||||||
const RelaySettingsPage = () => {
|
const RelaySettingsPage = () => {
|
||||||
const publisher = useEventPublisher();
|
const { publisher, system } = useEventPublisher();
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
const relays = login.relays;
|
const relays = login.relays;
|
||||||
const [newRelay, setNewRelay] = useState<string>();
|
const [newRelay, setNewRelay] = useState<string>();
|
||||||
|
|
||||||
const otherConnections = useMemo(() => {
|
const otherConnections = useMemo(() => {
|
||||||
return System.Sockets.filter(a => relays.item[a.address] === undefined);
|
return system.Sockets.filter(a => relays.item[a.address] === undefined);
|
||||||
}, [relays]);
|
}, [relays]);
|
||||||
|
|
||||||
async function saveRelays() {
|
async function saveRelays() {
|
||||||
if (publisher) {
|
if (publisher) {
|
||||||
const ev = await publisher.contactList(login.follows.item, login.relays.item);
|
const ev = await publisher.contactList(login.follows.item, login.relays.item);
|
||||||
System.BroadcastEvent(ev);
|
system.BroadcastEvent(ev);
|
||||||
try {
|
try {
|
||||||
const onlineRelays = await fetch("https://api.nostr.watch/v1/online").then(r => r.json());
|
const onlineRelays = await fetch("https://api.nostr.watch/v1/online").then(r => r.json());
|
||||||
const relayList = await publisher.relayList(login.relays.item);
|
const relayList = await publisher.relayList(login.relays.item);
|
||||||
const rs = Object.keys(relays.item).concat(randomSample(onlineRelays, 20));
|
const rs = Object.keys(relays.item).concat(randomSample(onlineRelays, 20));
|
||||||
rs.forEach(r => {
|
rs.forEach(r => {
|
||||||
System.WriteOnceToRelay(r, relayList);
|
system.WriteOnceToRelay(r, relayList);
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
@ -9,7 +9,7 @@ import SnortServiceProvider, { ManageHandle } from "Nip05/SnortServiceProvider";
|
|||||||
|
|
||||||
export default function LNForwardAddress({ handle }: { handle: ManageHandle }) {
|
export default function LNForwardAddress({ handle }: { handle: ManageHandle }) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const publisher = useEventPublisher();
|
const { publisher } = useEventPublisher();
|
||||||
|
|
||||||
const [newAddress, setNewAddress] = useState(handle.lnAddress ?? "");
|
const [newAddress, setNewAddress] = useState(handle.lnAddress ?? "");
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
|
@ -8,7 +8,7 @@ import SnortServiceProvider, { ManageHandle } from "Nip05/SnortServiceProvider";
|
|||||||
|
|
||||||
export default function ListHandles() {
|
export default function ListHandles() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const publisher = useEventPublisher();
|
const { publisher } = useEventPublisher();
|
||||||
const [handles, setHandles] = useState<Array<ManageHandle>>([]);
|
const [handles, setHandles] = useState<Array<ManageHandle>>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { ApiHost } from "Const";
|
import { ApiHost } from "Const";
|
||||||
import AsyncButton from "Element/AsyncButton";
|
import AsyncButton from "Element/AsyncButton";
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "Hooks/useEventPublisher";
|
||||||
import { ServiceError } from "Nip05/ServiceProvider";
|
import { ServiceError } from "Nip05/ServiceProvider";
|
||||||
import SnortServiceProvider, { ManageHandle } from "Nip05/SnortServiceProvider";
|
import SnortServiceProvider, { ManageHandle } from "Nip05/SnortServiceProvider";
|
||||||
import { useState } from "react";
|
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
|
|
||||||
export default function TransferHandle({ handle }: { handle: ManageHandle }) {
|
export default function TransferHandle({ handle }: { handle: ManageHandle }) {
|
||||||
const publisher = useEventPublisher();
|
const { publisher } = useEventPublisher();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import { mapSubscriptionErrorCode } from ".";
|
|||||||
import SubscriptionCard from "./SubscriptionCard";
|
import SubscriptionCard from "./SubscriptionCard";
|
||||||
|
|
||||||
export default function ManageSubscriptionPage() {
|
export default function ManageSubscriptionPage() {
|
||||||
const publisher = useEventPublisher();
|
const { publisher } = useEventPublisher();
|
||||||
const api = new SnortApi(undefined, publisher);
|
const api = new SnortApi(undefined, publisher);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import { SnortNostrAddressService } from "Pages/NostrAddressPage";
|
|||||||
import Nip05 from "Element/User/Nip05";
|
import Nip05 from "Element/User/Nip05";
|
||||||
|
|
||||||
export default function SubscriptionCard({ sub }: { sub: Subscription }) {
|
export default function SubscriptionCard({ sub }: { sub: Subscription }) {
|
||||||
const publisher = useEventPublisher();
|
const { publisher } = useEventPublisher();
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
const created = new Date(sub.created * 1000);
|
const created = new Date(sub.created * 1000);
|
||||||
|
@ -58,7 +58,7 @@ export function mapSubscriptionErrorCode(c: SubscriptionError) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function SubscribePage() {
|
export function SubscribePage() {
|
||||||
const publisher = useEventPublisher();
|
const { publisher } = useEventPublisher();
|
||||||
const api = new SnortApi(undefined, publisher);
|
const api = new SnortApi(undefined, publisher);
|
||||||
const [invoice, setInvoice] = useState("");
|
const [invoice, setInvoice] = useState("");
|
||||||
const [error, setError] = useState<SubscriptionError>();
|
const [error, setError] = useState<SubscriptionError>();
|
||||||
|
@ -41,7 +41,6 @@ export interface Uploader {
|
|||||||
|
|
||||||
export default function useFileUpload(): Uploader {
|
export default function useFileUpload(): Uploader {
|
||||||
const fileUploader = useLogin().preferences.fileUploader;
|
const fileUploader = useLogin().preferences.fileUploader;
|
||||||
//const publisher = useEventPublisher();
|
|
||||||
|
|
||||||
switch (fileUploader) {
|
switch (fileUploader) {
|
||||||
case "nostr.build": {
|
case "nostr.build": {
|
||||||
|
@ -43,7 +43,6 @@ import NostrLinkHandler from "Pages/NostrLinkHandler";
|
|||||||
import { ThreadRoute } from "Element/Event/Thread";
|
import { ThreadRoute } from "Element/Event/Thread";
|
||||||
import { SubscribeRoutes } from "Pages/subscribe";
|
import { SubscribeRoutes } from "Pages/subscribe";
|
||||||
import ZapPoolPage from "Pages/ZapPool";
|
import ZapPoolPage from "Pages/ZapPool";
|
||||||
import DebugPage from "Pages/Debug";
|
|
||||||
import { db } from "Db";
|
import { db } from "Db";
|
||||||
import { preload, RelayMetrics, SystemDb, UserCache, UserRelays } from "Cache";
|
import { preload, RelayMetrics, SystemDb, UserCache, UserRelays } from "Cache";
|
||||||
import { LoginStore } from "Login";
|
import { LoginStore } from "Login";
|
||||||
@ -80,7 +79,7 @@ export const GetPowWorker = () => (hasWasm ? new WasmPowWorker() : unwrap(Defaul
|
|||||||
/**
|
/**
|
||||||
* Singleton nostr system
|
* Singleton nostr system
|
||||||
*/
|
*/
|
||||||
export const System = new NostrSystem({
|
const System = new NostrSystem({
|
||||||
relayCache: UserRelays,
|
relayCache: UserRelays,
|
||||||
profileCache: UserCache,
|
profileCache: UserCache,
|
||||||
relayMetrics: RelayMetrics,
|
relayMetrics: RelayMetrics,
|
||||||
@ -229,10 +228,6 @@ export const router = createBrowserRouter([
|
|||||||
...NewUserRoutes,
|
...NewUserRoutes,
|
||||||
...WalletRoutes,
|
...WalletRoutes,
|
||||||
...(CONFIG.features.subscriptions ? SubscribeRoutes : []),
|
...(CONFIG.features.subscriptions ? SubscribeRoutes : []),
|
||||||
{
|
|
||||||
path: "/debug",
|
|
||||||
element: <DebugPage />,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "/*",
|
path: "/*",
|
||||||
element: <NostrLinkHandler />,
|
element: <NostrLinkHandler />,
|
||||||
|
@ -90,6 +90,9 @@
|
|||||||
"1nYUGC": {
|
"1nYUGC": {
|
||||||
"defaultMessage": "{n} Following"
|
"defaultMessage": "{n} Following"
|
||||||
},
|
},
|
||||||
|
"1o2BgB": {
|
||||||
|
"defaultMessage": "Check Signatures"
|
||||||
|
},
|
||||||
"1udzha": {
|
"1udzha": {
|
||||||
"defaultMessage": "Conversations"
|
"defaultMessage": "Conversations"
|
||||||
},
|
},
|
||||||
@ -832,6 +835,9 @@
|
|||||||
"UJTWqI": {
|
"UJTWqI": {
|
||||||
"defaultMessage": "Remove from my relays"
|
"defaultMessage": "Remove from my relays"
|
||||||
},
|
},
|
||||||
|
"UNjfWJ": {
|
||||||
|
"defaultMessage": "Check all event signatures received from relays"
|
||||||
|
},
|
||||||
"UT7Nkj": {
|
"UT7Nkj": {
|
||||||
"defaultMessage": "New Chat"
|
"defaultMessage": "New Chat"
|
||||||
},
|
},
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
"1c4YST": "Connected to: {node} 🎉",
|
"1c4YST": "Connected to: {node} 🎉",
|
||||||
"1iQ8GN": "Toggle Preview",
|
"1iQ8GN": "Toggle Preview",
|
||||||
"1nYUGC": "{n} Following",
|
"1nYUGC": "{n} Following",
|
||||||
|
"1o2BgB": "Check Signatures",
|
||||||
"1udzha": "Conversations",
|
"1udzha": "Conversations",
|
||||||
"2/2yg+": "Add",
|
"2/2yg+": "Add",
|
||||||
"25V4l1": "Banner",
|
"25V4l1": "Banner",
|
||||||
@ -272,6 +273,7 @@
|
|||||||
"Tpy00S": "People",
|
"Tpy00S": "People",
|
||||||
"UDYlxu": "Pending Subscriptions",
|
"UDYlxu": "Pending Subscriptions",
|
||||||
"UJTWqI": "Remove from my relays",
|
"UJTWqI": "Remove from my relays",
|
||||||
|
"UNjfWJ": "Check all event signatures received from relays",
|
||||||
"UT7Nkj": "New Chat",
|
"UT7Nkj": "New Chat",
|
||||||
"UUPFlt": "Users must accept the content warning to show the content of your note.",
|
"UUPFlt": "Users must accept the content warning to show the content of your note.",
|
||||||
"Up5U7K": "Block",
|
"Up5U7K": "Block",
|
||||||
|
@ -176,6 +176,6 @@ export abstract class EventExt {
|
|||||||
if (type === EventType.ParameterizedReplaceable) {
|
if (type === EventType.ParameterizedReplaceable) {
|
||||||
if (!findTag(ev, "d")) return false;
|
if (!findTag(ev, "d")) return false;
|
||||||
}
|
}
|
||||||
return EventExt.verify(ev);
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,11 @@ export * from "./cache/user-metadata";
|
|||||||
export * from "./cache/relay-metric";
|
export * from "./cache/relay-metric";
|
||||||
|
|
||||||
export interface SystemInterface {
|
export interface SystemInterface {
|
||||||
|
/**
|
||||||
|
* Check event signatures (reccomended)
|
||||||
|
*/
|
||||||
|
checkSigs: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler function for NIP-42
|
* Handler function for NIP-42
|
||||||
*/
|
*/
|
||||||
|
@ -81,6 +81,11 @@ export class NostrSystem extends ExternalStore<SystemSnapshot> implements System
|
|||||||
*/
|
*/
|
||||||
#queryOptimizer: QueryOptimizer;
|
#queryOptimizer: QueryOptimizer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check event signatures (reccomended)
|
||||||
|
*/
|
||||||
|
checkSigs: boolean;
|
||||||
|
|
||||||
constructor(props: {
|
constructor(props: {
|
||||||
authHandler?: AuthHandler;
|
authHandler?: AuthHandler;
|
||||||
relayCache?: FeedCache<UsersRelays>;
|
relayCache?: FeedCache<UsersRelays>;
|
||||||
@ -89,6 +94,7 @@ export class NostrSystem extends ExternalStore<SystemSnapshot> implements System
|
|||||||
eventsCache?: FeedCache<NostrEvent>;
|
eventsCache?: FeedCache<NostrEvent>;
|
||||||
queryOptimizer?: QueryOptimizer;
|
queryOptimizer?: QueryOptimizer;
|
||||||
db?: SnortSystemDb;
|
db?: SnortSystemDb;
|
||||||
|
checkSigs?: boolean;
|
||||||
}) {
|
}) {
|
||||||
super();
|
super();
|
||||||
this.#handleAuth = props.authHandler;
|
this.#handleAuth = props.authHandler;
|
||||||
@ -100,6 +106,7 @@ export class NostrSystem extends ExternalStore<SystemSnapshot> implements System
|
|||||||
|
|
||||||
this.#profileLoader = new ProfileLoaderService(this, this.#profileCache);
|
this.#profileLoader = new ProfileLoaderService(this, this.#profileCache);
|
||||||
this.#relayMetrics = new RelayMetricHandler(this.#relayMetricsCache);
|
this.#relayMetrics = new RelayMetricHandler(this.#relayMetricsCache);
|
||||||
|
this.checkSigs = props.checkSigs ?? true;
|
||||||
this.#cleanup();
|
this.#cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,6 +190,10 @@ export class NostrSystem extends ExternalStore<SystemSnapshot> implements System
|
|||||||
this.#log("Rejecting invalid event %O", ev);
|
this.#log("Rejecting invalid event %O", ev);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (this.checkSigs && !EventExt.verify(ev)) {
|
||||||
|
this.#log("Invalid sig %O", ev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (const [, v] of this.Queries) {
|
for (const [, v] of this.Queries) {
|
||||||
v.handleEvent(sub, ev);
|
v.handleEvent(sub, ev);
|
||||||
|
Loading…
Reference in New Issue
Block a user