bug: improve relay handeling
This commit is contained in:
@ -19,9 +19,7 @@ export const ProfileCacheExpire = (1_000 * 60 * 5);
|
|||||||
* Default bootstrap relays
|
* Default bootstrap relays
|
||||||
*/
|
*/
|
||||||
export const DefaultRelays = new Map<string, RelaySettings>([
|
export const DefaultRelays = new Map<string, RelaySettings>([
|
||||||
["wss://relay.snort.social", { read: true, write: true }],
|
["wss://relay.snort.social", { read: true, write: true }]
|
||||||
["wss://relay.damus.io", { read: true, write: true }],
|
|
||||||
["wss://nostr-pub.wellorder.net", { read: true, write: true }],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,7 +63,7 @@ export default function Relay(props: RelayProps) {
|
|||||||
<FontAwesomeIcon icon={faPlugCircleXmark} /> {state?.disconnects}
|
<FontAwesomeIcon icon={faPlugCircleXmark} /> {state?.disconnects}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="icon-btn" onClick={() => navigate(name)}>
|
<span className="icon-btn" onClick={() => navigate(state!.id)}>
|
||||||
<FontAwesomeIcon icon={faGear} />
|
<FontAwesomeIcon icon={faGear} />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,7 +13,7 @@ declare global {
|
|||||||
nostr: {
|
nostr: {
|
||||||
getPublicKey: () => Promise<HexKey>,
|
getPublicKey: () => Promise<HexKey>,
|
||||||
signEvent: (event: RawEvent) => Promise<RawEvent>,
|
signEvent: (event: RawEvent) => Promise<RawEvent>,
|
||||||
getRelays: () => Promise<[[string, { read: boolean, write: boolean }]]>,
|
getRelays: () => Promise<Record<string, { read: boolean, write: boolean }>>,
|
||||||
nip04: {
|
nip04: {
|
||||||
encrypt: (pubkey: HexKey, content: string) => Promise<string>,
|
encrypt: (pubkey: HexKey, content: string) => Promise<string>,
|
||||||
decrypt: (pubkey: HexKey, content: string) => Promise<string>
|
decrypt: (pubkey: HexKey, content: string) => Promise<string>
|
||||||
|
@ -29,10 +29,12 @@ export type StateSnapshot = {
|
|||||||
received: number,
|
received: number,
|
||||||
send: number
|
send: number
|
||||||
},
|
},
|
||||||
info?: RelayInfo
|
info?: RelayInfo,
|
||||||
|
id: string
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class Connection {
|
export default class Connection {
|
||||||
|
Id: string;
|
||||||
Address: string;
|
Address: string;
|
||||||
Socket: WebSocket | null;
|
Socket: WebSocket | null;
|
||||||
Pending: Subscriptions[];
|
Pending: Subscriptions[];
|
||||||
@ -50,6 +52,7 @@ export default class Connection {
|
|||||||
EventsCallback: Map<u256, () => void>;
|
EventsCallback: Map<u256, () => void>;
|
||||||
|
|
||||||
constructor(addr: string, options: RelaySettings) {
|
constructor(addr: string, options: RelaySettings) {
|
||||||
|
this.Id = uuid();
|
||||||
this.Address = addr;
|
this.Address = addr;
|
||||||
this.Socket = null;
|
this.Socket = null;
|
||||||
this.Pending = [];
|
this.Pending = [];
|
||||||
@ -285,6 +288,7 @@ export default class Connection {
|
|||||||
this.CurrentState.avgLatency = this.Stats.Latency.length > 0 ? (this.Stats.Latency.reduce((acc, v) => acc + v, 0) / this.Stats.Latency.length) : 0;
|
this.CurrentState.avgLatency = this.Stats.Latency.length > 0 ? (this.Stats.Latency.reduce((acc, v) => acc + v, 0) / this.Stats.Latency.length) : 0;
|
||||||
this.CurrentState.disconnects = this.Stats.Disconnects;
|
this.CurrentState.disconnects = this.Stats.Disconnects;
|
||||||
this.CurrentState.info = this.Info;
|
this.CurrentState.info = this.Info;
|
||||||
|
this.CurrentState.id = this.Id;
|
||||||
this.Stats.Latency = this.Stats.Latency.slice(-20); // trim
|
this.Stats.Latency = this.Stats.Latency.slice(-20); // trim
|
||||||
this.HasStateChange = true;
|
this.HasStateChange = true;
|
||||||
this._NotifyState();
|
this._NotifyState();
|
||||||
|
@ -4,7 +4,7 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import * as secp from '@noble/secp256k1';
|
import * as secp from '@noble/secp256k1';
|
||||||
|
|
||||||
import { RootState } from "State/Store";
|
import { RootState } from "State/Store";
|
||||||
import { setPrivateKey, setPublicKey } from "State/Login";
|
import { setPrivateKey, setPublicKey, setRelays } from "State/Login";
|
||||||
import { EmailRegex } from "Const";
|
import { EmailRegex } from "Const";
|
||||||
import { bech32ToHex } from "Util";
|
import { bech32ToHex } from "Util";
|
||||||
import { HexKey } from "Nostr";
|
import { HexKey } from "Nostr";
|
||||||
@ -72,7 +72,12 @@ export default function LoginPage() {
|
|||||||
|
|
||||||
async function doNip07Login() {
|
async function doNip07Login() {
|
||||||
let pubKey = await window.nostr.getPublicKey();
|
let pubKey = await window.nostr.getPublicKey();
|
||||||
|
let relays = await window.nostr.getRelays();
|
||||||
dispatch(setPublicKey(pubKey));
|
dispatch(setPublicKey(pubKey));
|
||||||
|
dispatch(setRelays({
|
||||||
|
relays: relays,
|
||||||
|
createdAt: 1
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function altLogins() {
|
function altLogins() {
|
||||||
|
@ -30,7 +30,7 @@ export const SettingsRoutes: RouteObject[] = [
|
|||||||
element: <Relay />,
|
element: <Relay />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "relays/:addr",
|
path: "relays/:id",
|
||||||
element: <RelayInfo />
|
element: <RelayInfo />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -10,16 +10,16 @@ const RelayInfo = () => {
|
|||||||
const params = useParams();
|
const params = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const addr: string = `wss://${params.addr}`;
|
|
||||||
|
|
||||||
const con = System.Sockets.get(addr) ?? System.Sockets.get(`${addr}/`);
|
const conn = Array.from(System.Sockets.values()).find(a => a.Id === params.id);
|
||||||
const stats = useRelayState(con?.Address ?? addr);
|
console.debug(conn);
|
||||||
|
const stats = useRelayState(conn?.Address ?? "");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h3 className="pointer" onClick={() => navigate("/settings/relays")}>Relays</h3>
|
<h3 className="pointer" onClick={() => navigate("/settings/relays")}>Relays</h3>
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<h3>{stats?.info?.name ?? addr}</h3>
|
<h3>{stats?.info?.name}</h3>
|
||||||
<p>{stats?.info?.description}</p>
|
<p>{stats?.info?.description}</p>
|
||||||
|
|
||||||
{stats?.info?.pubkey && (<>
|
{stats?.info?.pubkey && (<>
|
||||||
@ -45,7 +45,7 @@ const RelayInfo = () => {
|
|||||||
</>)}
|
</>)}
|
||||||
<div className="flex mt10 f-end">
|
<div className="flex mt10 f-end">
|
||||||
<div className="btn error" onClick={() => {
|
<div className="btn error" onClick={() => {
|
||||||
dispatch(removeRelay(con!.Address));
|
dispatch(removeRelay(conn!.Address));
|
||||||
navigate("/settings/relays")
|
navigate("/settings/relays")
|
||||||
}}>Remove</div>
|
}}>Remove</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,6 +8,8 @@ const PrivateKeyItem = "secret";
|
|||||||
const PublicKeyItem = "pubkey";
|
const PublicKeyItem = "pubkey";
|
||||||
const NotificationsReadItem = "notifications-read";
|
const NotificationsReadItem = "notifications-read";
|
||||||
const UserPreferencesKey = "preferences";
|
const UserPreferencesKey = "preferences";
|
||||||
|
const RelayListKey = "last-relays";
|
||||||
|
const FollowList = "last-follows";
|
||||||
|
|
||||||
export interface UserPreferences {
|
export interface UserPreferences {
|
||||||
/**
|
/**
|
||||||
@ -138,8 +140,6 @@ const LoginSlice = createSlice({
|
|||||||
state.loggedOut = true;
|
state.loggedOut = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.relays = Object.fromEntries(DefaultRelays.entries());
|
|
||||||
|
|
||||||
// check pub key only
|
// check pub key only
|
||||||
let pubKey = window.localStorage.getItem(PublicKeyItem);
|
let pubKey = window.localStorage.getItem(PublicKeyItem);
|
||||||
if (pubKey && !state.privateKey) {
|
if (pubKey && !state.privateKey) {
|
||||||
@ -147,6 +147,18 @@ const LoginSlice = createSlice({
|
|||||||
state.loggedOut = false;
|
state.loggedOut = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let lastRelayList = window.localStorage.getItem(RelayListKey);
|
||||||
|
if (lastRelayList) {
|
||||||
|
state.relays = JSON.parse(lastRelayList);
|
||||||
|
} else if (state.loggedOut === true) {
|
||||||
|
state.relays = Object.fromEntries(DefaultRelays.entries());
|
||||||
|
}
|
||||||
|
|
||||||
|
let lastFollows = window.localStorage.getItem(FollowList);
|
||||||
|
if (lastFollows) {
|
||||||
|
state.follows = JSON.parse(lastFollows);
|
||||||
|
}
|
||||||
|
|
||||||
// notifications
|
// notifications
|
||||||
let readNotif = parseInt(window.localStorage.getItem(NotificationsReadItem) ?? "0");
|
let readNotif = parseInt(window.localStorage.getItem(NotificationsReadItem) ?? "0");
|
||||||
if (!isNaN(readNotif)) {
|
if (!isNaN(readNotif)) {
|
||||||
@ -187,10 +199,12 @@ const LoginSlice = createSlice({
|
|||||||
|
|
||||||
state.relays = Object.fromEntries(filtered.entries());
|
state.relays = Object.fromEntries(filtered.entries());
|
||||||
state.latestRelays = createdAt;
|
state.latestRelays = createdAt;
|
||||||
|
window.localStorage.setItem(RelayListKey, JSON.stringify(state.relays));
|
||||||
},
|
},
|
||||||
removeRelay: (state, action: PayloadAction<string>) => {
|
removeRelay: (state, action: PayloadAction<string>) => {
|
||||||
delete state.relays[action.payload];
|
delete state.relays[action.payload];
|
||||||
state.relays = { ...state.relays };
|
state.relays = { ...state.relays };
|
||||||
|
window.localStorage.setItem(RelayListKey, JSON.stringify(state.relays));
|
||||||
},
|
},
|
||||||
setFollows: (state, action: PayloadAction<string | string[]>) => {
|
setFollows: (state, action: PayloadAction<string | string[]>) => {
|
||||||
let existing = new Set(state.follows);
|
let existing = new Set(state.follows);
|
||||||
@ -205,6 +219,7 @@ const LoginSlice = createSlice({
|
|||||||
}
|
}
|
||||||
if (changes) {
|
if (changes) {
|
||||||
state.follows = Array.from(existing);
|
state.follows = Array.from(existing);
|
||||||
|
window.localStorage.setItem(FollowList, JSON.stringify(state.follows));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addNotifications: (state, action: PayloadAction<TaggedRawEvent | TaggedRawEvent[]>) => {
|
addNotifications: (state, action: PayloadAction<TaggedRawEvent | TaggedRawEvent[]>) => {
|
||||||
@ -249,10 +264,10 @@ const LoginSlice = createSlice({
|
|||||||
state.dmInteraction += 1;
|
state.dmInteraction += 1;
|
||||||
},
|
},
|
||||||
logout: (state) => {
|
logout: (state) => {
|
||||||
window.localStorage.clear();
|
|
||||||
Object.assign(state, InitState);
|
Object.assign(state, InitState);
|
||||||
state.loggedOut = true;
|
state.loggedOut = true;
|
||||||
state.relays = Object.fromEntries(DefaultRelays.entries());
|
state.relays = Object.fromEntries(DefaultRelays.entries());
|
||||||
|
window.localStorage.clear();
|
||||||
},
|
},
|
||||||
markNotificationsRead: (state) => {
|
markNotificationsRead: (state) => {
|
||||||
state.readNotifications = new Date().getTime();
|
state.readNotifications = new Date().getTime();
|
||||||
|
Reference in New Issue
Block a user