Compare commits

...

9 Commits

Author SHA1 Message Date
Saúl Ibarra Corretgé
7a677afa06 fix(copyText) use a helper library
It does a more elaborate way of textarea copying, hopefully it's more reliable.
2021-03-04 16:28:33 +01:00
Hristo Terezov
5172d4f605 fix(live-stream-section): Use await for copyText 2021-03-03 16:27:42 -06:00
Hristo Terezov
5ad733d2c0 fix(copyText): in iframe for chrome<85 2021-03-03 16:18:38 -06:00
damencho
287b937d7a fix: Init availableDevices. 2021-02-26 19:12:11 -06:00
damencho
f1ed83eb65 fix: Device selection not being available 2021-02-26 15:39:18 -06:00
Hristo Terezov
88728ae9d2 feat(external_api): allow clipboard-write 2021-02-26 15:36:44 -06:00
Calinteodor
697f22b674 fix: improved copy text helper function (#8677) 2021-02-24 15:17:39 -06:00
damencho
a35f133949 fix: Save guards _features to be always empty and never undefined.
Updates lib-jitsi-meet with just that change.
2021-02-12 15:20:53 -06:00
hmuresan
baa64a8949 feat (external_api) add command for kick participant 2021-02-12 15:16:48 -06:00
8 changed files with 57 additions and 37 deletions

View File

@@ -14,7 +14,7 @@ import {
} from '../../react/features/base/conference';
import { parseJWTFromURLParams } from '../../react/features/base/jwt';
import JitsiMeetJS, { JitsiRecordingConstants } from '../../react/features/base/lib-jitsi-meet';
import { pinParticipant, getParticipantById } from '../../react/features/base/participants';
import { pinParticipant, getParticipantById, kickParticipant } from '../../react/features/base/participants';
import { setPrivateMessageRecipient } from '../../react/features/chat/actions';
import {
processExternalDeviceRequest
@@ -349,6 +349,9 @@ function initCommands() {
},
'cancel-private-chat': () => {
APP.store.dispatch(setPrivateMessageRecipient());
},
'kick-participant': participantId => {
APP.store.dispatch(kickParticipant(participantId));
}
};
transport.on('event', ({ data, name }) => {

View File

@@ -35,6 +35,7 @@ const commands = {
toggleLobby: 'toggle-lobby',
hangup: 'video-hangup',
intiatePrivateChat: 'initiate-private-chat',
kickParticipant: 'kick-participant',
muteEveryone: 'mute-everyone',
password: 'password',
pinParticipant: 'pin-participant',
@@ -319,7 +320,7 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
const frameName = `jitsiConferenceFrame${id}`;
this._frame = document.createElement('iframe');
this._frame.allow = 'camera; microphone; display-capture';
this._frame.allow = 'camera; microphone; display-capture; autoplay; clipboard-write';
this._frame.src = this._url;
this._frame.name = frameName;
this._frame.id = frameName;
@@ -753,6 +754,18 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
return getCurrentDevices(this._transport);
}
/**
* Returns the current livestream url.
*
* @returns {Promise} - Resolves with the current livestream URL if exists, with
* undefined if not and rejects on failure.
*/
getLivestreamUrl() {
return this._transport.sendRequest({
name: 'get-livestream-url'
});
}
/**
* Returns the conference participants information.
*

9
package-lock.json generated
View File

@@ -5947,6 +5947,11 @@
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
"integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="
},
"clipboard-copy": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/clipboard-copy/-/clipboard-copy-4.0.1.tgz",
"integrity": "sha512-wOlqdqziE/NNTUJsfSgXmBMIrYmfd5V0HCGsR8uAKHcg+h9NENWINcfRjtWGU77wDHC8B8ijV4hMTGYbrKovng=="
},
"cliui": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
@@ -10343,8 +10348,8 @@
}
},
"lib-jitsi-meet": {
"version": "github:jitsi/lib-jitsi-meet#9fdde46694d1c4bc8b7f051cc8d50e0df29ffd07",
"from": "github:jitsi/lib-jitsi-meet#9fdde46694d1c4bc8b7f051cc8d50e0df29ffd07",
"version": "github:jitsi/lib-jitsi-meet#9f53c439c0071f42e4e6b0099be2f177dc65858d",
"from": "github:jitsi/lib-jitsi-meet#9f53c439c0071f42e4e6b0099be2f177dc65858d",
"requires": {
"@jitsi/js-utils": "1.0.2",
"@jitsi/sdp-interop": "1.0.3",

View File

@@ -43,6 +43,7 @@
"amplitude-js": "7.3.3",
"base64-js": "1.3.1",
"bc-css-flags": "3.0.0",
"clipboard-copy": "4.0.1",
"dropbox": "4.0.9",
"focus-visible": "5.1.0",
"i18n-iso-countries": "3.7.8",
@@ -56,7 +57,7 @@
"jquery-i18next": "1.2.1",
"js-md5": "0.6.1",
"jwt-decode": "2.2.0",
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#9fdde46694d1c4bc8b7f051cc8d50e0df29ffd07",
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#9f53c439c0071f42e4e6b0099be2f177dc65858d",
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
"lodash": "4.17.19",
"moment": "2.19.4",

View File

@@ -2,9 +2,9 @@
import React, { useState } from 'react';
import { translate } from '../../base/i18n';
import { Icon, IconCheck, IconCopy } from '../../base/icons';
import { copyText } from '../../base/util';
import { translate } from '../i18n';
import { copyText } from '../util';
type Props = {
@@ -49,9 +49,12 @@ function CopyButton({ className, displayedText, textToCopy, textOnHover, textOnC
*
* @returns {void}
*/
function onClick() {
async function onClick() {
setIsHovered(false);
if (copyText(textToCopy)) {
const isCopied = await copyText(textToCopy);
if (isCopied) {
setIsClicked(true);
setTimeout(() => {

View File

@@ -74,8 +74,8 @@ class CopyMeetingUrl extends Component<Props, State> {
*
* @returns {void}
*/
_copyUrl() {
const success = copyText(this.props.url);
async _copyUrl() {
const success = await copyText(this.props.url);
if (success) {
this._showLinkCopied();
@@ -151,12 +151,13 @@ class CopyMeetingUrl extends Component<Props, State> {
* @private
* @returns {void}
*/
_copyUrlAutomatically() {
navigator.clipboard.writeText(this.props.url)
.then(() => {
this._showLinkCopied();
window.setTimeout(this._hideLinkCopied, COPY_TIMEOUT);
});
async _copyUrlAutomatically() {
const isCopied = await copyText(this.props.url);
if (isCopied) {
this._showLinkCopied();
window.setTimeout(this._hideLinkCopied, COPY_TIMEOUT);
}
}
/**

View File

@@ -1,5 +1,7 @@
// @flow
import clipboardCopy from 'clipboard-copy';
/**
* A helper function that behaves similar to Object.assign, but only reassigns a
* property in target if it's defined in source.
@@ -29,27 +31,16 @@ export function assignIfDefined(target: Object, source: Object) {
* Returns true if the action succeeds.
*
* @param {string} textToCopy - Text to be copied.
* @returns {boolean}
* @returns {Promise<boolean>}
*/
export function copyText(textToCopy: string) {
const fakeTextArea = document.createElement('textarea');
let result;
// $FlowFixMe
document.body.appendChild(fakeTextArea);
fakeTextArea.value = textToCopy;
fakeTextArea.select();
export async function copyText(textToCopy: string) {
try {
result = document.execCommand('copy');
} catch (err) {
result = false;
await clipboardCopy(textToCopy);
return true;
} catch (e) {
return false;
}
// $FlowFixMe
document.body.removeChild(fakeTextArea);
return result;
}
/**

View File

@@ -34,9 +34,12 @@ function LiveStreamSection({ liveStreamViewURL, t }: Props) {
*
* @returns {void}
*/
function onClick() {
async function onClick() {
setIsHovered(false);
if (copyText(liveStreamViewURL)) {
const isCopied = await copyText(liveStreamViewURL);
if (isCopied) {
setIsClicked(true);
setTimeout(() => {