jiti-meet/react/features/virtual-background/functions.js

143 lines
4.5 KiB
JavaScript
Raw Normal View History

2019-07-03 15:38:25 +00:00
// @flow
import { JitsiTrackEvents } from '../base/lib-jitsi-meet';
import { updateSettings } from '../base/settings';
import { toggleBackgroundEffect } from './actions';
let filterSupport;
/**
* Checks context filter support.
*
* @returns {boolean} True if the filter is supported and false if the filter is not supported by the browser.
*/
export function checkBlurSupport() {
if (typeof filterSupport === 'undefined') {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
filterSupport = typeof ctx.filter !== 'undefined';
canvas.remove();
}
return filterSupport;
}
/**
* Convert blob to base64.
*
* @param {Blob} blob - The link to add info with.
* @returns {Promise<string>}
*/
export const blobToData = (blob: Blob): Promise<string> =>
new Promise(resolve => {
const reader = new FileReader();
2022-01-07 10:54:42 +00:00
reader.onloadend = () => resolve(reader.result?.toString());
reader.readAsDataURL(blob);
});
/**
* Convert blob to base64.
*
* @param {string} url - The image url.
* @returns {Object} - Returns the converted blob to base64.
*/
export const toDataURL = async (url: string) => {
const response = await fetch(url);
const blob = await response.blob();
const resData = await blobToData(blob);
return resData;
};
/**
* Resize image and adjust original aspect ratio.
*
* @param {Object} base64image - Base64 image extraction.
* @param {number} width - Value for resizing the image width.
* @param {number} height - Value for resizing the image height.
* @returns {Promise<string>}
*
*/
export function resizeImage(base64image: any, width: number = 1920, height: number = 1080): Promise<string> {
// In order to work on Firefox browser we need to handle the asynchronous nature of image loading; We need to use
// a promise mechanism. The reason why it 'works' without this mechanism in Chrome is actually 'by accident' because
// the image happens to be in the cache and the browser is able to deliver the uncompressed/decoded image
// before using the image in the drawImage call.
return new Promise(resolve => {
const img = document.createElement('img');
img.onload = function() {
// Create an off-screen canvas.
const canvas = document.createElement('canvas');
// Set its dimension to target size.
const context = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
// Draw source image into the off-screen canvas.
// TODO: keep aspect ratio and implement object-fit: cover.
context.drawImage(img, 0, 0, width, height);
// Encode image to data-uri with base64 version of compressed image.
resolve(canvas.toDataURL('image/jpeg', 0.5));
};
img.src = base64image;
});
}
/**
* Check if the local desktop track was stopped and apply none option on virtual background.
*
* @param {Function} dispatch - The Redux dispatch function.
* @param {Object} desktopTrack - The desktop track that needs to be checked if it was stopped.
* @param {Object} currentLocalTrack - The current local track where we apply none virtual
* background option if the desktop track was stopped.
* @returns {Promise}
*/
export function localTrackStopped(dispatch: Function, desktopTrack: Object, currentLocalTrack: Object) {
const noneOptions = {
enabled: false,
backgroundType: 'none',
selectedThumbnail: 'none',
backgroundEffectEnabled: false
};
desktopTrack
&& desktopTrack.on(JitsiTrackEvents.LOCAL_TRACK_STOPPED, () => {
dispatch(toggleBackgroundEffect(noneOptions, currentLocalTrack));
// Set x scale to default value.
dispatch(updateSettings({
localFlipX: true
}));
});
}
/**
* Creating a wrapper for promises on a specific time interval.
*
* @param {number} milliseconds - The number of milliseconds to wait the specified
* {@code promise} to settle before automatically rejecting the returned
* {@code Promise}.
* @param {Promise} promise - The {@code Promise} for which automatic rejecting
* after the specified timeout is to be implemented.
* @returns {Promise}
*/
export function timeout(milliseconds: number, promise: Promise<*>): Promise<Object> {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('408'));
return;
}, milliseconds);
promise.then(resolve, reject);
});
}