mirror of
https://github.com/cinnyapp/cinny.git
synced 2025-11-04 22:40:29 +03:00
copy over utils form EW
Signed-off-by: Timo K <toger5@hotmail.de>
This commit is contained in:
parent
98c90b23af
commit
bbe53d6d6f
1 changed files with 157 additions and 0 deletions
157
src/app/components/element-call/utils.ts
Normal file
157
src/app/components/element-call/utils.ts
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
import { logger } from 'matrix-js-sdk/lib/logger';
|
||||
|
||||
import { EventType } from 'matrix-js-sdk';
|
||||
import { EventDirection, MatrixCapabilities, WidgetEventCapability } from 'matrix-widget-api';
|
||||
import EventEmitter from 'events';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
function getCredentials() {
|
||||
const accessToken = localStorage.getItem('mx_access_token');
|
||||
const userId = localStorage.getItem('mx_user_id');
|
||||
const deviceId = localStorage.getItem('mx_device_id');
|
||||
return [accessToken, userId, deviceId];
|
||||
}
|
||||
|
||||
export async function downloadFromUrlToFile(url: string, filename?: string): Promise<File> {
|
||||
const [accessToken] = getCredentials();
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
body: 'blob',
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
const file = new File([await response.blob()], filename || 'file', {
|
||||
type: response.type,
|
||||
});
|
||||
return file;
|
||||
} catch (error) {
|
||||
logger.error('Error downloading file', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
export type Diff<T> = { added: T[]; removed: T[] };
|
||||
|
||||
/**
|
||||
* Performs a diff on two arrays. The result is what is different with the
|
||||
* first array (`added` in the returned object means objects in B that aren't
|
||||
* in A). Shallow comparisons are used to perform the diff.
|
||||
* @param a The first array. Must be defined.
|
||||
* @param b The second array. Must be defined.
|
||||
* @returns The diff between the arrays.
|
||||
*/
|
||||
export function arrayDiff<T>(a: T[], b: T[]): Diff<T> {
|
||||
return {
|
||||
added: b.filter((i) => !a.includes(i)),
|
||||
removed: a.filter((i) => !b.includes(i)),
|
||||
};
|
||||
}
|
||||
|
||||
export default function iterableDiff<T>(
|
||||
a: Iterable<T>,
|
||||
b: Iterable<T>
|
||||
): { added: Iterable<T>; removed: Iterable<T> } {
|
||||
return arrayDiff(Array.from(a), Array.from(b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones an array as fast as possible, retaining references of the array's values.
|
||||
* @param a The array to clone. Must be defined.
|
||||
* @returns A copy of the array.
|
||||
*/
|
||||
export function arrayFastClone<T>(a: T[]): T[] {
|
||||
return a.slice(0, a.length);
|
||||
}
|
||||
|
||||
export function elementCallCapabilities(
|
||||
inRoomId: string,
|
||||
clientUserId: string,
|
||||
clientDeviceId?: string
|
||||
): Set<string> {
|
||||
const allowedCapabilities = new Set<string>();
|
||||
|
||||
// This is a trusted Element Call widget that we control
|
||||
const addCapability = (type: string, state: boolean, dir: EventDirection, stateKey?: string) =>
|
||||
allowedCapabilities.add(
|
||||
state
|
||||
? WidgetEventCapability.forStateEvent(dir, type, stateKey).raw
|
||||
: WidgetEventCapability.forRoomEvent(dir, type).raw
|
||||
);
|
||||
const addToDeviceCapability = (eventType: string, dir: EventDirection) =>
|
||||
allowedCapabilities.add(WidgetEventCapability.forToDeviceEvent(dir, eventType).raw);
|
||||
const recvState = (eventType: string, stateKey?: string) =>
|
||||
addCapability(eventType, true, EventDirection.Receive, stateKey);
|
||||
const sendState = (eventType: string, stateKey?: string) =>
|
||||
addCapability(eventType, true, EventDirection.Send, stateKey);
|
||||
const sendRecvToDevice = (eventType: string) => {
|
||||
addToDeviceCapability(eventType, EventDirection.Receive);
|
||||
addToDeviceCapability(eventType, EventDirection.Send);
|
||||
};
|
||||
const recvRoom = (eventType: string) => addCapability(eventType, false, EventDirection.Receive);
|
||||
const sendRoom = (eventType: string) => addCapability(eventType, false, EventDirection.Send);
|
||||
const sendRecvRoom = (eventType: string) => {
|
||||
recvRoom(eventType);
|
||||
sendRoom(eventType);
|
||||
};
|
||||
|
||||
allowedCapabilities.add(MatrixCapabilities.AlwaysOnScreen);
|
||||
allowedCapabilities.add(MatrixCapabilities.MSC3846TurnServers);
|
||||
allowedCapabilities.add(`org.matrix.msc2762.timeline:${inRoomId}`);
|
||||
allowedCapabilities.add(MatrixCapabilities.MSC4157SendDelayedEvent);
|
||||
allowedCapabilities.add(MatrixCapabilities.MSC4157UpdateDelayedEvent);
|
||||
recvState(EventType.RoomMember);
|
||||
recvState('org.matrix.msc3401.call');
|
||||
recvState(EventType.RoomEncryption);
|
||||
recvState(EventType.RoomName);
|
||||
// For the legacy membership type
|
||||
sendState('org.matrix.msc3401.call.member', clientUserId);
|
||||
// For the session membership type compliant with MSC4143
|
||||
sendState('org.matrix.msc3401.call.member', `_${clientUserId}_${clientDeviceId}_m.call`);
|
||||
sendState('org.matrix.msc3401.call.member', `${clientUserId}_${clientDeviceId}_m.call`);
|
||||
sendState('org.matrix.msc3401.call.member', `_${clientUserId}_${clientDeviceId}`);
|
||||
sendState('org.matrix.msc3401.call.member', `${clientUserId}_${clientDeviceId}`);
|
||||
recvState('org.matrix.msc3401.call.member');
|
||||
// for determining auth rules specific to the room version
|
||||
recvState(EventType.RoomCreate);
|
||||
|
||||
sendRoom('org.matrix.msc4075.rtc.notification');
|
||||
sendRecvRoom('io.element.call.encryption_keys');
|
||||
sendRecvRoom('org.matrix.rageshake_request');
|
||||
sendRecvRoom(EventType.Reaction);
|
||||
sendRecvRoom(EventType.RoomRedaction);
|
||||
sendRecvRoom('io.element.call.reaction');
|
||||
sendRecvRoom('org.matrix.msc4310.rtc.decline');
|
||||
|
||||
sendRecvToDevice(EventType.CallInvite);
|
||||
sendRecvToDevice(EventType.CallCandidates);
|
||||
sendRecvToDevice(EventType.CallAnswer);
|
||||
sendRecvToDevice(EventType.CallHangup);
|
||||
sendRecvToDevice(EventType.CallReject);
|
||||
sendRecvToDevice(EventType.CallSelectAnswer);
|
||||
sendRecvToDevice(EventType.CallNegotiate);
|
||||
sendRecvToDevice(EventType.CallSDPStreamMetadataChanged);
|
||||
sendRecvToDevice(EventType.CallSDPStreamMetadataChangedPrefix);
|
||||
sendRecvToDevice(EventType.CallReplaces);
|
||||
sendRecvToDevice(EventType.CallEncryptionKeysPrefix);
|
||||
|
||||
return allowedCapabilities;
|
||||
}
|
||||
|
||||
// Shortcut for registering a listener on an EventTarget
|
||||
// Copied from element-web
|
||||
export function useEventEmitter<T>(
|
||||
emitter: EventEmitter | null | undefined,
|
||||
eventType: string,
|
||||
listener: (event: T) => void
|
||||
): void {
|
||||
useEffect((): (() => void) => {
|
||||
if (emitter) {
|
||||
emitter.on(eventType, listener);
|
||||
return (): void => {
|
||||
emitter.off(eventType, listener);
|
||||
};
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
return () => {};
|
||||
}, [emitter, eventType, listener]);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue