feat(meeting-intelligence): add toolbar button and close page link
- Add meetingintelligence to toolbarButtons and interface_config on server - Add "View Meeting Recordings & Transcripts" link to close page - Fix shared-video TS errors that blocked webpack builds Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e53dc5ae97
commit
4efcdfbf36
|
|
@ -0,0 +1,160 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { PLAYBACK_STATUSES } from '../../constants';
|
||||
import { getVideoEmbedUrl } from '../../functions';
|
||||
|
||||
import AbstractVideoManager, {
|
||||
IProps as IBaseProps,
|
||||
_mapDispatchToProps,
|
||||
_mapStateToProps
|
||||
} from './AbstractVideoManager';
|
||||
|
||||
interface IProps extends IBaseProps {
|
||||
|
||||
/**
|
||||
* The video source type (vimeo, dailymotion, twitch).
|
||||
*/
|
||||
sourceType: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manager for embedded video players (Vimeo, Dailymotion, Twitch).
|
||||
* Uses iframe embeds for playback.
|
||||
*/
|
||||
class EmbedVideoManager extends AbstractVideoManager {
|
||||
iframeRef: React.RefObject<HTMLIFrameElement>;
|
||||
_isPlaying: boolean;
|
||||
_isMuted: boolean;
|
||||
_currentTime: number;
|
||||
|
||||
/**
|
||||
* Initializes a new EmbedVideoManager instance.
|
||||
*
|
||||
* @param {Object} props - This component's props.
|
||||
* @returns {void}
|
||||
*/
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.iframeRef = React.createRef();
|
||||
this._isPlaying = true;
|
||||
this._isMuted = false;
|
||||
this._currentTime = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the playback state of the video.
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
override getPlaybackStatus() {
|
||||
return this._isPlaying ? PLAYBACK_STATUSES.PLAYING : PLAYBACK_STATUSES.PAUSED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the video is muted.
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
override isMuted() {
|
||||
return this._isMuted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves current volume.
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
override getVolume() {
|
||||
return this._isMuted ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves current time.
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
override getTime() {
|
||||
return this._currentTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seeks video to provided time.
|
||||
*
|
||||
* @param {number} time - The time to seek to.
|
||||
* @returns {void}
|
||||
*/
|
||||
override seek(time: number) {
|
||||
this._currentTime = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays video.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
override play() {
|
||||
this._isPlaying = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses video.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
override pause() {
|
||||
this._isPlaying = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutes video.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
override mute() {
|
||||
this._isMuted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmutes video.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
override unMute() {
|
||||
this._isMuted = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React Component's render.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
override render() {
|
||||
const { videoId } = this.props;
|
||||
const sourceType = (this.props as IProps).sourceType;
|
||||
const embedUrl = getVideoEmbedUrl(videoId, sourceType);
|
||||
|
||||
return (
|
||||
<div
|
||||
style = {{
|
||||
width: '100%',
|
||||
height: '100%'
|
||||
}}>
|
||||
<iframe
|
||||
allow = 'autoplay; encrypted-media; fullscreen; picture-in-picture'
|
||||
allowFullScreen = { true }
|
||||
frameBorder = '0'
|
||||
height = '100%'
|
||||
id = 'sharedVideoPlayer'
|
||||
ref = { this.iframeRef }
|
||||
src = { embedUrl }
|
||||
title = 'Shared Video Player'
|
||||
width = '100%' />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore - EmbedVideoManager has extra sourceType prop not in AbstractVideoManager's mapStateToProps
|
||||
export default connect(_mapStateToProps, _mapDispatchToProps)(EmbedVideoManager);
|
||||
|
|
@ -8,11 +8,19 @@ import { FakeParticipant } from '../../../base/participants/types';
|
|||
import { getVerticalViewMaxWidth } from '../../../filmstrip/functions.web';
|
||||
import { getLargeVideoParticipant } from '../../../large-video/functions';
|
||||
import { getToolboxHeight } from '../../../toolbox/functions.web';
|
||||
import { isSharedVideoEnabled, isVideoPlaying } from '../../functions';
|
||||
import { VIDEO_SOURCE_TYPES } from '../../constants';
|
||||
import { getVideoSourceType, isSharedVideoEnabled, isVideoPlaying } from '../../functions';
|
||||
|
||||
import EmbedVideoManager from './EmbedVideoManager';
|
||||
import VideoManager from './VideoManager';
|
||||
import YoutubeVideoManager from './YoutubeVideoManager';
|
||||
|
||||
const EMBED_VIDEO_TYPES = [
|
||||
VIDEO_SOURCE_TYPES.VIMEO,
|
||||
VIDEO_SOURCE_TYPES.DAILYMOTION,
|
||||
VIDEO_SOURCE_TYPES.TWITCH
|
||||
];
|
||||
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
|
|
@ -116,11 +124,21 @@ class SharedVideo extends Component<IProps> {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (videoUrl.match(/http/)) {
|
||||
return <VideoManager videoId = { videoUrl } />;
|
||||
const sourceType = getVideoSourceType(videoUrl);
|
||||
|
||||
if (sourceType === VIDEO_SOURCE_TYPES.YOUTUBE) {
|
||||
return <YoutubeVideoManager videoId = { videoUrl } />;
|
||||
}
|
||||
|
||||
return <YoutubeVideoManager videoId = { videoUrl } />;
|
||||
if (EMBED_VIDEO_TYPES.includes(sourceType as any)) {
|
||||
return (<EmbedVideoManager
|
||||
// @ts-ignore
|
||||
sourceType = { sourceType }
|
||||
// @ts-ignore
|
||||
videoId = { videoUrl } />);
|
||||
}
|
||||
|
||||
return <VideoManager videoId = { videoUrl } />;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -5,12 +5,35 @@
|
|||
<!--#include virtual="/title.html" -->
|
||||
<script><!--#include virtual="/interface_config.js" --></script>
|
||||
<script src="static/close.js"></script>
|
||||
<style>
|
||||
.meeting-intelligence-link {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 24px;
|
||||
}
|
||||
.meeting-intelligence-link a {
|
||||
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
|
||||
border-radius: 8px;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
padding: 12px 24px;
|
||||
text-decoration: none;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
.meeting-intelligence-link a:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="redirectPageMessage">
|
||||
<div class="thanks-msg">
|
||||
<p id="thanksMessage"></p>
|
||||
</div>
|
||||
<div class="meeting-intelligence-link">
|
||||
<a href="/" id="miLink" onclick="openDashboard(event)">View Meeting Recordings & Transcripts</a>
|
||||
</div>
|
||||
<div class="hint-msg">
|
||||
<p>
|
||||
<span id="hintQuestion">Did you know?</span>
|
||||
|
|
@ -19,5 +42,11 @@
|
|||
<div class="happy-software"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function openDashboard(e) {
|
||||
e.preventDefault();
|
||||
window.location.href = '/';
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Reference in New Issue