@openeventkit/event-site 2.0.121 → 2.0.123
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/actions/event-actions.js +1 -10
- package/src/components/AttendeeToAttendeeWidgetComponent.js +41 -5
- package/src/components/SyncWordsPlayer.js +58 -0
- package/src/components/VideoComponent.js +12 -3
- package/src/components/summit-my-orders-tickets/components/TicketPopup/TicketPopupEditDetailsForm/TicketPopupEditDetailsForm.js +5 -0
- package/src/styles/full-profile.module.scss +3 -0
- package/src/styles/video.module.scss +21 -1
- package/src/templates/full-profile-page.js +65 -14
- package/src/utils/videoUtils.js +18 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openeventkit/event-site",
|
|
3
3
|
"description": "Event Site",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.123",
|
|
5
5
|
"author": "Tipit LLC",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
|
@@ -21,14 +21,14 @@
|
|
|
21
21
|
"@sentry/integrations": "^7.39.0",
|
|
22
22
|
"@sentry/react": "^7.39.0",
|
|
23
23
|
"@sentry/webpack-plugin": "^1.20.0",
|
|
24
|
-
"@supabase/supabase-js": "
|
|
24
|
+
"@supabase/supabase-js": "2.45.1",
|
|
25
25
|
"@types/googlemaps": "^3.39.9",
|
|
26
26
|
"@types/markerclustererplus": "^2.1.33",
|
|
27
27
|
"@types/react": "^16.9.42",
|
|
28
28
|
"@vimeo/player": "^2.16.3",
|
|
29
29
|
"ably": "^1.2.34",
|
|
30
30
|
"assert": "^2.1.0",
|
|
31
|
-
"attendee-to-attendee-widget": "3.1.
|
|
31
|
+
"attendee-to-attendee-widget": "3.1.1-beta.32",
|
|
32
32
|
"autoprefixer": "10.4.14",
|
|
33
33
|
"awesome-bootstrap-checkbox": "^1.0.1",
|
|
34
34
|
"axios": "^0.19.2",
|
|
@@ -29,23 +29,14 @@ export const setEventLastUpdate = (lastUpdate) => (dispatch) => {
|
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* @param eventId
|
|
32
|
-
* @param checkLocal
|
|
33
32
|
* @returns {(function(*, *): Promise<*>)|*}
|
|
34
33
|
*/
|
|
35
34
|
export const getEventById = (
|
|
36
35
|
eventId
|
|
37
|
-
) => async (dispatch
|
|
36
|
+
) => async (dispatch) => {
|
|
38
37
|
|
|
39
38
|
dispatch(startLoading());
|
|
40
|
-
// if we have it on the reducer , provide that first
|
|
41
|
-
let {allSchedulesState: {allEvents}} = getState();
|
|
42
|
-
const event = allEvents.find(ev => ev.id === parseInt(eventId));
|
|
43
|
-
|
|
44
|
-
if (event) {
|
|
45
|
-
dispatch(createAction(GET_EVENT_DATA)({event}));
|
|
46
|
-
}
|
|
47
39
|
|
|
48
|
-
// then refresh from api
|
|
49
40
|
let accessToken;
|
|
50
41
|
try {
|
|
51
42
|
accessToken = await getAccessToken();
|
|
@@ -59,7 +59,13 @@ const AttendeesWidgetComponent = ({ user, event, chatSettings }) => {
|
|
|
59
59
|
linked_in_profile,
|
|
60
60
|
twitter_name,
|
|
61
61
|
wechat_user,
|
|
62
|
-
public_profile_show_fullname
|
|
62
|
+
public_profile_show_fullname,
|
|
63
|
+
public_profile_show_email,
|
|
64
|
+
public_profile_allow_chat_with_me,
|
|
65
|
+
public_profile_show_photo,
|
|
66
|
+
public_profile_show_social_media_info,
|
|
67
|
+
public_profile_show_bio
|
|
68
|
+
} = idpProfile || {};
|
|
63
69
|
|
|
64
70
|
useEffect(() => {
|
|
65
71
|
if (!user || !userProfile || !idpProfile) return;
|
|
@@ -127,6 +133,12 @@ const AttendeesWidgetComponent = ({ user, event, chatSettings }) => {
|
|
|
127
133
|
.flatMap((st) => st.badge.features)
|
|
128
134
|
.filter((v, i, a) => a.map((item) => item.id).indexOf(v.id) === i),
|
|
129
135
|
bio: bio,
|
|
136
|
+
showEmail: public_profile_show_email === true,
|
|
137
|
+
allowChatWithMe: public_profile_allow_chat_with_me === true,
|
|
138
|
+
showFullName: public_profile_show_fullname === true,
|
|
139
|
+
showProfilePic: public_profile_show_photo === true,
|
|
140
|
+
showSocialInfo: public_profile_show_social_media_info === true,
|
|
141
|
+
showBio: public_profile_show_bio === true,
|
|
130
142
|
hasPermission: (permission) => {
|
|
131
143
|
const isAdmin = groups &&
|
|
132
144
|
groups.map((g) => g.slug).filter((g) => adminGroups.includes(g))
|
|
@@ -186,6 +198,20 @@ const mapState = ({ settingState }) => ({
|
|
|
186
198
|
export const AttendeesWidget = connect(mapState)(AttendeesWidgetComponent);
|
|
187
199
|
|
|
188
200
|
const AccessTracker = ({ user, isLoggedUser, summitPhase, chatSettings }) => {
|
|
201
|
+
const chatProps = {
|
|
202
|
+
streamApiKey: getEnvVariable(STREAM_IO_API_KEY),
|
|
203
|
+
apiBaseUrl: getEnvVariable(IDP_BASE_URL),
|
|
204
|
+
chatApiBaseUrl: getEnvVariable(CHAT_API_BASE_URL),
|
|
205
|
+
onAuthError: (err, res) => console.log(err),
|
|
206
|
+
openDir: "left",
|
|
207
|
+
activity: null,
|
|
208
|
+
getAccessToken: async () => {
|
|
209
|
+
const accessToken = await getAccessToken();
|
|
210
|
+
//console.log("AttendeesList->getAccessToken", accessToken);
|
|
211
|
+
return accessToken;
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
|
|
189
215
|
const trackerRef = useRef();
|
|
190
216
|
|
|
191
217
|
const handleLogout = useCallback(() => {
|
|
@@ -237,11 +263,15 @@ const AccessTracker = ({ user, isLoggedUser, summitPhase, chatSettings }) => {
|
|
|
237
263
|
wechat_user,
|
|
238
264
|
public_profile_show_fullname,
|
|
239
265
|
public_profile_show_email,
|
|
240
|
-
public_profile_allow_chat_with_me
|
|
266
|
+
public_profile_allow_chat_with_me,
|
|
267
|
+
public_profile_show_photo,
|
|
268
|
+
public_profile_show_social_media_info,
|
|
269
|
+
public_profile_show_bio
|
|
241
270
|
} = user.idpProfile;
|
|
242
271
|
|
|
243
272
|
const widgetProps = {
|
|
244
273
|
user: {
|
|
274
|
+
id: sub,
|
|
245
275
|
idpUserId: sub,
|
|
246
276
|
fullName: public_profile_show_fullname ? `${given_name} ${family_name}` : `${given_name}`,
|
|
247
277
|
email: email,
|
|
@@ -260,11 +290,17 @@ const AccessTracker = ({ user, isLoggedUser, summitPhase, chatSettings }) => {
|
|
|
260
290
|
.flatMap((st) => st.badge.features)
|
|
261
291
|
.filter((v, i, a) => a.map((item) => item.id).indexOf(v.id) === i),
|
|
262
292
|
bio: bio,
|
|
263
|
-
showEmail: public_profile_show_email,
|
|
264
|
-
allowChatWithMe: public_profile_allow_chat_with_me
|
|
293
|
+
showEmail: public_profile_show_email === true,
|
|
294
|
+
allowChatWithMe: public_profile_allow_chat_with_me === true,
|
|
295
|
+
showFullName: public_profile_show_fullname === true,
|
|
296
|
+
showProfilePic: public_profile_show_photo === true,
|
|
297
|
+
showSocialInfo: public_profile_show_social_media_info === true,
|
|
298
|
+
showBio: public_profile_show_bio === true
|
|
265
299
|
},
|
|
266
300
|
summitId: parseInt(getEnvVariable(SUMMIT_ID)),
|
|
267
|
-
|
|
301
|
+
keepAliveEnabled: true,
|
|
302
|
+
...chatProps,
|
|
303
|
+
...sbAuthProps
|
|
268
304
|
};
|
|
269
305
|
|
|
270
306
|
if (!chatSettings.enabled) return null;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import {getSynchWordsVideoFrameDdFromSrc} from "../utils/videoUtils";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SynchWordsPlayer extends React.Component {
|
|
7
|
+
|
|
8
|
+
constructor(props) {
|
|
9
|
+
super(props);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
componentDidMount() {
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
componentWillUnmount() {
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
render() {
|
|
19
|
+
const { video, className, autoplay } = this.props;
|
|
20
|
+
const id = getSynchWordsVideoFrameDdFromSrc(video);
|
|
21
|
+
console.log(`SynchWordsPlayer::render with id ${id}`);
|
|
22
|
+
let allow = "encrypted-media";
|
|
23
|
+
if(autoplay) allow = allow +';autoplay'
|
|
24
|
+
return (
|
|
25
|
+
<div className={className}>
|
|
26
|
+
<iframe id={id}
|
|
27
|
+
src={video}
|
|
28
|
+
frameBorder="0"
|
|
29
|
+
scrolling="no"
|
|
30
|
+
allow={allow}
|
|
31
|
+
allowFullScreen webkitallowfullscreen mozallowfullscreen oallowfullscreen msallowfullscreen
|
|
32
|
+
>
|
|
33
|
+
</iframe>
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
SynchWordsPlayer.propTypes = {
|
|
40
|
+
/**
|
|
41
|
+
* a video URL.
|
|
42
|
+
*/
|
|
43
|
+
video: PropTypes.oneOfType([
|
|
44
|
+
PropTypes.number,
|
|
45
|
+
PropTypes.string,
|
|
46
|
+
]),
|
|
47
|
+
/**
|
|
48
|
+
* CSS className for the player element.
|
|
49
|
+
*/
|
|
50
|
+
className: PropTypes.string,
|
|
51
|
+
/**
|
|
52
|
+
* Automatically start playback of the video. Note that this won’t work on
|
|
53
|
+
* some devices.
|
|
54
|
+
*/
|
|
55
|
+
autoplay: PropTypes.bool,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export default SynchWordsPlayer;
|
|
@@ -4,7 +4,8 @@ import VideoJSPlayer from './VideoJSPlayer';
|
|
|
4
4
|
import VimeoPlayer from "./VimeoPlayer";
|
|
5
5
|
import VideoMUXPlayer from './VideoMUXPlayer';
|
|
6
6
|
import styles from '../styles/video.module.scss';
|
|
7
|
-
import { isMuxVideo, isVimeoVideo, isYouTubeVideo } from '../utils/videoUtils';
|
|
7
|
+
import { isMuxVideo, isVimeoVideo, isYouTubeVideo, isSynchWordsVideo } from '../utils/videoUtils';
|
|
8
|
+
import SynchWordsPlayer from "./SyncWordsPlayer";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* @param url
|
|
@@ -48,6 +49,14 @@ const VideoComponent = ({ url, title, namespace, isLive, firstHalf, autoPlay, st
|
|
|
48
49
|
/>
|
|
49
50
|
);
|
|
50
51
|
};
|
|
52
|
+
// synch words player
|
|
53
|
+
if(isSynchWordsVideo(url)){
|
|
54
|
+
return (<SynchWordsPlayer
|
|
55
|
+
video={url}
|
|
56
|
+
autoplay={autoPlay}
|
|
57
|
+
className={styles.synchWordsPlayer}
|
|
58
|
+
/>);
|
|
59
|
+
}
|
|
51
60
|
|
|
52
61
|
const defaultVideoJsOptions = isYouTubeVideo(url) ? {
|
|
53
62
|
techOrder: ["youtube"],
|
|
@@ -99,7 +108,7 @@ VideoComponent.propTypes = {
|
|
|
99
108
|
isLive: PropTypes.bool,
|
|
100
109
|
firstHalf: PropTypes.bool,
|
|
101
110
|
autoPlay: PropTypes.bool,
|
|
102
|
-
start: PropTypes.number,
|
|
111
|
+
start: PropTypes.number,
|
|
103
112
|
tokens: PropTypes.object,
|
|
104
113
|
onError: PropTypes.func,
|
|
105
114
|
};
|
|
@@ -108,7 +117,7 @@ VideoComponent.defaultProps = {
|
|
|
108
117
|
title: '',
|
|
109
118
|
namespace: '',
|
|
110
119
|
firstHalf: true,
|
|
111
|
-
autoPlay: false,
|
|
120
|
+
autoPlay: false,
|
|
112
121
|
tokens: null,
|
|
113
122
|
};
|
|
114
123
|
|
|
@@ -319,6 +319,11 @@ export const TicketPopupEditDetailsForm = ({
|
|
|
319
319
|
onBlur={formik.handleBlur}
|
|
320
320
|
onChange={!!initialValues[TicketKeys.company].name ? noop : formik.handleChange}
|
|
321
321
|
disabled={!!initialValues[TicketKeys.company].name}
|
|
322
|
+
menuPortalTarget={document.body}
|
|
323
|
+
menuPosition="fixed"
|
|
324
|
+
styles={{
|
|
325
|
+
menuPortal: (base) => ({ ...base, zIndex: 9999 }),
|
|
326
|
+
}}
|
|
322
327
|
tabSelectsValue={false}
|
|
323
328
|
/>
|
|
324
329
|
{(formik.touched[TicketKeys.company] || triedSubmitting) && formik.errors[TicketKeys.company] &&
|
|
@@ -16,4 +16,24 @@
|
|
|
16
16
|
width: 100%;
|
|
17
17
|
height: 100%;
|
|
18
18
|
}
|
|
19
|
-
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.synchWordsPlayer{
|
|
22
|
+
/* 16:9 */
|
|
23
|
+
--video--width: 960;
|
|
24
|
+
--video--height: 540;
|
|
25
|
+
|
|
26
|
+
position: relative;
|
|
27
|
+
padding-bottom: calc(var(--video--height) / var(--video--width) * 100%); /* 56.25% */
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
max-width: 100%;
|
|
30
|
+
background: black;
|
|
31
|
+
|
|
32
|
+
iframe, object, embed{
|
|
33
|
+
position: absolute;
|
|
34
|
+
top: 0;
|
|
35
|
+
left: 0;
|
|
36
|
+
width: 100%;
|
|
37
|
+
height: 100%;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -16,6 +16,7 @@ import withOrchestra from "../utils/widgetOrchestra";
|
|
|
16
16
|
import LiteScheduleComponent from '../components/LiteScheduleComponent'
|
|
17
17
|
import ProfilePopupComponent from '../components/ProfilePopupComponent'
|
|
18
18
|
import ChangePasswordComponent from '../components/ChangePasswordComponent';
|
|
19
|
+
import AccessTracker from "../components/AttendeeToAttendeeWidgetComponent";
|
|
19
20
|
|
|
20
21
|
import { updateProfilePicture, updateProfile, getIDPProfile, updatePassword } from '../actions/user-actions'
|
|
21
22
|
|
|
@@ -46,6 +47,10 @@ export const FullProfilePageTemplate = ({ user, getIDPProfile, updateProfile, up
|
|
|
46
47
|
const [showFullName, setShowFullName] = useState(false);
|
|
47
48
|
const [allowChatWithMe, setAllowChatWithMe] = useState(false)
|
|
48
49
|
const [showEmail, setShowEmail] = useState(false);
|
|
50
|
+
const [showPicture, setShowPicture] = useState(false);
|
|
51
|
+
const [showBio, setShowBio] = useState(false);
|
|
52
|
+
const [showSocialMedia, setShowSocialMedia] = useState(false);
|
|
53
|
+
const [showTelephone, setShowTelephone] = useState(false);
|
|
49
54
|
const [bio, setBio] = useState('');
|
|
50
55
|
const [statementOfInterest, setStatementOfInterest] = useState('');
|
|
51
56
|
|
|
@@ -88,6 +93,10 @@ export const FullProfilePageTemplate = ({ user, getIDPProfile, updateProfile, up
|
|
|
88
93
|
setShowFullName(user.idpProfile.public_profile_show_fullname);
|
|
89
94
|
setAllowChatWithMe(user.idpProfile.public_profile_allow_chat_with_me);
|
|
90
95
|
setShowEmail(user.idpProfile.public_profile_show_email);
|
|
96
|
+
setShowPicture(user.idpProfile.public_profile_show_photo);
|
|
97
|
+
setShowBio(user.idpProfile.public_profile_show_bio);
|
|
98
|
+
setShowSocialMedia(user.idpProfile.public_profile_show_social_media_info);
|
|
99
|
+
setShowTelephone(user.idpProfile.public_profile_show_telephone_number);
|
|
91
100
|
setBio(user.idpProfile.bio || '');
|
|
92
101
|
setStatementOfInterest(user.idpProfile.statement_of_interest || '');
|
|
93
102
|
setAddress({
|
|
@@ -139,6 +148,10 @@ export const FullProfilePageTemplate = ({ user, getIDPProfile, updateProfile, up
|
|
|
139
148
|
public_profile_show_fullname: showFullName,
|
|
140
149
|
public_profile_allow_chat_with_me: allowChatWithMe,
|
|
141
150
|
public_profile_show_email: showEmail,
|
|
151
|
+
public_profile_show_photo: showPicture,
|
|
152
|
+
public_profile_show_bio: showBio,
|
|
153
|
+
public_profile_show_social_media_info: showSocialMedia,
|
|
154
|
+
public_profile_show_telephone_number: showTelephone,
|
|
142
155
|
bio: bio,
|
|
143
156
|
statement_of_interest: statementOfInterest,
|
|
144
157
|
address1: address.street,
|
|
@@ -204,6 +217,10 @@ export const FullProfilePageTemplate = ({ user, getIDPProfile, updateProfile, up
|
|
|
204
217
|
setShowFullName(user.idpProfile.public_profile_show_fullname);
|
|
205
218
|
setAllowChatWithMe(user.idpProfile.public_profile_allow_chat_with_me);
|
|
206
219
|
setShowEmail(user.idpProfile.public_profile_show_email);
|
|
220
|
+
setShowPicture(user.idpProfile.public_profile_show_photo);
|
|
221
|
+
setShowBio(user.idpProfile.public_profile_show_bio);
|
|
222
|
+
setShowSocialMedia(user.idpProfile.public_profile_show_social_media_info);
|
|
223
|
+
setShowTelephone(user.idpProfile.public_profile_show_telephone_number);
|
|
207
224
|
break;
|
|
208
225
|
case 'bio':
|
|
209
226
|
setBio(user.idpProfile.bio || '');
|
|
@@ -423,20 +440,53 @@ export const FullProfilePageTemplate = ({ user, getIDPProfile, updateProfile, up
|
|
|
423
440
|
</div>
|
|
424
441
|
</div>
|
|
425
442
|
</div>
|
|
426
|
-
<
|
|
427
|
-
<
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
443
|
+
<div className={`columns is-mobile`}>
|
|
444
|
+
<div className={`column is-full`}>
|
|
445
|
+
<span>
|
|
446
|
+
By electing to show your information you are indicating that other attendees at the
|
|
447
|
+
event(s) you are registered for will be able to see this information.
|
|
448
|
+
</span>
|
|
449
|
+
</div>
|
|
450
|
+
</div>
|
|
451
|
+
<div className={`columns is-mobile`}>
|
|
452
|
+
<div className={`column is-half`}>
|
|
453
|
+
<label className={styles.checkbox}>
|
|
454
|
+
<input type="checkbox" checked={showFullName} onChange={e => setShowFullName(e.target.checked)} />
|
|
455
|
+
Show full name (first name is always shown)
|
|
456
|
+
</label>
|
|
457
|
+
<br />
|
|
458
|
+
<label className={styles.checkbox}>
|
|
459
|
+
<input type="checkbox" checked={showEmail} onChange={e => setShowEmail(e.target.checked)} />
|
|
460
|
+
Show email
|
|
461
|
+
</label>
|
|
462
|
+
<br />
|
|
463
|
+
<label className={styles.checkbox}>
|
|
464
|
+
<input type="checkbox" checked={showTelephone} onChange={e => setShowTelephone(e.target.checked)} />
|
|
465
|
+
Show telephone number
|
|
466
|
+
</label>
|
|
467
|
+
<br />
|
|
468
|
+
<label className={styles.checkbox}>
|
|
469
|
+
<input type="checkbox" checked={allowChatWithMe} onChange={e => setAllowChatWithMe(e.target.checked)} />
|
|
470
|
+
Allow people to chat with me
|
|
471
|
+
</label>
|
|
472
|
+
</div>
|
|
473
|
+
<div className={`column is-half`}>
|
|
474
|
+
<label className={styles.checkbox}>
|
|
475
|
+
<input type="checkbox" checked={showPicture} onChange={e => setShowPicture(e.target.checked)} />
|
|
476
|
+
Show picture
|
|
477
|
+
</label>
|
|
478
|
+
<br />
|
|
479
|
+
<label className={styles.checkbox}>
|
|
480
|
+
<input type="checkbox" checked={showBio} onChange={e => setShowBio(e.target.checked)} />
|
|
481
|
+
Show bio
|
|
482
|
+
</label>
|
|
483
|
+
<br />
|
|
484
|
+
<label className={styles.checkbox}>
|
|
485
|
+
<input type="checkbox" checked={showSocialMedia} onChange={e => setShowSocialMedia(e.target.checked)} />
|
|
486
|
+
Show social media info
|
|
487
|
+
</label>
|
|
488
|
+
</div>
|
|
489
|
+
</div>
|
|
440
490
|
<div className={`columns is-mobile ${styles.buttons}`}>
|
|
441
491
|
<div className={`column is-half`}>
|
|
442
492
|
<button className={`button is-large ${styles.profileButton}`} onClick={() => discardChanges('profile')}>Discard</button>
|
|
@@ -602,6 +652,7 @@ export const FullProfilePageTemplate = ({ user, getIDPProfile, updateProfile, up
|
|
|
602
652
|
closePopup={() => handleTogglePopup(!showProfile)}
|
|
603
653
|
/>
|
|
604
654
|
}
|
|
655
|
+
<AccessTracker />
|
|
605
656
|
</React.Fragment>
|
|
606
657
|
)
|
|
607
658
|
};
|
package/src/utils/videoUtils.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const IS_MUX_VIDEO_REGEX = /https:\/\/stream.mux.com\/(.*).m3u8/;
|
|
2
|
+
const IS_SYNC_WORDS_VIDEO_REGEX = /https:\/\/player.syncwords.com\/iframe\/live\/(.*)\/(.*)/g;
|
|
2
3
|
|
|
3
4
|
export const getMUXPlaybackId = (url) => {
|
|
4
5
|
if(!url) return null;
|
|
@@ -25,3 +26,20 @@ export const isMuxVideo = (url) => {
|
|
|
25
26
|
if(!url) return false;
|
|
26
27
|
return url.match(IS_MUX_VIDEO_REGEX)
|
|
27
28
|
}
|
|
29
|
+
|
|
30
|
+
export const isSynchWordsVideo = (url) => {
|
|
31
|
+
if(!url) return false;
|
|
32
|
+
return url.match(IS_SYNC_WORDS_VIDEO_REGEX);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param src
|
|
37
|
+
* @returns {string|null}
|
|
38
|
+
*/
|
|
39
|
+
export const getSynchWordsVideoFrameDdFromSrc = (src) => {
|
|
40
|
+
const m = [...src.matchAll(IS_SYNC_WORDS_VIDEO_REGEX)];
|
|
41
|
+
if(!m?.length) return null;
|
|
42
|
+
const parts = m[0];
|
|
43
|
+
if(parts.length < 3) return null;
|
|
44
|
+
return `${parts[1]}-live-${parts[2]}`;
|
|
45
|
+
}
|