Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c720b430b7 | |||
| 934a8c3735 | |||
| ab1479f363 |
@@ -42,19 +42,28 @@ pub struct StringMessage {
|
|||||||
|
|
||||||
/// Create a new binary message with a user-specified `kind`.
|
/// Create a new binary message with a user-specified `kind`.
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn create_binary_message(kind: u8, payload: Vec<u8>) -> Vec<u8> {
|
pub fn create_binary_message(kind: u8, payload: Vec<u8>, headers: Option<String>) -> Vec<u8> {
|
||||||
create_binary_message_with_headers(kind, payload, "".to_string())
|
create_binary_message_with_headers(kind, payload, headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new message with a UTF-8 encoded string `payload` and a user-specified `kind`.
|
/// Create a new message with a UTF-8 encoded string `payload` and a user-specified `kind`.
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn create_binary_message_from_string(kind: u8, payload: String) -> Vec<u8> {
|
pub fn create_binary_message_from_string(
|
||||||
create_binary_message_with_headers(kind, payload.as_bytes().to_vec(), "".to_string())
|
kind: u8,
|
||||||
|
payload: String,
|
||||||
|
headers: Option<String>,
|
||||||
|
) -> Vec<u8> {
|
||||||
|
create_binary_message_with_headers(kind, payload.as_bytes().to_vec(), headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new binary message with a user-specified `kind`, and `headers` as a string.
|
/// Create a new binary message with a user-specified `kind`, and `headers` as a string.
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn create_binary_message_with_headers(kind: u8, payload: Vec<u8>, headers: String) -> Vec<u8> {
|
pub fn create_binary_message_with_headers(
|
||||||
|
kind: u8,
|
||||||
|
payload: Vec<u8>,
|
||||||
|
headers: Option<String>,
|
||||||
|
) -> Vec<u8> {
|
||||||
|
let headers = headers.unwrap_or_else(|| "".to_string());
|
||||||
let headers = headers.as_bytes().to_vec();
|
let headers = headers.as_bytes().to_vec();
|
||||||
let size = (headers.len() as u64).to_be_bytes().to_vec();
|
let size = (headers.len() as u64).to_be_bytes().to_vec();
|
||||||
vec![vec![kind], size, headers, payload].concat()
|
vec![vec![kind], size, headers, payload].concat()
|
||||||
@@ -169,7 +178,7 @@ mod tests {
|
|||||||
let message_as_bytes = create_binary_message_with_headers(
|
let message_as_bytes = create_binary_message_with_headers(
|
||||||
42u8,
|
42u8,
|
||||||
vec![0u8, 1u8, 2u8],
|
vec![0u8, 1u8, 2u8],
|
||||||
"test headers".to_string(),
|
Some("test headers".to_string()),
|
||||||
);
|
);
|
||||||
|
|
||||||
// calculate header size
|
// calculate header size
|
||||||
@@ -197,7 +206,7 @@ mod tests {
|
|||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn test_binary_with_empty_headers() {
|
fn test_binary_with_empty_headers() {
|
||||||
let message_as_bytes =
|
let message_as_bytes =
|
||||||
create_binary_message_with_headers(42u8, vec![0u8, 1u8, 2u8], "".to_string());
|
create_binary_message_with_headers(42u8, vec![0u8, 1u8, 2u8], Some("".to_string()));
|
||||||
|
|
||||||
let expected_size = 0;
|
let expected_size = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,12 @@ import {
|
|||||||
Chip,
|
Chip,
|
||||||
CircularProgress,
|
CircularProgress,
|
||||||
Container,
|
Container,
|
||||||
|
FormControlLabel,
|
||||||
|
FormGroup,
|
||||||
InputAdornment,
|
InputAdornment,
|
||||||
Link,
|
Link,
|
||||||
Stack,
|
Stack,
|
||||||
|
Switch,
|
||||||
TextField,
|
TextField,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Typography,
|
Typography,
|
||||||
@@ -20,6 +23,8 @@ import CallReceivedIcon from '@mui/icons-material/CallReceived';
|
|||||||
import PersonIcon from '@mui/icons-material/Person';
|
import PersonIcon from '@mui/icons-material/Person';
|
||||||
import PersonOffIcon from '@mui/icons-material/PersonOff';
|
import PersonOffIcon from '@mui/icons-material/PersonOff';
|
||||||
import ErrorIcon from '@mui/icons-material/Error';
|
import ErrorIcon from '@mui/icons-material/Error';
|
||||||
|
import VisibilityIcon from '@mui/icons-material/Visibility';
|
||||||
|
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
|
||||||
import { NymLogo } from '@nymproject/react/logo/NymLogo';
|
import { NymLogo } from '@nymproject/react/logo/NymLogo';
|
||||||
import { NymThemeProvider } from '@nymproject/mui-theme';
|
import { NymThemeProvider } from '@nymproject/mui-theme';
|
||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
@@ -28,9 +33,10 @@ import { DropzoneDialog } from 'react-mui-dropzone';
|
|||||||
import UploadFileIcon from '@mui/icons-material/UploadFile';
|
import UploadFileIcon from '@mui/icons-material/UploadFile';
|
||||||
import ArticleIcon from '@mui/icons-material/Article';
|
import ArticleIcon from '@mui/icons-material/Article';
|
||||||
import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile';
|
import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile';
|
||||||
|
import { Headers } from '@nymproject/sdk';
|
||||||
import { ThemeToggle } from './ThemeToggle';
|
import { ThemeToggle } from './ThemeToggle';
|
||||||
import { AppContextProvider, useAppContext } from './context';
|
import { AppContextProvider, useAppContext } from './context';
|
||||||
import { MixnetContextProvider, parseBinaryMessageHeaders, useMixnetContext } from './context/mixnet';
|
import { BinaryMessageHeaders, MixnetContextProvider, useMixnetContext } from './context/mixnet';
|
||||||
|
|
||||||
export const AppTheme: React.FC = ({ children }) => {
|
export const AppTheme: React.FC = ({ children }) => {
|
||||||
const { mode } = useAppContext();
|
const { mode } = useAppContext();
|
||||||
@@ -45,6 +51,7 @@ interface Log {
|
|||||||
fileDownloadUrl?: string;
|
fileDownloadUrl?: string;
|
||||||
filesize?: number;
|
filesize?: number;
|
||||||
timestamp: Date;
|
timestamp: Date;
|
||||||
|
headers?: Headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UploadState {
|
interface UploadState {
|
||||||
@@ -52,11 +59,48 @@ interface UploadState {
|
|||||||
files: File[];
|
files: File[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ClientAddress: React.FC<{ label?: string; tooltip?: string; address?: string }> = ({
|
||||||
|
label,
|
||||||
|
address,
|
||||||
|
tooltip,
|
||||||
|
}) => {
|
||||||
|
const copy = useClipboard();
|
||||||
|
|
||||||
|
if (!address) {
|
||||||
|
return <Chip label="Anonymous" icon={<VisibilityOffIcon />} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const addressShort = `${address.slice(0, 24)}...`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip arrow title={tooltip || ''}>
|
||||||
|
<Chip
|
||||||
|
clickable
|
||||||
|
label={
|
||||||
|
label ? (
|
||||||
|
<>
|
||||||
|
<strong>{label}</strong> {addressShort}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>{addressShort}</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onClick={() => {
|
||||||
|
if (address) {
|
||||||
|
copy.copy(address);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
icon={<ContentCopyIcon />}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const Content: React.FC = () => {
|
export const Content: React.FC = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { isReady, address, connect, events, sendTextMessage, sendBinaryMessage } = useMixnetContext();
|
const { isReady, address, connect, events, sendTextMessage, sendBinaryMessage } = useMixnetContext();
|
||||||
const copy = useClipboard();
|
|
||||||
|
|
||||||
|
const [revealSenderAddress, setRevealSenderAddress] = React.useState(false);
|
||||||
const [sendToSelf, setSendToSelf] = React.useState(false);
|
const [sendToSelf, setSendToSelf] = React.useState(false);
|
||||||
const [recipient, setRecipient] = React.useState<string>();
|
const [recipient, setRecipient] = React.useState<string>();
|
||||||
const handleRecipientChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
const handleRecipientChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
@@ -94,13 +138,8 @@ export const Content: React.FC = () => {
|
|||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (isReady) {
|
if (isReady) {
|
||||||
// // mixnet v1
|
const validatorApiUrl = 'https://validator.nymtech.net/api';
|
||||||
// const validatorApiUrl = 'https://validator.nymtech.net/api';
|
const preferredGatewayIdentityKey = 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM';
|
||||||
// const preferredGatewayIdentityKey = 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM';
|
|
||||||
|
|
||||||
// mixnet v2
|
|
||||||
const validatorApiUrl = 'https://qwerty-validator-api.qa.nymte.ch/api'; // "http://localhost:8081";
|
|
||||||
const preferredGatewayIdentityKey = undefined; // '36vfvEyBzo5cWEFbnP7fqgY39kFw9PQhvwzbispeNaxL';
|
|
||||||
|
|
||||||
connect({
|
connect({
|
||||||
clientId: 'Example Client',
|
clientId: 'Example Client',
|
||||||
@@ -117,6 +156,7 @@ export const Content: React.FC = () => {
|
|||||||
kind: 'rx',
|
kind: 'rx',
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
message: e.args.payload,
|
message: e.args.payload,
|
||||||
|
headers: e.args.headers,
|
||||||
});
|
});
|
||||||
setLogTrigger(Date.now());
|
setLogTrigger(Date.now());
|
||||||
});
|
});
|
||||||
@@ -142,8 +182,12 @@ export const Content: React.FC = () => {
|
|||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (events) {
|
if (events) {
|
||||||
const unsubcribe = events.subscribeToBinaryMessageReceivedEvent((e) => {
|
const unsubcribe = events.subscribeToBinaryMessageReceivedEvent((e) => {
|
||||||
// the headers will be JSON (see the mixnet context for how they are created), so parse them
|
if (!e.args.headers) {
|
||||||
const headers = parseBinaryMessageHeaders(e.args.headers);
|
console.error('Expected headers, got undefined 😢', e.args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers = e.args.headers as BinaryMessageHeaders;
|
||||||
|
|
||||||
const blob = new Blob([new Uint8Array(e.args.payload)], { type: headers.mimeType });
|
const blob = new Blob([new Uint8Array(e.args.payload)], { type: headers.mimeType });
|
||||||
log.current.push({
|
log.current.push({
|
||||||
@@ -152,6 +196,7 @@ export const Content: React.FC = () => {
|
|||||||
filename: headers.filename,
|
filename: headers.filename,
|
||||||
fileDownloadUrl: URL.createObjectURL(blob),
|
fileDownloadUrl: URL.createObjectURL(blob),
|
||||||
filesize: e.args.payload.length,
|
filesize: e.args.payload.length,
|
||||||
|
headers: e.args.headers,
|
||||||
});
|
});
|
||||||
setLogTrigger(Date.now());
|
setLogTrigger(Date.now());
|
||||||
});
|
});
|
||||||
@@ -184,7 +229,8 @@ export const Content: React.FC = () => {
|
|||||||
message,
|
message,
|
||||||
});
|
});
|
||||||
setLogTrigger(Date.now());
|
setLogTrigger(Date.now());
|
||||||
await sendTextMessage({ payload: message, recipient });
|
const senderAddress = revealSenderAddress ? address : undefined;
|
||||||
|
await sendTextMessage({ payload: message, recipient, headers: { senderAddress } });
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
files.map(async (f) => {
|
files.map(async (f) => {
|
||||||
@@ -200,7 +246,7 @@ export const Content: React.FC = () => {
|
|||||||
return await sendBinaryMessage({
|
return await sendBinaryMessage({
|
||||||
payload: new Uint8Array(buffer),
|
payload: new Uint8Array(buffer),
|
||||||
recipient,
|
recipient,
|
||||||
headers: { filename: f.name, mimeType: f.type },
|
headers: { filename: f.name, mimeType: f.type, senderAddress },
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
addErrorLog('Failed to send file', f.name);
|
addErrorLog('Failed to send file', f.name);
|
||||||
@@ -249,20 +295,7 @@ export const Content: React.FC = () => {
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Chip color="success" icon={<CheckCircleIcon />} label="Connected" variant="outlined" />
|
<Chip color="success" icon={<CheckCircleIcon />} label="Connected" variant="outlined" />
|
||||||
{address && (
|
<ClientAddress address={address} tooltip="Copy your client address to the clipboard" />
|
||||||
<Tooltip arrow title="Copy your client address to the clipboard">
|
|
||||||
<Chip
|
|
||||||
clickable
|
|
||||||
label={`${address.slice(0, 24)}...`}
|
|
||||||
onClick={() => {
|
|
||||||
if (address) {
|
|
||||||
copy.copy(address);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
icon={<ContentCopyIcon />}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -347,9 +380,34 @@ export const Content: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Button variant="contained" sx={{ width: 100 }} onClick={handleSend}>
|
<Stack direction="row" spacing={2}>
|
||||||
Send
|
<Button variant="contained" sx={{ width: 100 }} onClick={handleSend}>
|
||||||
</Button>
|
Send
|
||||||
|
</Button>
|
||||||
|
<FormGroup>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
color={revealSenderAddress ? 'warning' : 'default'}
|
||||||
|
onClick={() => setRevealSenderAddress((prevState) => !prevState)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={
|
||||||
|
revealSenderAddress ? (
|
||||||
|
<Stack direction="row" spacing={1}>
|
||||||
|
<VisibilityIcon color="warning" />
|
||||||
|
<Typography color={theme.palette.warning.main}>Reveal your address to the recipient</Typography>
|
||||||
|
</Stack>
|
||||||
|
) : (
|
||||||
|
<Stack direction="row" spacing={1}>
|
||||||
|
<VisibilityOffIcon />
|
||||||
|
<Typography>Hide your address from the recipient</Typography>
|
||||||
|
</Stack>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
@@ -398,6 +456,16 @@ export const Content: React.FC = () => {
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{item.kind === 'rx' &&
|
||||||
|
(item.headers?.senderAddress ? (
|
||||||
|
<ClientAddress
|
||||||
|
label="Sender"
|
||||||
|
tooltip="Click to copy the message sender's address"
|
||||||
|
address={item.headers?.senderAddress}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ClientAddress label="Sender" />
|
||||||
|
))}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { createNymMixnetClient, IWebWorkerEvents, NymClientConfig, NymMixnetClient } from '@nymproject/sdk';
|
import { createNymMixnetClient, IWebWorkerEvents, NymClientConfig, NymMixnetClient, Headers } from '@nymproject/sdk';
|
||||||
|
|
||||||
export interface BinaryMessageHeaders {
|
export interface BinaryMessageHeaders extends Headers {
|
||||||
filename: string;
|
filename: string;
|
||||||
mimeType: string;
|
mimeType: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const parseBinaryMessageHeaders = (headers: string): BinaryMessageHeaders =>
|
|
||||||
JSON.parse(headers) as BinaryMessageHeaders;
|
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
// data
|
// data
|
||||||
isReady: boolean;
|
isReady: boolean;
|
||||||
@@ -17,7 +14,7 @@ interface State {
|
|||||||
|
|
||||||
// methods
|
// methods
|
||||||
connect: (config: NymClientConfig) => Promise<void>;
|
connect: (config: NymClientConfig) => Promise<void>;
|
||||||
sendTextMessage: (args: { payload: string; recipient: string }) => Promise<void>;
|
sendTextMessage: (args: { payload: string; recipient: string; headers?: Headers }) => Promise<void>;
|
||||||
sendBinaryMessage: (args: { payload: Uint8Array; recipient: string; headers: BinaryMessageHeaders }) => Promise<void>;
|
sendBinaryMessage: (args: { payload: Uint8Array; recipient: string; headers: BinaryMessageHeaders }) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +59,7 @@ export const MixnetContextProvider: React.FC = ({ children }) => {
|
|||||||
await nym.current.client.start(config);
|
await nym.current.client.start(config);
|
||||||
};
|
};
|
||||||
|
|
||||||
const sendTextMessage = async (args: { payload: string; recipient: string }) => {
|
const sendTextMessage = async (args: { payload: string; recipient: string; headers?: Headers }) => {
|
||||||
if (!nym.current?.client) {
|
if (!nym.current?.client) {
|
||||||
console.error('Nym client has not initialised. Please wrap in useEffect on `isReady` prop of this context.');
|
console.error('Nym client has not initialised. Please wrap in useEffect on `isReady` prop of this context.');
|
||||||
return;
|
return;
|
||||||
@@ -76,8 +73,7 @@ export const MixnetContextProvider: React.FC = ({ children }) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// convert headers to JSON
|
// convert headers to JSON
|
||||||
const sendArgs = { ...args, headers: JSON.stringify(args.headers) };
|
await nym.current.client.sendBinaryMessage(args);
|
||||||
await nym.current.client.sendBinaryMessage(sendArgs);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const value = React.useMemo<State>(
|
const value = React.useMemo<State>(
|
||||||
|
|||||||
@@ -39,11 +39,16 @@ export interface NymClientConfig {
|
|||||||
debug?: wasm_bindgen.Debug;
|
debug?: wasm_bindgen.Debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Headers {
|
||||||
|
senderAddress?: string;
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IWebWorker {
|
export interface IWebWorker {
|
||||||
start: (config: NymClientConfig) => void;
|
start: (config: NymClientConfig) => void;
|
||||||
selfAddress: () => string | undefined;
|
selfAddress: () => string | undefined;
|
||||||
sendMessage: (args: { payload: string; recipient: string }) => void;
|
sendMessage: (args: { payload: string; recipient: string; headers?: Headers }) => void;
|
||||||
sendBinaryMessage: (args: { payload: Uint8Array; recipient: string; headers?: string }) => void;
|
sendBinaryMessage: (args: { payload: Uint8Array; recipient: string; headers?: Headers }) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum EventKinds {
|
export enum EventKinds {
|
||||||
@@ -72,6 +77,7 @@ export interface StringMessageReceivedEvent {
|
|||||||
args: {
|
args: {
|
||||||
kind: number;
|
kind: number;
|
||||||
payload: string;
|
payload: string;
|
||||||
|
headers?: Headers;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +86,7 @@ export interface BinaryMessageReceivedEvent {
|
|||||||
args: {
|
args: {
|
||||||
kind: number;
|
kind: number;
|
||||||
payload: Uint8Array;
|
payload: Uint8Array;
|
||||||
headers: string;
|
headers?: Headers;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import type {
|
|||||||
StringMessageReceivedEvent,
|
StringMessageReceivedEvent,
|
||||||
BinaryMessageReceivedEvent,
|
BinaryMessageReceivedEvent,
|
||||||
NymClientConfig,
|
NymClientConfig,
|
||||||
|
Headers,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { EventKinds } from './types';
|
import { EventKinds } from './types';
|
||||||
|
|
||||||
@@ -91,12 +92,13 @@ class ClientWrapper {
|
|||||||
this.client = await this.client.start();
|
this.client = await this.client.start();
|
||||||
};
|
};
|
||||||
|
|
||||||
sendMessage = async ({ payload, recipient }: { recipient: string; payload: string }) => {
|
sendMessage = async ({ payload, recipient, headers }: { recipient: string; payload: string; headers?: Headers }) => {
|
||||||
if (!this.client) {
|
if (!this.client) {
|
||||||
console.error('Client has not been initialised. Please call `init` first.');
|
console.error('Client has not been initialised. Please call `init` first.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const message = wasm_bindgen.create_binary_message_from_string(PAYLOAD_KIND_TEXT, payload);
|
const headersAsJsonString = headers ? JSON.stringify(headers) : '';
|
||||||
|
const message = wasm_bindgen.create_binary_message_from_string(PAYLOAD_KIND_TEXT, payload, headersAsJsonString);
|
||||||
this.client = await this.client.send_binary_message(message, recipient);
|
this.client = await this.client.send_binary_message(message, recipient);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -107,13 +109,14 @@ class ClientWrapper {
|
|||||||
}: {
|
}: {
|
||||||
recipient: string;
|
recipient: string;
|
||||||
payload: Uint8Array;
|
payload: Uint8Array;
|
||||||
headers?: string;
|
headers?: Headers;
|
||||||
}) => {
|
}) => {
|
||||||
if (!this.client) {
|
if (!this.client) {
|
||||||
console.error('Client has not been initialised. Please call `init` first.');
|
console.error('Client has not been initialised. Please call `init` first.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const message = wasm_bindgen.create_binary_message_with_headers(PAYLOAD_KIND_BINARY, payload, headers || '');
|
const headersAsJsonString = headers ? JSON.stringify(headers) : '';
|
||||||
|
const message = wasm_bindgen.create_binary_message_with_headers(PAYLOAD_KIND_BINARY, payload, headersAsJsonString);
|
||||||
this.client = await this.client.send_binary_message(message, recipient);
|
this.client = await this.client.send_binary_message(message, recipient);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -135,8 +138,7 @@ wasm_bindgen(wasmUrl)
|
|||||||
);
|
);
|
||||||
|
|
||||||
// set a different gatewayListener in order to avoid workaround ws over https error
|
// set a different gatewayListener in order to avoid workaround ws over https error
|
||||||
if (config.gatewayListener)
|
if (config.gatewayListener) gatewayEndpoint.gateway_listener = config.gatewayListener;
|
||||||
gatewayEndpoint.gateway_listener = config.gatewayListener;
|
|
||||||
|
|
||||||
// create the client, passing handlers for events
|
// create the client, passing handlers for events
|
||||||
wrapper.init(
|
wrapper.init(
|
||||||
@@ -153,19 +155,20 @@ wasm_bindgen(wasmUrl)
|
|||||||
async (message) => {
|
async (message) => {
|
||||||
try {
|
try {
|
||||||
const { kind, payload, headers } = await wasm_bindgen.parse_binary_message_with_headers(message);
|
const { kind, payload, headers } = await wasm_bindgen.parse_binary_message_with_headers(message);
|
||||||
|
const parsedHeaders = headers?.length > 0 ? JSON.parse(headers) : undefined;
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case PAYLOAD_KIND_TEXT: {
|
case PAYLOAD_KIND_TEXT: {
|
||||||
const stringMessage = await wasm_bindgen.parse_string_message_with_headers(message);
|
const stringMessage = await wasm_bindgen.parse_string_message_with_headers(message);
|
||||||
postMessageWithType<StringMessageReceivedEvent>({
|
postMessageWithType<StringMessageReceivedEvent>({
|
||||||
kind: EventKinds.StringMessageReceived,
|
kind: EventKinds.StringMessageReceived,
|
||||||
args: { kind, payload: stringMessage.payload },
|
args: { kind, payload: stringMessage.payload, headers: parsedHeaders },
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PAYLOAD_KIND_BINARY:
|
case PAYLOAD_KIND_BINARY:
|
||||||
postMessageWithType<BinaryMessageReceivedEvent>({
|
postMessageWithType<BinaryMessageReceivedEvent>({
|
||||||
kind: EventKinds.BinaryMessageReceived,
|
kind: EventKinds.BinaryMessageReceived,
|
||||||
args: { kind, payload, headers: headers || '' },
|
args: { kind, payload, headers: parsedHeaders },
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
Reference in New Issue
Block a user