mirror of
https://github.com/RoboSats/robosats.git
synced 2024-12-13 02:46:28 +00:00
Merge pull request #1614 from RoboSats/refactor-nostr-websockets
Refactor nostr websocket to be preared for mobile
This commit is contained in:
commit
02ac9e59dd
@ -127,10 +127,13 @@ const EncryptedSocketChat: React.FC<Props> = ({
|
||||
setConnection(connection);
|
||||
setConnected(true);
|
||||
|
||||
connection.send({
|
||||
message: robot?.pubKey,
|
||||
nick: userNick,
|
||||
});
|
||||
connection.send(
|
||||
JSON.stringify({
|
||||
type: 'message',
|
||||
message: robot?.pubKey,
|
||||
nick: userNick,
|
||||
}),
|
||||
);
|
||||
|
||||
connection.onMessage((message) => {
|
||||
setServerMessages((prev) => [...prev, message]);
|
||||
@ -173,10 +176,13 @@ const EncryptedSocketChat: React.FC<Props> = ({
|
||||
dataFromServer.message !== robot.pubKey
|
||||
) {
|
||||
setPeerPubKey(dataFromServer.message);
|
||||
connection.send({
|
||||
message: `-----SERVE HISTORY-----`,
|
||||
nick: userNick,
|
||||
});
|
||||
connection.send(
|
||||
JSON.stringify({
|
||||
type: 'message',
|
||||
message: `-----SERVE HISTORY-----`,
|
||||
nick: userNick,
|
||||
}),
|
||||
);
|
||||
}
|
||||
// If we receive an encrypted message
|
||||
else if (dataFromServer.message.substring(0, 27) === `-----BEGIN PGP MESSAGE-----`) {
|
||||
@ -242,10 +248,13 @@ const EncryptedSocketChat: React.FC<Props> = ({
|
||||
}
|
||||
// If input string contains '#' send unencrypted and unlogged message
|
||||
else if (connection != null && value.substring(0, 1) === '#') {
|
||||
connection.send({
|
||||
message: value,
|
||||
nick: userNick,
|
||||
});
|
||||
connection.send(
|
||||
JSON.stringify({
|
||||
type: 'message',
|
||||
message: value,
|
||||
nick: userNick,
|
||||
}),
|
||||
);
|
||||
setValue('');
|
||||
}
|
||||
|
||||
@ -257,10 +266,13 @@ const EncryptedSocketChat: React.FC<Props> = ({
|
||||
encryptMessage(value, robot.pubKey, peerPubKey, robot.encPrivKey, slot.token)
|
||||
.then((encryptedMessage) => {
|
||||
if (connection != null) {
|
||||
connection.send({
|
||||
message: String(encryptedMessage).split('\n').join('\\'),
|
||||
nick: userNick,
|
||||
});
|
||||
connection.send(
|
||||
JSON.stringify({
|
||||
type: 'message',
|
||||
message: String(encryptedMessage).split('\n').join('\\'),
|
||||
nick: userNick,
|
||||
}),
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { type Event } from 'nostr-tools';
|
||||
import { type Settings } from '../../models';
|
||||
import defaultFederation from '../../../static/federation.json';
|
||||
import { websocketClient, WebsocketConnection, WebsocketState } from '../Websocket';
|
||||
|
||||
interface RoboPoolEvents {
|
||||
onevent: (event: Event) => void;
|
||||
@ -39,63 +40,60 @@ class RoboPool {
|
||||
public relays: string[];
|
||||
public network: string;
|
||||
|
||||
public webSockets: WebSocket[] = [];
|
||||
public webSockets: Record<string, WebsocketConnection | null> = {};
|
||||
private readonly messageHandlers: Array<(url: string, event: MessageEvent) => void> = [];
|
||||
|
||||
connect = (): void => {
|
||||
this.relays.forEach((url) => {
|
||||
if (this.webSockets.find((w: WebSocket) => w.url === url)) return;
|
||||
this.relays.forEach((url: string) => {
|
||||
if (Object.keys(this.webSockets).find((wUrl) => wUrl === url)) return;
|
||||
|
||||
let ws: WebSocket;
|
||||
this.webSockets[url] = null;
|
||||
|
||||
const connect = (): void => {
|
||||
ws = new WebSocket(url);
|
||||
|
||||
// Add event listeners for the WebSocket
|
||||
ws.onopen = () => {
|
||||
const connectRelay = () => {
|
||||
websocketClient.open(url).then((connection) => {
|
||||
console.log(`Connected to ${url}`);
|
||||
};
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
this.messageHandlers.forEach((handler) => {
|
||||
handler(url, event);
|
||||
connection.onMessage((event) => {
|
||||
this.messageHandlers.forEach((handler) => {
|
||||
handler(url, event);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
ws.onerror = (error) => {
|
||||
console.error(`WebSocket error on ${url}:`, error);
|
||||
};
|
||||
connection.onError((error) => {
|
||||
console.error(`WebSocket error on ${url}:`, error);
|
||||
});
|
||||
|
||||
ws.onclose = () => {
|
||||
console.log(`Disconnected from ${url}. Attempting to reconnect...`);
|
||||
setTimeout(connect, 1000); // Reconnect after 1 second
|
||||
};
|
||||
connection.onClose(() => {
|
||||
console.log(`Disconnected from ${url}`);
|
||||
});
|
||||
|
||||
this.webSockets[url] = connection;
|
||||
});
|
||||
};
|
||||
|
||||
connect();
|
||||
this.webSockets.push(ws);
|
||||
connectRelay();
|
||||
});
|
||||
};
|
||||
|
||||
close = (): void => {
|
||||
this.webSockets.forEach((ws) => {
|
||||
ws.close();
|
||||
Object.values(this.webSockets).forEach((ws) => {
|
||||
ws?.close();
|
||||
});
|
||||
this.webSockets = {};
|
||||
};
|
||||
|
||||
sendMessage = (message: string): void => {
|
||||
const send = (index: number, message: string): void => {
|
||||
const ws = this.webSockets[index];
|
||||
const send = (url: string, message: string): void => {
|
||||
const ws = this.webSockets[url];
|
||||
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
if (!ws || ws.getReadyState() === WebsocketState.CONNECTING) {
|
||||
setTimeout(send, 500, url, message);
|
||||
} else if (ws.getReadyState() === WebsocketState.OPEN) {
|
||||
ws.send(message);
|
||||
} else if (ws.readyState === WebSocket.CONNECTING) {
|
||||
setTimeout(send, 500, index, message);
|
||||
}
|
||||
};
|
||||
|
||||
this.webSockets.forEach((_ws, index) => {
|
||||
send(index, message);
|
||||
Object.keys(this.webSockets).forEach((url) => {
|
||||
send(url, message);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1,44 +0,0 @@
|
||||
import ReconnectingWebSocket from 'reconnecting-websocket';
|
||||
import { type WebsocketConnection } from '..';
|
||||
|
||||
class WebsocketConnectionWeb implements WebsocketConnection {
|
||||
constructor(path: string) {
|
||||
this.rws = new ReconnectingWebSocket(path, [], {
|
||||
WebSocket,
|
||||
minReconnectionDelay: 15000,
|
||||
connectionTimeout: 15000,
|
||||
reconnectionDelayGrowFactor: 2,
|
||||
maxRetries: 4,
|
||||
maxReconnectionDelay: 1000000,
|
||||
});
|
||||
}
|
||||
|
||||
public rws: ReconnectingWebSocket;
|
||||
|
||||
public send: (message: object) => void = (message: object) => {
|
||||
this.rws.send(
|
||||
JSON.stringify({
|
||||
type: 'message',
|
||||
...message,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
public close: () => void = () => {
|
||||
this.rws.close();
|
||||
};
|
||||
|
||||
public onMessage: (event: (message: any) => void) => void = (event) => {
|
||||
this.rws.addEventListener('message', event);
|
||||
};
|
||||
|
||||
public onClose: (event: () => void) => void = (event) => {
|
||||
this.rws.addEventListener('close', event);
|
||||
};
|
||||
|
||||
public onError: (event: () => void) => void = (event) => {
|
||||
this.rws.addEventListener('error', event);
|
||||
};
|
||||
}
|
||||
|
||||
export default WebsocketConnectionWeb;
|
@ -1,5 +1,42 @@
|
||||
import ReconnectingWebSocket from 'reconnecting-websocket';
|
||||
import { type WebsocketClient, type WebsocketConnection } from '..';
|
||||
import WebsocketConnectionWeb from '../WebsocketConnectionWeb';
|
||||
|
||||
class WebsocketConnectionWeb implements WebsocketConnection {
|
||||
constructor(path: string) {
|
||||
this.rws = new ReconnectingWebSocket(path, [], {
|
||||
WebSocket,
|
||||
minReconnectionDelay: 15000,
|
||||
connectionTimeout: 15000,
|
||||
reconnectionDelayGrowFactor: 2,
|
||||
maxRetries: 4,
|
||||
maxReconnectionDelay: 1000000,
|
||||
});
|
||||
}
|
||||
|
||||
public rws: ReconnectingWebSocket;
|
||||
|
||||
public send: (message: string) => void = (message: string) => {
|
||||
this.rws.send(message);
|
||||
};
|
||||
|
||||
public close: () => void = () => {
|
||||
this.rws.close();
|
||||
};
|
||||
|
||||
public onMessage: (event: (message: any) => void) => void = (event) => {
|
||||
this.rws.addEventListener('message', event);
|
||||
};
|
||||
|
||||
public onClose: (event: () => void) => void = (event) => {
|
||||
this.rws.addEventListener('close', event);
|
||||
};
|
||||
|
||||
public onError: (event: (error: any) => void) => void = (event) => {
|
||||
this.rws.addEventListener('error', event);
|
||||
};
|
||||
|
||||
public getReadyState: () => number = () => this.rws.readyState;
|
||||
}
|
||||
|
||||
class WebsocketWebClient implements WebsocketClient {
|
||||
public open: (path: string) => Promise<WebsocketConnection> = async (path) => {
|
||||
|
@ -1,11 +1,19 @@
|
||||
import WebsocketWebClient from './WebsocketWebClient';
|
||||
|
||||
export const WebsocketState = {
|
||||
CONNECTING: 0,
|
||||
OPEN: 1,
|
||||
CLOSING: 2,
|
||||
CLOSED: 3,
|
||||
} as const;
|
||||
|
||||
export interface WebsocketConnection {
|
||||
send: (message: object) => void;
|
||||
send: (message: string) => void;
|
||||
onMessage: (event: (message: any) => void) => void;
|
||||
onClose: (event: () => void) => void;
|
||||
onError: (event: () => void) => void;
|
||||
onError: (event: (error: any) => void) => void;
|
||||
close: () => void;
|
||||
getReadyState: () => number;
|
||||
}
|
||||
|
||||
export interface WebsocketClient {
|
||||
|
Loading…
Reference in New Issue
Block a user