mirror of
				https://github.com/cinnyapp/cinny.git
				synced 2025-11-04 06:20:28 +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