@instructure/canvas-rce 7.3.1 → 8.1.0
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/CHANGELOG.md +70 -0
- package/{es/rce/plugins/shared/ai_tools/index.js → __mocks__/@instructure/ui-media-player/_mockUiMediaPlayer.js} +4 -4
- package/__tests__/common/mimeClass.test.js +25 -1
- package/__tests__/rcs/api.test.js +280 -251
- package/es/canvasFileBrowser/FileBrowser.d.ts +2 -2
- package/es/canvasFileBrowser/FileBrowser.js +8 -7
- package/es/common/mimeClass.js +3 -1
- package/es/defaultTinymceConfig.js +47 -49
- package/es/enhance-user-content/enhance_user_content.js +6 -8
- package/es/enhance-user-content/index.d.ts +3 -1
- package/es/enhance-user-content/index.js +3 -1
- package/es/enhance-user-content/youtube_overlay.js +18 -0
- package/es/getThemeVars.d.ts +1 -1
- package/es/getThemeVars.js +23 -26
- package/es/rce/KeyboardShortcutModal.js +1 -1
- package/es/rce/RCE.d.ts +9 -0
- package/es/rce/RCE.js +4 -0
- package/es/rce/RCEGlobals.d.ts +2 -0
- package/es/rce/RCEGlobals.js +1 -0
- package/es/rce/RCEVariants.d.ts +1 -2
- package/es/rce/RCEVariants.js +1 -2
- package/es/rce/RCEWrapper.d.ts +6 -16
- package/es/rce/RCEWrapper.js +18 -87
- package/es/rce/RCEWrapper.utils.d.ts +1 -1
- package/es/rce/RCEWrapperProps.d.ts +2 -1
- package/es/rce/RCEWrapperProps.js +2 -1
- package/es/rce/StatusBar.d.ts +0 -1
- package/es/rce/StatusBar.js +3 -28
- package/es/rce/plugins/instructure_equation/EquationEditorModal/advancedOnlySyntax.d.ts +2 -1
- package/es/rce/plugins/instructure_equation/EquationEditorModal/advancedOnlySyntax.js +3 -1
- package/es/rce/plugins/instructure_equation/EquationEditorModal/index.d.ts +1 -0
- package/es/rce/plugins/instructure_equation/EquationEditorModal/index.js +12 -2
- package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/ImageOptions.js +2 -2
- package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/ImageSection.js +3 -3
- package/es/rce/plugins/instructure_icon_maker/svg/constants.d.ts +20 -5
- package/es/rce/plugins/instructure_icon_maker/svg/utils.d.ts +1 -1
- package/es/rce/plugins/instructure_icon_maker/utils/IconMakerFormHasChanges.js +2 -2
- package/es/rce/plugins/instructure_image/ImageEmbedOptions.d.ts +0 -2
- package/es/rce/plugins/instructure_image/ImageEmbedOptions.js +2 -9
- package/es/rce/plugins/instructure_paste/plugin.js +18 -12
- package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialogModal.d.ts +1 -1
- package/es/rce/plugins/instructure_rce_external_tools/components/util/ToolLaunchIframe.d.ts +4 -0
- package/es/rce/plugins/instructure_rce_external_tools/components/util/ToolLaunchIframe.js +4 -0
- package/es/rce/plugins/instructure_record/AudioOptionsTray/TrayController.d.ts +11 -2
- package/es/rce/plugins/instructure_record/AudioOptionsTray/TrayController.js +92 -10
- package/es/rce/plugins/instructure_record/AudioOptionsTray/index.d.ts +13 -1
- package/es/rce/plugins/instructure_record/AudioOptionsTray/index.js +216 -24
- package/es/rce/plugins/instructure_record/MediaPanel/index.js +16 -5
- package/es/rce/plugins/instructure_record/VideoOptionsTray/TrayController.d.ts +14 -13
- package/es/rce/plugins/instructure_record/VideoOptionsTray/TrayController.js +110 -39
- package/es/rce/plugins/instructure_record/VideoOptionsTray/index.d.ts +11 -1
- package/es/rce/plugins/instructure_record/VideoOptionsTray/index.js +242 -67
- package/es/rce/plugins/instructure_record/clickCallback.js +19 -4
- package/es/rce/plugins/instructure_record/mediaTranslations.js +1 -1
- package/es/rce/plugins/instructure_record/playerLayoutOptions.d.ts +25 -0
- package/es/rce/plugins/instructure_record/playerLayoutOptions.js +91 -0
- package/es/rce/plugins/instructure_record/plugin.js +2 -5
- package/es/rce/plugins/instructure_record/utils.d.ts +3 -0
- package/es/rce/plugins/instructure_record/utils.js +31 -0
- package/es/rce/plugins/instructure_studio_media_options/plugin.js +82 -26
- package/es/rce/plugins/shared/ContentSelection.d.ts +6 -1
- package/es/rce/plugins/shared/ContentSelection.js +15 -6
- package/es/rce/plugins/shared/DimensionsInput/DimensionInput.js +1 -2
- package/es/rce/plugins/shared/DimensionsInput/index.js +11 -12
- package/es/rce/plugins/shared/DimensionsInput/useDimensionsState.d.ts +1 -1
- package/es/rce/plugins/shared/DimensionsInput/useDimensionsState.js +4 -3
- package/es/rce/plugins/shared/StudioLtiSupportUtils.d.ts +27 -6
- package/es/rce/plugins/shared/StudioLtiSupportUtils.js +82 -13
- package/es/rce/plugins/shared/Upload/UploadFile.js +1 -8
- package/es/rce/style.d.ts +2 -1
- package/es/rce/style.js +4 -2
- package/es/rcs/api.d.ts +5 -10
- package/es/rcs/api.js +15 -21
- package/es/rcs/fake.d.ts +1 -7
- package/es/rcs/fake.js +1 -47
- package/es/sidebar/actions/media.d.ts +19 -6
- package/es/sidebar/actions/media.js +17 -4
- package/es/sidebar/actions/upload.d.ts +3 -3
- package/es/sidebar/actions/upload.js +9 -9
- package/es/sidebar/containers/Sidebar.js +0 -2
- package/es/sidebar/containers/sidebarHandlers.d.ts +2 -4
- package/es/sidebar/containers/sidebarHandlers.js +2 -5
- package/es/sidebar/reducers/index.d.ts +0 -1
- package/es/sidebar/reducers/index.js +0 -2
- package/es/sidebar/store/initialState.d.ts +0 -1
- package/es/sidebar/store/initialState.js +0 -5
- package/es/translations/locales/ar.js +65 -80
- package/es/translations/locales/ca.js +65 -80
- package/es/translations/locales/cy.js +65 -80
- package/es/translations/locales/da-x-k12.js +65 -80
- package/es/translations/locales/da.js +65 -80
- package/es/translations/locales/de.js +65 -80
- package/es/translations/locales/el.js +0 -9
- package/es/translations/locales/en-AU-x-unimelb.js +65 -80
- package/es/translations/locales/en-GB-x-ukhe.js +65 -80
- package/es/translations/locales/en.js +61 -79
- package/es/translations/locales/en_AU.js +65 -80
- package/es/translations/locales/en_CA.js +65 -80
- package/es/translations/locales/en_CY.js +65 -80
- package/es/translations/locales/en_GB.js +65 -80
- package/es/translations/locales/es.js +65 -80
- package/es/translations/locales/es_ES.js +65 -80
- package/es/translations/locales/fa_IR.js +0 -9
- package/es/translations/locales/fi.js +65 -80
- package/es/translations/locales/fr.js +65 -80
- package/es/translations/locales/fr_CA.js +65 -80
- package/es/translations/locales/ga.js +65 -80
- package/es/translations/locales/he.js +0 -9
- package/es/translations/locales/hi.js +65 -80
- package/es/translations/locales/ht.js +65 -80
- package/es/translations/locales/hu.js +0 -36
- package/es/translations/locales/hy.js +0 -9
- package/es/translations/locales/id.js +65 -80
- package/es/translations/locales/is.js +65 -80
- package/es/translations/locales/it.js +65 -80
- package/es/translations/locales/ja.js +65 -80
- package/es/translations/locales/ko.js +2455 -133
- package/es/translations/locales/mi.js +65 -80
- package/es/translations/locales/ms.js +65 -80
- package/es/translations/locales/nb-x-k12.js +65 -80
- package/es/translations/locales/nb.js +65 -80
- package/es/translations/locales/nl.js +66 -81
- package/es/translations/locales/nn.js +0 -36
- package/es/translations/locales/pl.js +65 -80
- package/es/translations/locales/pt.js +65 -80
- package/es/translations/locales/pt_BR.js +65 -80
- package/es/translations/locales/ru.js +65 -80
- package/es/translations/locales/sl.js +65 -80
- package/es/translations/locales/sv-x-k12.js +65 -80
- package/es/translations/locales/sv.js +65 -80
- package/es/translations/locales/th.js +65 -80
- package/es/translations/locales/tr.js +1962 -18
- package/es/translations/locales/uk_UA.js +0 -9
- package/es/translations/locales/vi.js +65 -80
- package/es/translations/locales/zh-Hans.js +65 -80
- package/es/translations/locales/zh-Hant.js +65 -80
- package/es/translations/locales/zh.js +65 -80
- package/es/translations/locales/zh_HK.js +65 -80
- package/eslint.config.js +16 -147
- package/jest/jest-setup.js +1 -0
- package/jest.config.js +2 -0
- package/oxlint.json +84 -0
- package/package.json +87 -62
- package/tsconfig.json +3 -2
- package/es/rce/plugins/shared/ai_tools/AIResponseModal.d.ts +0 -10
- package/es/rce/plugins/shared/ai_tools/AIResponseModal.js +0 -67
- package/es/rce/plugins/shared/ai_tools/AIToolsTray.d.ts +0 -18
- package/es/rce/plugins/shared/ai_tools/AIToolsTray.js +0 -489
- package/es/rce/plugins/shared/ai_tools/aiicons.d.ts +0 -7
- package/es/rce/plugins/shared/ai_tools/aiicons.js +0 -60
- package/es/rce/plugins/shared/ai_tools/index.d.ts +0 -3
- package/es/sidebar/actions/flickr.d.ts +0 -20
- package/es/sidebar/actions/flickr.js +0 -60
- package/es/sidebar/reducers/flickr.d.ts +0 -1
- package/es/sidebar/reducers/flickr.js +0 -49
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function mapStudioEmbedOptions(embedOptions: Record<string, boolean>): string[];
|
|
2
|
+
export declare function readViewerRestrictions(viewerRestrictions: Record<string, boolean>): string[];
|
|
3
|
+
export declare function mapViewerRestrictions(viewerRestrictions: string[]): Record<string, boolean>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2026 - present Instructure, Inc.
|
|
3
|
+
*
|
|
4
|
+
* This file is part of Canvas.
|
|
5
|
+
*
|
|
6
|
+
* Canvas is free software: you can redistribute it and/or modify it under
|
|
7
|
+
* the terms of the GNU Affero General Public License as published by the Free
|
|
8
|
+
* Software Foundation, version 3 of the License.
|
|
9
|
+
*
|
|
10
|
+
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
11
|
+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
12
|
+
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
13
|
+
* details.
|
|
14
|
+
*
|
|
15
|
+
* You should have received a copy of the GNU Affero General Public License along
|
|
16
|
+
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export function mapStudioEmbedOptions(embedOptions) {
|
|
20
|
+
return embedOptions ? Object.entries(embedOptions).filter(([, v]) => v).map(([k]) => k) : [];
|
|
21
|
+
}
|
|
22
|
+
const VIEWER_RESTRICTIONS = ['show_rolling_transcript'];
|
|
23
|
+
export function readViewerRestrictions(viewerRestrictions) {
|
|
24
|
+
return viewerRestrictions ? Object.keys(viewerRestrictions).filter(k => viewerRestrictions[k]) : [];
|
|
25
|
+
}
|
|
26
|
+
export function mapViewerRestrictions(viewerRestrictions) {
|
|
27
|
+
return VIEWER_RESTRICTIONS.reduce((acc, restriction) => {
|
|
28
|
+
acc[restriction] = viewerRestrictions.includes(restriction);
|
|
29
|
+
return acc;
|
|
30
|
+
}, {});
|
|
31
|
+
}
|
|
@@ -17,19 +17,29 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import tinymce from 'tinymce';
|
|
20
|
-
import { isStudioEmbeddedMedia, handleBeforeObjectSelected, notifyStudioEmbedTypeChange, updateStudioIframeDimensions,
|
|
20
|
+
import { isStudioEmbeddedMedia, isImprovedStudioEmbed, handleBeforeObjectSelected, notifyStudioEmbedTypeChange, updateStudioIframeDimensions, validateStudioEmbedTypeChangeResponse } from '../shared/StudioLtiSupportUtils';
|
|
21
21
|
import VideoTrayController from '../instructure_record/VideoOptionsTray/TrayController';
|
|
22
22
|
import formatMessage from '../../../format-message';
|
|
23
23
|
import RCEGlobals from '../../RCEGlobals';
|
|
24
24
|
import { thumbnailViewIcon, learnViewIcon, collabViewIcon, optionsIcon, removeIcon } from './studioToolbarIcons';
|
|
25
25
|
const studioTrayController = new VideoTrayController();
|
|
26
26
|
const handleStudioMessage = e => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
// can be extended in the future to handle more message types from Studio LTI
|
|
28
|
+
switch (e.data?.subject) {
|
|
29
|
+
case 'studio.embedTypeChanged.response':
|
|
30
|
+
if (validateStudioEmbedTypeChangeResponse(e.data)) {
|
|
31
|
+
updateStudioIframeDimensions(tinymce.activeEditor, e.data);
|
|
32
|
+
}
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
return;
|
|
31
36
|
}
|
|
32
37
|
};
|
|
38
|
+
const isEmbedButtonActive = (buttonName, currentSelectedElement) => {
|
|
39
|
+
return (currentSelectedElement.getAttribute('data-mce-p-src') || '').includes(buttonName);
|
|
40
|
+
};
|
|
41
|
+
const isImprovedStudioEmbeddedMedia = element => isStudioEmbeddedMedia(element) && isImprovedStudioEmbed(element);
|
|
42
|
+
const isNonImprovedStudioEmbeddedMedia = element => isStudioEmbeddedMedia(element) && !isImprovedStudioEmbed(element);
|
|
33
43
|
tinymce.PluginManager.add('instructure_studio_media_options', function (ed) {
|
|
34
44
|
if (RCEGlobals.getFeatures().rce_studio_embed_improvements) {
|
|
35
45
|
window.addEventListener('message', handleStudioMessage);
|
|
@@ -48,6 +58,16 @@ tinymce.PluginManager.add('instructure_studio_media_options', function (ed) {
|
|
|
48
58
|
background-color: #2B7ABC;
|
|
49
59
|
color: white;
|
|
50
60
|
}
|
|
61
|
+
|
|
62
|
+
.tox .tox-pop .tox-tbtn.tox-tbtn--enabled {
|
|
63
|
+
background-color: #6A7883;
|
|
64
|
+
color: white;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.tox .tox-pop .tox-tbtn.tox-tbtn--enabled:hover {
|
|
68
|
+
background-color: #2B7ABC;
|
|
69
|
+
color: white;
|
|
70
|
+
}
|
|
51
71
|
`;
|
|
52
72
|
document.head.appendChild(style);
|
|
53
73
|
}
|
|
@@ -57,39 +77,66 @@ tinymce.PluginManager.add('instructure_studio_media_options', function (ed) {
|
|
|
57
77
|
ed.ui.registry.addIcon('collab-view-icon', collabViewIcon);
|
|
58
78
|
ed.ui.registry.addIcon('options-icon', optionsIcon);
|
|
59
79
|
ed.ui.registry.addIcon('remove-icon', removeIcon);
|
|
60
|
-
ed.ui.registry.
|
|
80
|
+
ed.ui.registry.addToggleButton('thumbnail-view', {
|
|
81
|
+
onSetup: buttonApi => {
|
|
82
|
+
buttonApi.setActive(isEmbedButtonActive('thumbnail_embed', ed.selection.getNode()));
|
|
83
|
+
const editorEventCallback = eventApi => {
|
|
84
|
+
buttonApi.setActive(isEmbedButtonActive('thumbnail_embed', eventApi.element));
|
|
85
|
+
};
|
|
86
|
+
ed.on('NodeChange', editorEventCallback);
|
|
87
|
+
return () => ed.off('NodeChange', editorEventCallback);
|
|
88
|
+
},
|
|
61
89
|
onAction() {
|
|
62
90
|
notifyStudioEmbedTypeChange(ed, 'thumbnail_embed');
|
|
63
91
|
},
|
|
64
92
|
icon: 'thumbnail-view-icon',
|
|
65
|
-
text: formatMessage('Thumbnail')
|
|
66
|
-
tooltip: formatMessage('Thumbnail')
|
|
93
|
+
text: formatMessage('Thumbnail')
|
|
67
94
|
});
|
|
68
|
-
ed.ui.registry.
|
|
95
|
+
ed.ui.registry.addToggleButton('learn-view', {
|
|
96
|
+
onSetup: buttonApi => {
|
|
97
|
+
buttonApi.setActive(isEmbedButtonActive('learn_embed', ed.selection.getNode()));
|
|
98
|
+
const editorEventCallback = eventApi => {
|
|
99
|
+
buttonApi.setActive(isEmbedButtonActive('learn_embed', eventApi.element));
|
|
100
|
+
};
|
|
101
|
+
ed.on('NodeChange', editorEventCallback);
|
|
102
|
+
return () => ed.off('NodeChange', editorEventCallback);
|
|
103
|
+
},
|
|
69
104
|
onAction() {
|
|
70
105
|
notifyStudioEmbedTypeChange(ed, 'learn_embed');
|
|
71
106
|
},
|
|
72
107
|
icon: 'learn-view-icon',
|
|
73
|
-
text: formatMessage('Learn')
|
|
74
|
-
tooltip: formatMessage('Learn')
|
|
108
|
+
text: formatMessage('Learn')
|
|
75
109
|
});
|
|
76
|
-
ed.ui.registry.
|
|
110
|
+
ed.ui.registry.addToggleButton('collab-view', {
|
|
111
|
+
onSetup: buttonApi => {
|
|
112
|
+
buttonApi.setActive(isEmbedButtonActive('collaboration_embed', ed.selection.getNode()));
|
|
113
|
+
const editorEventCallback = eventApi => {
|
|
114
|
+
buttonApi.setActive(isEmbedButtonActive('collaboration_embed', eventApi.element));
|
|
115
|
+
};
|
|
116
|
+
ed.on('NodeChange', editorEventCallback);
|
|
117
|
+
return () => ed.off('NodeChange', editorEventCallback);
|
|
118
|
+
},
|
|
77
119
|
onAction() {
|
|
78
120
|
notifyStudioEmbedTypeChange(ed, 'collaboration_embed');
|
|
79
121
|
},
|
|
80
122
|
icon: 'collab-view-icon',
|
|
81
|
-
text: formatMessage('Collab')
|
|
82
|
-
tooltip: formatMessage('Collab')
|
|
123
|
+
text: formatMessage('Collab')
|
|
83
124
|
});
|
|
125
|
+
const openStudioTray = () => {
|
|
126
|
+
if (!studioTrayController.isOpen) {
|
|
127
|
+
studioTrayController.showTrayForEditor(ed);
|
|
128
|
+
ed.focus();
|
|
129
|
+
}
|
|
130
|
+
};
|
|
84
131
|
ed.ui.registry.addButton('studio-media-options', {
|
|
85
|
-
onAction
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
132
|
+
onAction: openStudioTray,
|
|
133
|
+
icon: 'options-icon',
|
|
134
|
+
text: formatMessage('Options')
|
|
135
|
+
});
|
|
136
|
+
ed.ui.registry.addButton('studio-media-options-basic', {
|
|
137
|
+
onAction: openStudioTray,
|
|
90
138
|
icon: 'options-icon',
|
|
91
|
-
text: formatMessage('Options')
|
|
92
|
-
tooltip: formatMessage('Options')
|
|
139
|
+
text: formatMessage('Studio Media Options')
|
|
93
140
|
});
|
|
94
141
|
ed.ui.registry.addButton('remove-studio-media', {
|
|
95
142
|
onAction() {
|
|
@@ -108,22 +155,31 @@ tinymce.PluginManager.add('instructure_studio_media_options', function (ed) {
|
|
|
108
155
|
}
|
|
109
156
|
},
|
|
110
157
|
icon: 'remove-icon',
|
|
111
|
-
text: formatMessage('Remove')
|
|
112
|
-
tooltip: formatMessage('Remove Studio Media')
|
|
158
|
+
text: formatMessage('Remove')
|
|
113
159
|
});
|
|
114
160
|
ed.ui.registry.addContextToolbar('studio-extra-toolbar', {
|
|
115
161
|
items: 'thumbnail-view | learn-view | collab-view | studio-media-options | remove-studio-media',
|
|
116
162
|
position: 'node',
|
|
117
|
-
predicate:
|
|
163
|
+
predicate: isImprovedStudioEmbeddedMedia,
|
|
164
|
+
scope: 'node'
|
|
165
|
+
});
|
|
166
|
+
ed.ui.registry.addContextToolbar('studio-basic-toolbar', {
|
|
167
|
+
items: 'studio-media-options-basic | remove-studio-media',
|
|
168
|
+
position: 'node',
|
|
169
|
+
predicate: isNonImprovedStudioEmbeddedMedia,
|
|
118
170
|
scope: 'node'
|
|
119
171
|
});
|
|
172
|
+
ed.on('NodeChange', () => {
|
|
173
|
+
if (studioTrayController.isOpen) {
|
|
174
|
+
studioTrayController.hideTrayForEditor(ed, true);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
120
177
|
} else {
|
|
121
178
|
ed.ui.registry.addButton('studio-media-options', {
|
|
122
179
|
onAction() {
|
|
123
180
|
studioTrayController.showTrayForEditor(ed);
|
|
124
181
|
},
|
|
125
|
-
text: formatMessage('Studio Media Options')
|
|
126
|
-
tooltip: formatMessage('Show Studio media options')
|
|
182
|
+
text: formatMessage('Studio Media Options')
|
|
127
183
|
});
|
|
128
184
|
ed.ui.registry.addContextToolbar('studio-media-options-toolbar', {
|
|
129
185
|
items: 'studio-media-options',
|
|
@@ -23,10 +23,11 @@ export function asLink($element: any, editor: any): {
|
|
|
23
23
|
fileName: any;
|
|
24
24
|
published: boolean;
|
|
25
25
|
} | null;
|
|
26
|
-
export function asVideoElement($element: any): {
|
|
26
|
+
export function asVideoElement($element: any, isStudioVideo?: boolean): {
|
|
27
27
|
$element: any;
|
|
28
28
|
type: string;
|
|
29
29
|
id: string | null;
|
|
30
|
+
viewerRestrictions: any;
|
|
30
31
|
titleText: any;
|
|
31
32
|
appliedHeight: any;
|
|
32
33
|
appliedWidth: any;
|
|
@@ -37,6 +38,10 @@ export function asVideoElement($element: any): {
|
|
|
37
38
|
export function asAudioElement($element: any): {
|
|
38
39
|
titleText: any;
|
|
39
40
|
id: any;
|
|
41
|
+
containerDimensions: {
|
|
42
|
+
width: any;
|
|
43
|
+
height: any;
|
|
44
|
+
};
|
|
40
45
|
} | null;
|
|
41
46
|
export function getContentFromElement($element: any, editor: any): {
|
|
42
47
|
$element: any;
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import { fromImageEmbed, fromVideoEmbed } from '../instructure_image/ImageEmbedOptions';
|
|
20
|
-
import { isOnlyTextSelected } from '../../contentInsertionUtils';
|
|
21
19
|
import formatMessage from '../../../format-message';
|
|
22
|
-
import { isStudioEmbeddedMedia } from './StudioLtiSupportUtils';
|
|
23
20
|
import { parseUrlPath } from '../../../util/url-util';
|
|
21
|
+
import { isOnlyTextSelected } from '../../contentInsertionUtils';
|
|
22
|
+
import { fromImageEmbed, fromVideoEmbed } from '../instructure_image/ImageEmbedOptions';
|
|
24
23
|
import { findMediaPlayerIframe } from './iframeUtils';
|
|
24
|
+
import { isStudioEmbeddedMedia } from './StudioLtiSupportUtils';
|
|
25
25
|
const FILE_DOWNLOAD_PATH_REGEX = /^\/(courses\/\d+\/)?files\/\d+\/download$/;
|
|
26
26
|
export const LINK_TYPE = 'link';
|
|
27
27
|
export const FILE_LINK_TYPE = 'file-link';
|
|
@@ -91,7 +91,8 @@ export function asLink($element, editor) {
|
|
|
91
91
|
// and it's attributes, even though this could change with future
|
|
92
92
|
// tinymce releases.
|
|
93
93
|
// see https://github.com/tinymce/tinymce/issues/5181
|
|
94
|
-
export function asVideoElement($element) {
|
|
94
|
+
export function asVideoElement($element, isStudioVideo = false) {
|
|
95
|
+
var _$videoElem$contentWi;
|
|
95
96
|
const $videoElem = findMediaPlayerIframe($element);
|
|
96
97
|
if (!isVideoElement($videoElem) && !isStudioEmbeddedMedia($videoElem)) {
|
|
97
98
|
return null;
|
|
@@ -100,19 +101,26 @@ export function asVideoElement($element) {
|
|
|
100
101
|
...fromVideoEmbed($videoElem),
|
|
101
102
|
$element,
|
|
102
103
|
type: VIDEO_EMBED_TYPE,
|
|
103
|
-
id: $videoElem.parentElement?.getAttribute('data-mce-p-data-media-id') || $videoElem.getAttribute('data-mce-p-data-media-id')
|
|
104
|
+
id: $videoElem.parentElement?.getAttribute('data-mce-p-data-media-id') || $videoElem.getAttribute('data-mce-p-data-media-id'),
|
|
105
|
+
viewerRestrictions: isStudioVideo ? {} : (_$videoElem$contentWi = $videoElem.contentWindow?.['env'.toUpperCase()]?.media_object?.viewer_restrictions) !== null && _$videoElem$contentWi !== void 0 ? _$videoElem$contentWi : {}
|
|
104
106
|
};
|
|
105
107
|
}
|
|
106
108
|
export function asAudioElement($element) {
|
|
109
|
+
var _$audioIframe$content;
|
|
107
110
|
if (!$element) {
|
|
108
111
|
return null;
|
|
109
112
|
}
|
|
110
113
|
const $audioIframe = $element.tagName === 'IFRAME' ? $element : $element.firstElementChild;
|
|
111
114
|
const $tinymceIframeShim = $audioIframe.parentElement;
|
|
112
115
|
const title = ($audioIframe.getAttribute('title') || $tinymceIframeShim.getAttribute('data-mce-p-title') || '').replace(formatMessage('Video player for '), '');
|
|
116
|
+
const containerRect = $element.getBoundingClientRect();
|
|
113
117
|
const audioOptions = {
|
|
114
118
|
titleText: title,
|
|
115
|
-
id: $element.parentElement?.getAttribute('data-mce-p-data-media-id') || $element.getAttribute('data-mce-p-data-media-id')
|
|
119
|
+
id: $element.parentElement?.getAttribute('data-mce-p-data-media-id') || $element.getAttribute('data-mce-p-data-media-id'),
|
|
120
|
+
containerDimensions: {
|
|
121
|
+
width: containerRect.width,
|
|
122
|
+
height: containerRect.height
|
|
123
|
+
}
|
|
116
124
|
};
|
|
117
125
|
if ($audioIframe.tagName === 'IFRAME') {
|
|
118
126
|
const audioDoc = $audioIframe.contentDocument;
|
|
@@ -129,6 +137,7 @@ export function asAudioElement($element) {
|
|
|
129
137
|
if (matches) {
|
|
130
138
|
audioOptions.attachmentId = matches[1];
|
|
131
139
|
}
|
|
140
|
+
audioOptions.viewerRestrictions = (_$audioIframe$content = $audioIframe.contentWindow?.['env'.toUpperCase()]?.media_object?.viewer_restrictions) !== null && _$audioIframe$content !== void 0 ? _$audioIframe$content : {};
|
|
132
141
|
return audioOptions;
|
|
133
142
|
}
|
|
134
143
|
function asText($element, editor) {
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
|
|
19
19
|
import React from 'react';
|
|
20
20
|
import { func, shape, string, object } from 'prop-types';
|
|
21
|
-
import { ScreenReaderContent } from '@instructure/ui-a11y-content';
|
|
22
21
|
import { NumberInput } from '@instructure/ui-number-input';
|
|
23
22
|
export default function DimensionInput(props) {
|
|
24
23
|
const {
|
|
@@ -43,7 +42,7 @@ export default function DimensionInput(props) {
|
|
|
43
42
|
}
|
|
44
43
|
return /*#__PURE__*/React.createElement(NumberInput, {
|
|
45
44
|
allowStringValue: true,
|
|
46
|
-
renderLabel:
|
|
45
|
+
renderLabel: label,
|
|
47
46
|
onChange: handleChange,
|
|
48
47
|
onDecrement: handleDecrement,
|
|
49
48
|
onIncrement: handleIncrement,
|
|
@@ -17,13 +17,13 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import React from 'react';
|
|
20
|
-
import { bool, func, number, shape, string
|
|
20
|
+
import { bool, func, number, object, shape, string } from 'prop-types';
|
|
21
21
|
import { ScreenReaderContent } from '@instructure/ui-a11y-content';
|
|
22
|
+
import { Flex } from '@instructure/ui-flex';
|
|
22
23
|
import { FormFieldGroup } from '@instructure/ui-form-field';
|
|
23
24
|
import { IconLockLine, IconWarningSolid } from '@instructure/ui-icons';
|
|
24
|
-
import { Flex } from '@instructure/ui-flex';
|
|
25
|
-
import { Text } from '@instructure/ui-text';
|
|
26
25
|
import { RadioInput, RadioInputGroup } from '@instructure/ui-radio-input';
|
|
26
|
+
import { Text } from '@instructure/ui-text';
|
|
27
27
|
import formatMessage from '../../../../format-message';
|
|
28
28
|
import DimensionInput from './DimensionInput';
|
|
29
29
|
export { default as useDimensionsState } from './useDimensionsState';
|
|
@@ -39,8 +39,9 @@ const errorMessage = message => {
|
|
|
39
39
|
}, message));
|
|
40
40
|
};
|
|
41
41
|
const getMessage = (dimensionsState, minWidth, minHeight, minPercentage) => {
|
|
42
|
+
const baseHint = formatMessage('Aspect ratio will be preserved');
|
|
42
43
|
let result = {
|
|
43
|
-
text:
|
|
44
|
+
text: baseHint,
|
|
44
45
|
type: 'hint'
|
|
45
46
|
};
|
|
46
47
|
if (dimensionsState.usePercentageUnits) {
|
|
@@ -102,11 +103,9 @@ export default function DimensionsInput(props) {
|
|
|
102
103
|
};
|
|
103
104
|
return /*#__PURE__*/React.createElement(Flex, {
|
|
104
105
|
direction: "column"
|
|
105
|
-
}, /*#__PURE__*/React.createElement(Flex.Item, {
|
|
106
|
+
}, !hidePercentage && /*#__PURE__*/React.createElement(Flex.Item, {
|
|
106
107
|
padding: "small"
|
|
107
|
-
},
|
|
108
|
-
weight: "bold"
|
|
109
|
-
}, formatMessage('Custom width and height (Pixels)')) : /*#__PURE__*/React.createElement(RadioInputGroup, {
|
|
108
|
+
}, /*#__PURE__*/React.createElement(RadioInputGroup, {
|
|
110
109
|
"data-testid": "dimension-type",
|
|
111
110
|
name: "dimension-type",
|
|
112
111
|
description: formatMessage('Dimension Type'),
|
|
@@ -119,11 +118,11 @@ export default function DimensionsInput(props) {
|
|
|
119
118
|
label: formatMessage('Pixels'),
|
|
120
119
|
value: "pixels"
|
|
121
120
|
}))), /*#__PURE__*/React.createElement(Flex.Item, {
|
|
122
|
-
|
|
121
|
+
overflowX: "hidden"
|
|
123
122
|
}, /*#__PURE__*/React.createElement(FormFieldGroup, {
|
|
124
|
-
description: /*#__PURE__*/React.createElement(ScreenReaderContent, null, formatMessage('Dimensions'))
|
|
123
|
+
description: /*#__PURE__*/React.createElement(ScreenReaderContent, null, formatMessage('Custom Dimensions'))
|
|
125
124
|
}, /*#__PURE__*/React.createElement(Flex, {
|
|
126
|
-
alignItems: "
|
|
125
|
+
alignItems: "end",
|
|
127
126
|
direction: "row",
|
|
128
127
|
"data-testid": "input-number-container"
|
|
129
128
|
}, dimensionsState.usePercentageUnits ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Flex.Item, {
|
|
@@ -145,7 +144,7 @@ export default function DimensionsInput(props) {
|
|
|
145
144
|
messages: [secondaryMessage],
|
|
146
145
|
dimensionsRef: dimensionsRef
|
|
147
146
|
})), /*#__PURE__*/React.createElement(Flex.Item, {
|
|
148
|
-
padding: "x-small small"
|
|
147
|
+
padding: "0 x-small small"
|
|
149
148
|
}, /*#__PURE__*/React.createElement(IconLockLine, null)), /*#__PURE__*/React.createElement(Flex.Item, {
|
|
150
149
|
shouldShrink: true
|
|
151
150
|
}, /*#__PURE__*/React.createElement(DimensionInput, {
|
|
@@ -34,7 +34,8 @@ function parseAsInteger(inputString) {
|
|
|
34
34
|
function inputValueFor(initialNumber) {
|
|
35
35
|
return Number.isFinite(initialNumber) ? `${initialNumber}` : '';
|
|
36
36
|
}
|
|
37
|
-
export default function useDimensionsState(initialDimensions, constraints) {
|
|
37
|
+
export default function useDimensionsState(initialDimensions, constraints, options = {}) {
|
|
38
|
+
var _options$scaleFns$hei, _options$scaleFns$wid;
|
|
38
39
|
const {
|
|
39
40
|
appliedHeight,
|
|
40
41
|
appliedWidth,
|
|
@@ -73,8 +74,8 @@ export default function useDimensionsState(initialDimensions, constraints) {
|
|
|
73
74
|
percentage: minPercentage
|
|
74
75
|
};
|
|
75
76
|
const dimensionScaleFns = {
|
|
76
|
-
height: scaleForHeight,
|
|
77
|
-
width: scaleForWidth
|
|
77
|
+
height: (_options$scaleFns$hei = options.scaleFns?.height) !== null && _options$scaleFns$hei !== void 0 ? _options$scaleFns$hei : scaleForHeight,
|
|
78
|
+
width: (_options$scaleFns$wid = options.scaleFns?.width) !== null && _options$scaleFns$wid !== void 0 ? _options$scaleFns$wid : scaleForWidth
|
|
78
79
|
};
|
|
79
80
|
function updateDimensions(attributes) {
|
|
80
81
|
setDimensions({
|
|
@@ -18,14 +18,29 @@ export interface StudioMediaOptionsAttributes {
|
|
|
18
18
|
export declare const parsedStudioOptionsPropType: import("prop-types").Requireable<import("prop-types").InferProps<{
|
|
19
19
|
resizable: import("prop-types").Validator<boolean>;
|
|
20
20
|
convertibleToLink: import("prop-types").Validator<boolean>;
|
|
21
|
+
isImprovedEmbed: import("prop-types").Validator<boolean>;
|
|
21
22
|
}>>;
|
|
22
23
|
export type ParsedStudioOptions = {
|
|
23
24
|
resizable: boolean;
|
|
24
25
|
convertibleToLink: boolean;
|
|
26
|
+
isImprovedEmbed: boolean;
|
|
27
|
+
embedOptions: StudioEmbedOptions;
|
|
28
|
+
};
|
|
29
|
+
type ValidStudioEmbedType = 'thumbnail_embed' | 'learn_embed' | 'collaboration_embed';
|
|
30
|
+
export type StudioEmbedTypeChangedResponse = {
|
|
31
|
+
subject: 'studio.embedTypeChanged.response';
|
|
32
|
+
width: number;
|
|
33
|
+
height: number;
|
|
34
|
+
embedType: ValidStudioEmbedType;
|
|
35
|
+
resizable?: boolean;
|
|
25
36
|
};
|
|
26
37
|
export declare function isStudioContentItemCustomJson(input: any): input is StudioContentItemCustomJson;
|
|
38
|
+
export declare const isValidEmbedType: (embedType: any) => embedType is ValidStudioEmbedType;
|
|
39
|
+
export declare const isValidDimension: (value: any) => value is number;
|
|
40
|
+
export declare const isValidResizable: (value: any) => value is boolean;
|
|
27
41
|
export declare function studioAttributesFrom(customJson: StudioContentItemCustomJson): StudioMediaOptionsAttributes;
|
|
28
42
|
export declare function displayStyleFrom(studioAttributes: StudioMediaOptionsAttributes | null): 'inline-block' | '';
|
|
43
|
+
export declare function isImprovedStudioEmbed(element: Element): boolean;
|
|
29
44
|
export declare function isStudioEmbeddedMedia(element: Element): boolean;
|
|
30
45
|
export declare function parseStudioOptions(element: Element | null): ParsedStudioOptions;
|
|
31
46
|
/**
|
|
@@ -36,11 +51,17 @@ export declare function parseStudioOptions(element: Element | null): ParsedStudi
|
|
|
36
51
|
*/
|
|
37
52
|
export declare function handleBeforeObjectSelected(e: EditorEvent<Events.ObjectSelectedEvent>): void;
|
|
38
53
|
export declare function findStudioLtiIframeFromSelection(selectedNode: Node): HTMLIFrameElement | null;
|
|
39
|
-
export declare const notifyStudioEmbedTypeChange: (editor: Editor, embedType: "thumbnail_embed" | "learn_embed" | "collaboration_embed") => void;
|
|
40
54
|
export type EmbedType = 'thumbnail_embed' | 'learn_embed' | 'collaboration_embed';
|
|
41
|
-
export declare const
|
|
42
|
-
|
|
43
|
-
export declare const
|
|
44
|
-
export
|
|
45
|
-
|
|
55
|
+
export declare const notifyStudioEmbedTypeChange: (editor: Editor, embedType: EmbedType) => void;
|
|
56
|
+
export declare const validateStudioEmbedTypeChangeResponse: (data: any) => data is StudioEmbedTypeChangedResponse;
|
|
57
|
+
export declare const updateStudioIframeDimensions: (editor: Editor, data: StudioEmbedTypeChangedResponse) => void;
|
|
58
|
+
export type StudioEmbedOptions = {
|
|
59
|
+
enableMediaDownload: boolean;
|
|
60
|
+
enableTranscriptDownload: boolean;
|
|
61
|
+
lockSpeed: boolean;
|
|
62
|
+
isExternal: boolean;
|
|
63
|
+
showRollingTranscript: boolean;
|
|
64
|
+
};
|
|
65
|
+
export declare function validateStudioEmbedOptions(input: any): input is StudioEmbedOptions;
|
|
66
|
+
export declare function updateStudioEmbedOptions(editor: Editor, embedOptions: StudioEmbedOptions, videoContainer: Element | null): void;
|
|
46
67
|
export {};
|
|
@@ -28,11 +28,21 @@ import { findMediaPlayerIframe } from './iframeUtils';
|
|
|
28
28
|
|
|
29
29
|
export const parsedStudioOptionsPropType = shape({
|
|
30
30
|
resizable: bool.isRequired,
|
|
31
|
-
convertibleToLink: bool.isRequired
|
|
31
|
+
convertibleToLink: bool.isRequired,
|
|
32
|
+
isImprovedEmbed: bool.isRequired
|
|
32
33
|
});
|
|
33
34
|
export function isStudioContentItemCustomJson(input) {
|
|
34
35
|
return typeof input === 'object' && input.source === 'studio';
|
|
35
36
|
}
|
|
37
|
+
export const isValidEmbedType = embedType => {
|
|
38
|
+
return typeof embedType === 'string' && ['thumbnail_embed', 'learn_embed', 'collaboration_embed'].includes(embedType);
|
|
39
|
+
};
|
|
40
|
+
export const isValidDimension = value => {
|
|
41
|
+
return typeof value === 'number' && !isNaN(value) && isFinite(value) && value > 0;
|
|
42
|
+
};
|
|
43
|
+
export const isValidResizable = value => {
|
|
44
|
+
return typeof value === 'boolean';
|
|
45
|
+
};
|
|
36
46
|
export function studioAttributesFrom(customJson) {
|
|
37
47
|
var _customJson$resizable, _customJson$enableMed;
|
|
38
48
|
return {
|
|
@@ -45,6 +55,10 @@ export function displayStyleFrom(studioAttributes) {
|
|
|
45
55
|
if (!studioAttributes) return '';
|
|
46
56
|
return studioAttributes['data-studio-resizable'] || studioAttributes['data-studio-tray-enabled'] ? 'inline-block' : '';
|
|
47
57
|
}
|
|
58
|
+
export function isImprovedStudioEmbed(element) {
|
|
59
|
+
const src = element.getAttribute('data-mce-p-src') || '';
|
|
60
|
+
return src.includes('thumbnail_embed') || src.includes('learn_embed') || src.includes('collaboration_embed');
|
|
61
|
+
}
|
|
48
62
|
export function isStudioEmbeddedMedia(element) {
|
|
49
63
|
// Borrowing this structure from isMediaElement in ContentSelection.js
|
|
50
64
|
const tinymceIframeShim = element?.tagName === 'IFRAME' ? element?.parentElement : element;
|
|
@@ -55,9 +69,26 @@ export function isStudioEmbeddedMedia(element) {
|
|
|
55
69
|
}
|
|
56
70
|
export function parseStudioOptions(element) {
|
|
57
71
|
const tinymceIframeShim = element?.tagName === 'IFRAME' ? element?.parentElement : element;
|
|
72
|
+
const embedOptions = {};
|
|
73
|
+
const href = tinymceIframeShim?.getAttribute('data-mce-p-src');
|
|
74
|
+
if (href) {
|
|
75
|
+
// parse out embed options from url params
|
|
76
|
+
const urlMatch = href.match(/url=([^&]*)$/);
|
|
77
|
+
if (urlMatch) {
|
|
78
|
+
const url = new URL(decodeURIComponent(urlMatch[1]));
|
|
79
|
+
const params = url.searchParams;
|
|
80
|
+
embedOptions['enableMediaDownload'] = params.get('custom_arc_display_download') === 'true';
|
|
81
|
+
embedOptions['enableTranscriptDownload'] = params.get('custom_arc_transcript_downloadable') === 'true';
|
|
82
|
+
embedOptions['showRollingTranscript'] = params.get('custom_arc_show_rolling_transcript') === 'true';
|
|
83
|
+
embedOptions['lockSpeed'] = params.get('custom_arc_lock_speed') === 'true';
|
|
84
|
+
embedOptions['isExternal'] = params.get('custom_arc_is_external') === 'true';
|
|
85
|
+
}
|
|
86
|
+
}
|
|
58
87
|
return {
|
|
59
88
|
resizable: tinymceIframeShim?.getAttribute('data-mce-p-data-studio-resizable') === 'true',
|
|
60
|
-
convertibleToLink: tinymceIframeShim?.getAttribute('data-mce-p-data-studio-convertible-to-link') === 'true'
|
|
89
|
+
convertibleToLink: tinymceIframeShim?.getAttribute('data-mce-p-data-studio-convertible-to-link') === 'true',
|
|
90
|
+
isImprovedEmbed: tinymceIframeShim ? isImprovedStudioEmbed(tinymceIframeShim) : false,
|
|
91
|
+
embedOptions
|
|
61
92
|
};
|
|
62
93
|
}
|
|
63
94
|
|
|
@@ -123,14 +154,23 @@ export const notifyStudioEmbedTypeChange = (editor, embedType) => {
|
|
|
123
154
|
}, '*');
|
|
124
155
|
}
|
|
125
156
|
};
|
|
126
|
-
export const
|
|
157
|
+
export const validateStudioEmbedTypeChangeResponse = data => {
|
|
158
|
+
return isValidDimension(data.width) && isValidDimension(data.height) && isValidEmbedType(data.embedType);
|
|
159
|
+
};
|
|
160
|
+
export const updateStudioIframeDimensions = (editor, data) => {
|
|
161
|
+
const {
|
|
162
|
+
width,
|
|
163
|
+
height,
|
|
164
|
+
embedType,
|
|
165
|
+
resizable
|
|
166
|
+
} = data;
|
|
127
167
|
const selectedNode = editor.selection.getNode();
|
|
128
168
|
const videoContainer = findMediaPlayerIframe(selectedNode);
|
|
129
169
|
if (videoContainer?.tagName !== 'IFRAME') {
|
|
130
170
|
return;
|
|
131
171
|
}
|
|
132
172
|
const tinymceIframeShim = videoContainer.parentElement;
|
|
133
|
-
if (!tinymceIframeShim) {
|
|
173
|
+
if (!tinymceIframeShim || !videoContainer) {
|
|
134
174
|
return;
|
|
135
175
|
}
|
|
136
176
|
editor.dom.setStyles(tinymceIframeShim, {
|
|
@@ -141,7 +181,7 @@ export const updateStudioIframeDimensions = (editor, width, height, embedType, r
|
|
|
141
181
|
width: `${width}px`,
|
|
142
182
|
height: `${height}px`
|
|
143
183
|
});
|
|
144
|
-
if (resizable !== undefined) {
|
|
184
|
+
if (resizable !== undefined && isValidResizable(resizable)) {
|
|
145
185
|
// Update both the actual attribute and the TinyMCE prefixed version
|
|
146
186
|
// This ensures they stay in sync when content is saved and reloaded
|
|
147
187
|
editor.dom.setAttrib(tinymceIframeShim, 'data-studio-resizable', String(resizable));
|
|
@@ -172,12 +212,41 @@ export const updateStudioIframeDimensions = (editor, width, height, embedType, r
|
|
|
172
212
|
height
|
|
173
213
|
});
|
|
174
214
|
};
|
|
175
|
-
|
|
176
|
-
|
|
215
|
+
const embedOptionsKeyMap = {
|
|
216
|
+
enableMediaDownload: 'custom_arc_display_download',
|
|
217
|
+
enableTranscriptDownload: 'custom_arc_transcript_downloadable',
|
|
218
|
+
showRollingTranscript: 'custom_arc_show_rolling_transcript',
|
|
219
|
+
lockSpeed: 'custom_arc_lock_speed',
|
|
220
|
+
isExternal: 'custom_arc_is_external'
|
|
177
221
|
};
|
|
178
|
-
export
|
|
179
|
-
return typeof
|
|
180
|
-
}
|
|
181
|
-
export
|
|
182
|
-
|
|
183
|
-
|
|
222
|
+
export function validateStudioEmbedOptions(input) {
|
|
223
|
+
return typeof input === 'object' && (Object.keys(input).length === 0 || typeof input.isExternal === 'boolean' || typeof input.enableMediaDownload === 'boolean' || typeof input.enableTranscriptDownload === 'boolean' || typeof input.showRollingTranscript === 'boolean' || typeof input.lockSpeed === 'boolean');
|
|
224
|
+
}
|
|
225
|
+
export function updateStudioEmbedOptions(editor, embedOptions, videoContainer) {
|
|
226
|
+
if (videoContainer?.tagName !== 'IFRAME') {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
const tinymceIframeShim = videoContainer.parentElement;
|
|
230
|
+
if (!tinymceIframeShim) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const href = editor.dom.getAttrib(tinymceIframeShim, 'data-mce-p-src');
|
|
234
|
+
if (!href) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const urlMatch = href.match(/url=([^&]*)$/);
|
|
238
|
+
const url = new URL(decodeURIComponent(urlMatch ? urlMatch[1] : ''));
|
|
239
|
+
const params = url.searchParams;
|
|
240
|
+
for (const param of Object.values(embedOptionsKeyMap)) {
|
|
241
|
+
params.delete(param);
|
|
242
|
+
}
|
|
243
|
+
if (embedOptions) {
|
|
244
|
+
for (const [option, param] of Object.entries(embedOptionsKeyMap)) {
|
|
245
|
+
if (embedOptions[option]) {
|
|
246
|
+
params.set(param, 'true');
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
const newHref = href.replace(/(url=)(.*)$/, `$1${encodeURIComponent(url.toString())}`);
|
|
251
|
+
editor.dom.setAttrib(tinymceIframeShim, 'data-mce-p-src', newHref);
|
|
252
|
+
}
|
|
@@ -21,7 +21,6 @@ import React, { useEffect, useState } from 'react';
|
|
|
21
21
|
import ReactDOM from 'react-dom';
|
|
22
22
|
import { px } from '@instructure/ui-utils';
|
|
23
23
|
import indicatorRegion from '../../../indicatorRegion';
|
|
24
|
-
import { isAudioOrVideo, isImage } from '../fileTypeUtils';
|
|
25
24
|
import indicate from '../../../../common/indicate';
|
|
26
25
|
import { StoreProvider } from '../StoreContext';
|
|
27
26
|
import Bridge from '../../../../bridge';
|
|
@@ -63,13 +62,7 @@ _source, afterInsert = () => undefined) => {
|
|
|
63
62
|
displayAs,
|
|
64
63
|
usageRights: uploadData?.usageRights?.usageRight === 'choose' ? undefined : uploadData?.usageRights
|
|
65
64
|
};
|
|
66
|
-
|
|
67
|
-
if (isImage(theFile.type)) {
|
|
68
|
-
tabContext = 'images';
|
|
69
|
-
} else if (isAudioOrVideo(theFile.type)) {
|
|
70
|
-
tabContext = 'media';
|
|
71
|
-
}
|
|
72
|
-
storeProps.startMediaUpload(tabContext, fileMetaData);
|
|
65
|
+
storeProps.startMediaUpload(fileMetaData);
|
|
73
66
|
break;
|
|
74
67
|
}
|
|
75
68
|
case 'URL':
|
package/es/rce/style.d.ts
CHANGED