init
Some checks failed
Close stale issues and PRs / stale (push) Has been cancelled

This commit is contained in:
2025-09-02 14:49:16 +08:00
commit 38ba663466
2885 changed files with 391107 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
import { connect } from 'react-redux';
import { IReduxState } from '../../../app/types';
import { translate } from '../../../base/i18n/functions';
import { IconVolumeOff, IconVolumeUp } from '../../../base/icons/svg';
import JitsiMeetJS from '../../../base/lib-jitsi-meet';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import { setOverflowMenuVisible } from '../../../toolbox/actions.web';
import { startAudioScreenShareFlow } from '../../actions.web';
import { isAudioOnlySharing, isScreenAudioSupported } from '../../functions';
interface IProps extends AbstractButtonProps {
/**
* Whether or not the local participant is audio only screen sharing.
*/
_isAudioOnlySharing: boolean;
}
/**
* Component that renders a toolbar button for toggling audio only screen share.
*/
class ShareAudioButton extends AbstractButton<IProps> {
override accessibilityLabel = 'toolbar.accessibilityLabel.shareaudio';
override icon = IconVolumeUp;
override label = 'toolbar.shareaudio';
override tooltip = 'toolbar.shareaudio';
override toggledIcon = IconVolumeOff;
override toggledLabel = 'toolbar.stopAudioSharing';
/**
* Handles clicking / pressing the button, and opens a new dialog.
*
* @private
* @returns {void}
*/
override _handleClick() {
const { dispatch } = this.props;
dispatch(startAudioScreenShareFlow());
dispatch(setOverflowMenuVisible(false));
}
/**
* Indicates whether this button is in toggled state or not.
*
* @override
* @protected
* @returns {boolean}
*/
override _isToggled() {
return this.props._isAudioOnlySharing;
}
}
/**
* Maps part of the Redux state to the props of this component.
*
* @param {Object} state - The Redux state.
* @private
* @returns {IProps}
*/
function _mapStateToProps(state: IReduxState) {
return {
_isAudioOnlySharing: Boolean(isAudioOnlySharing(state)),
visible: JitsiMeetJS.isDesktopSharingEnabled() && isScreenAudioSupported()
};
}
export default translate(connect(_mapStateToProps)(ShareAudioButton));

View File

@@ -0,0 +1,117 @@
import React, { Component } from 'react';
import { WithTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import { IReduxState, IStore } from '../../../app/types';
import { translate } from '../../../base/i18n/functions';
import { updateSettings } from '../../../base/settings/actions';
import { shouldHideShareAudioHelper } from '../../../base/settings/functions.web';
import { toggleScreensharing } from '../../../base/tracks/actions.web';
import Checkbox from '../../../base/ui/components/web/Checkbox';
import Dialog from '../../../base/ui/components/web/Dialog';
/**
* The type of the React {@code Component} props of {@link ShareAudioDialog}.
*/
export interface IProps extends WithTranslation {
/**
* Boolean stored in local storage that determines whether or not the dialog will be displayed again.
*/
_shouldHideShareAudioHelper: boolean;
/**
* The redux {@code dispatch} function.
*/
dispatch: IStore['dispatch'];
}
/**
* Component that displays the audio screen share helper dialog.
*/
class ShareAudioDialog extends Component<IProps> {
/**
* Instantiates a new component.
*
* @inheritdoc
*/
constructor(props: IProps) {
super(props);
this._onContinue = this._onContinue.bind(this);
this._onSelectHideShareAudioHelper = this._onSelectHideShareAudioHelper.bind(this);
}
/**
* Continue the normal screen sharing flow when the user clicks continue.
*
* @returns {boolean}
*/
_onContinue() {
// Pass undefined as the first parameter so the underlying logic decides weather or not to stop screen sharing.
this.props.dispatch(toggleScreensharing(undefined, true));
return true;
}
/**
* Callback invoked when the hide audio helper checkbox has been selected. This setting will be persisted in
* the local storage, thus the dialog won't be displayed again.
*
* @param {Object} e - The key event to handle.
* @returns {void}
*/
_onSelectHideShareAudioHelper({ target: { checked } }: React.ChangeEvent<HTMLInputElement>) {
this.props.dispatch(updateSettings({ hideShareAudioHelper: checked }));
}
/**
* Implements {@Component#render}.
*
* @inheritdoc
*/
override render() {
const { t } = this.props;
return (
<Dialog
ok = {{ translationKey: 'dialog.shareAudio' }}
onSubmit = { this._onContinue }
size = 'large'
titleKey = { t('dialog.shareAudioTitle') }>
<div className = 'share-audio-dialog'>
<img
alt = { t('dialog.shareAudioAltText') }
className = 'share-audio-animation'
src = 'images/share-audio.gif'
tabIndex = { 0 } />
<Checkbox
checked = { this.props._shouldHideShareAudioHelper }
label = { t('dialog.hideShareAudioHelper') }
name = 'hide-share-audio-helper'
// eslint-disable-next-line react/jsx-no-bind
onChange = { this._onSelectHideShareAudioHelper } />
</div>
</Dialog>
);
}
}
/**
* Maps part of the Redux state to the props of this component.
*
* @param {IReduxState} state - The Redux state.
* @private
* @returns {IProps}
*/
function _mapStateToProps(state: IReduxState) {
return {
_shouldHideShareAudioHelper: Boolean(shouldHideShareAudioHelper(state))
};
}
export default translate(connect(_mapStateToProps)(ShareAudioDialog));

View File

@@ -0,0 +1,95 @@
import React, { Component } from 'react';
import { WithTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import { IStore } from '../../../app/types';
import { translate } from '../../../base/i18n/functions';
import { toggleScreensharing } from '../../../base/tracks/actions';
import Dialog from '../../../base/ui/components/web/Dialog';
export interface IProps extends WithTranslation {
/**
* Whether or not the dialog was opened for the audio screen sharing flow or the normal one.
*/
_isAudioScreenShareWarning: Boolean;
/**
* The redux {@code dispatch} function.
*/
dispatch: IStore['dispatch'];
}
/**
* Component that displays the share audio helper dialog.
*/
class ShareScreenWarningDialog extends Component<IProps> {
/**
* Instantiates a new component.
*
* @inheritdoc
*/
constructor(props: IProps) {
super(props);
this._onStopSharing = this._onStopSharing.bind(this);
}
/**
* Stop current screen sharing session.
*
* @returns {boolean}
*/
_onStopSharing() {
// Depending on the context from which this dialog is opened we'll either be toggling off an audio only
// share session or a normal screen sharing one, this is indicated by the _isAudioScreenShareWarning prop.
this.props.dispatch(toggleScreensharing(undefined,
!this.props._isAudioScreenShareWarning));
return true;
}
/**
* Implements {@Component#render}.
*§.
*
* @inheritdoc
*/
override render() {
const { t } = this.props;
let description1, description2, header1, header2, stopSharing, title;
if (this.props._isAudioScreenShareWarning) {
header1 = 'dialog.shareAudioWarningH1';
header2 = 'dialog.shareMediaWarningGenericH2';
description1 = 'dialog.shareAudioWarningD1';
description2 = 'dialog.shareAudioWarningD2';
title = 'dialog.shareAudioWarningTitle';
stopSharing = 'toolbar.stopScreenSharing';
} else {
header1 = 'dialog.shareScreenWarningTitle';
header2 = 'dialog.shareMediaWarningGenericH2';
description1 = 'dialog.shareScreenWarningD1';
description2 = 'dialog.shareScreenWarningD2';
title = 'dialog.shareScreenWarningTitle';
stopSharing = 'toolbar.stopAudioSharing';
}
return (<Dialog
ok = {{ translationKey: stopSharing }}
onSubmit = { this._onStopSharing }
titleKey = { t(title) }>
<div className = 'share-screen-warn-dialog'>
<p className = 'header'> { t(header1) } </p>
<p className = 'description' > { t(description1) } </p>
<div className = 'separator-line' />
<p className = 'header' > { t(header2) } </p>
<p className = 'description' > { t(description2) } </p>
</div>
</Dialog>);
}
}
export default translate(connect()(ShareScreenWarningDialog));