Allow Element Call to be started without audio / video interface (#924)
* config: add feature in `config.json` * groupCall: adjust connection state in feed if allowCallWithoutVideoAndAudio * matrix-js-sdk: update version for allowCallWithoutVideoAndAudio - I modified the SDK so that mute unmute work without media and check device permission inside the SDK - allowCallWithoutVideoAndAudio is only checked at one point outside the SDK * docu: add join group call without media docu in READMe --------- Co-authored-by: Robin Townsend <robin@robin.town> Co-authored-by: Šimon Brandner <simon.bra.ag@gmail.com>
This commit is contained in:
parent
0423a494c4
commit
29e41c7227
7 changed files with 89 additions and 38 deletions
|
|
@ -44,6 +44,14 @@ export interface ConfigOptions {
|
|||
server_name: string;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Allow to join a group calls without audio and video.
|
||||
* TEMPORARY: Is a feature that's not proved and experimental
|
||||
*/
|
||||
features?: {
|
||||
feature_group_calls_without_video_and_audio: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
// Overrides members from ConfigOptions that are always provided by the
|
||||
|
|
|
|||
|
|
@ -92,10 +92,14 @@ export async function initClient(
|
|||
indexedDB = window.indexedDB;
|
||||
} catch (e) {}
|
||||
|
||||
const storeOpts = {} as ICreateClientOpts;
|
||||
const baseOpts = {
|
||||
fallbackICEServerAllowed: fallbackICEServerAllowed,
|
||||
isVoipWithNoMediaAllowed:
|
||||
Config.get().features?.feature_group_calls_without_video_and_audio,
|
||||
} as ICreateClientOpts;
|
||||
|
||||
if (indexedDB && localStorage) {
|
||||
storeOpts.store = new IndexedDBStore({
|
||||
baseOpts.store = new IndexedDBStore({
|
||||
indexedDB: window.indexedDB,
|
||||
localStorage,
|
||||
dbName: SYNC_STORE_NAME,
|
||||
|
|
@ -107,7 +111,7 @@ export async function initClient(
|
|||
: () => new IndexedDBWorker(),
|
||||
});
|
||||
} else if (localStorage) {
|
||||
storeOpts.store = new MemoryStore({ localStorage });
|
||||
baseOpts.store = new MemoryStore({ localStorage });
|
||||
}
|
||||
|
||||
// Check whether we have crypto data store. If we are restoring a session
|
||||
|
|
@ -139,14 +143,14 @@ export async function initClient(
|
|||
}
|
||||
|
||||
if (indexedDB) {
|
||||
storeOpts.cryptoStore = new IndexedDBCryptoStore(
|
||||
baseOpts.cryptoStore = new IndexedDBCryptoStore(
|
||||
indexedDB,
|
||||
CRYPTO_STORE_NAME
|
||||
);
|
||||
} else if (localStorage) {
|
||||
storeOpts.cryptoStore = new LocalStorageCryptoStore(localStorage);
|
||||
baseOpts.cryptoStore = new LocalStorageCryptoStore(localStorage);
|
||||
} else {
|
||||
storeOpts.cryptoStore = new MemoryCryptoStore();
|
||||
baseOpts.cryptoStore = new MemoryCryptoStore();
|
||||
}
|
||||
|
||||
// XXX: we read from the URL params in RoomPage too:
|
||||
|
|
@ -160,7 +164,7 @@ export async function initClient(
|
|||
}
|
||||
|
||||
const client = createClient({
|
||||
...storeOpts,
|
||||
...baseOpts,
|
||||
...clientOptions,
|
||||
useAuthorizationHeader: true,
|
||||
// Use a relatively low timeout for API calls: this is a realtime app
|
||||
|
|
|
|||
|
|
@ -372,27 +372,36 @@ export function InCallView({
|
|||
|
||||
if (noControls) {
|
||||
footer = null;
|
||||
} else if (reducedControls) {
|
||||
footer = (
|
||||
<div className={styles.footer}>
|
||||
<MicButton muted={microphoneMuted} onPress={toggleMicrophoneMuted} />
|
||||
<VideoButton muted={localVideoMuted} onPress={toggleLocalVideoMuted} />
|
||||
<HangupButton onPress={onLeave} />
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
footer = (
|
||||
<div className={styles.footer}>
|
||||
<MicButton muted={microphoneMuted} onPress={toggleMicrophoneMuted} />
|
||||
<VideoButton muted={localVideoMuted} onPress={toggleLocalVideoMuted} />
|
||||
{canScreenshare && !hideScreensharing && !isSafari && (
|
||||
const buttons: JSX.Element[] = [];
|
||||
|
||||
buttons.push(
|
||||
<MicButton
|
||||
key="1"
|
||||
muted={microphoneMuted}
|
||||
onPress={toggleMicrophoneMuted}
|
||||
/>,
|
||||
<VideoButton
|
||||
key="2"
|
||||
muted={localVideoMuted}
|
||||
onPress={toggleLocalVideoMuted}
|
||||
/>
|
||||
);
|
||||
|
||||
if (!reducedControls) {
|
||||
if (canScreenshare && !hideScreensharing && !isSafari) {
|
||||
buttons.push(
|
||||
<ScreenshareButton
|
||||
key="3"
|
||||
enabled={isScreensharing}
|
||||
onPress={toggleScreensharing}
|
||||
/>
|
||||
)}
|
||||
{!maximisedParticipant && (
|
||||
);
|
||||
}
|
||||
if (!maximisedParticipant) {
|
||||
buttons.push(
|
||||
<OverflowMenu
|
||||
key="4"
|
||||
inCall
|
||||
roomIdOrAlias={roomIdOrAlias}
|
||||
groupCall={groupCall}
|
||||
|
|
@ -400,10 +409,12 @@ export function InCallView({
|
|||
feedbackModalState={feedbackModalState}
|
||||
feedbackModalProps={feedbackModalProps}
|
||||
/>
|
||||
)}
|
||||
<HangupButton onPress={onLeave} />
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
buttons.push(<HangupButton key="6" onPress={onLeave} />);
|
||||
footer = <div className={styles.footer}>{buttons}</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -98,12 +98,24 @@ function getParticipants(
|
|||
(f) => f.userId === member.userId && f.deviceId === deviceId
|
||||
);
|
||||
|
||||
participantInfoMap.set(deviceId, {
|
||||
connectionState: feed
|
||||
let connectionState: ConnectionState;
|
||||
// If we allow calls without media, we have no feeds and cannot read the connection status from them.
|
||||
// @TODO: The connection state should generally not be determined by the feed.
|
||||
if (
|
||||
groupCall.allowCallWithoutVideoAndAudio &&
|
||||
!feed &&
|
||||
!participant.screensharing
|
||||
) {
|
||||
connectionState = ConnectionState.Connected;
|
||||
} else {
|
||||
connectionState = feed
|
||||
? feed.connected
|
||||
? ConnectionState.Connected
|
||||
: ConnectionState.WaitMedia
|
||||
: ConnectionState.EstablishingCall,
|
||||
: ConnectionState.EstablishingCall;
|
||||
}
|
||||
participantInfoMap.set(deviceId, {
|
||||
connectionState,
|
||||
presenter: participant.screensharing,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue