MDL-83108 tiny_h5p: New option to enable auto-play in the app

This commit is contained in:
Albert Gasset 2025-02-21 11:01:57 +01:00
parent 7a318d5c85
commit 22f97671d5
7 changed files with 89 additions and 4 deletions

View File

@ -5,6 +5,6 @@ define("tiny_h5p/ui",["exports","editor_tiny/utils","./common","./options","core
* @module tiny_h5p/ui
* @copyright 2022 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.handleAction=void 0,_config=_interopRequireDefault(_config),_modal=_interopRequireDefault(_modal),_modal_events=_interopRequireDefault(_modal_events),_pending=_interopRequireDefault(_pending);let openingSelection=null;_exports.handleAction=editor=>{openingSelection=editor.selection.getBookmark(),displayDialogue(editor)};const getTemplateContext=(editor,data)=>{var _ref,_permissions$embed,_data$url;const permissions=(0,_options.getPermissions)(editor),canShowFilePicker=void 0!==(0,_options2.getFilePicker)(editor,"h5p"),canUpload=null!==(_ref=permissions.upload&&canShowFilePicker)&&void 0!==_ref&&_ref,canEmbed=null!==(_permissions$embed=permissions.embed)&&void 0!==_permissions$embed&&_permissions$embed,canUploadAndEmbed=canUpload&&canEmbed;return Object.assign({},{elementid:editor.id,canUpload:canUpload,canEmbed:canEmbed,canUploadAndEmbed:canUploadAndEmbed,showOptions:!1,fileURL:null!==(_data$url=null==data?void 0:data.url)&&void 0!==_data$url?_data$url:""},data)},isValidUrl=url=>!!new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*").test(url),handleDialogueSubmission=async(editor,modal,data)=>{const pendingPromise=new _pending.default("tiny_h5p:handleDialogueSubmission"),form=(0,_normalise.getList)(modal.getRoot())[0].querySelector("form");if(!form)return modal.destroy(),displayDialogue(editor,Object.assign({},data)),void pendingPromise.resolve();const submittedUrl=form.querySelector('input[name="url"]').value,url=((form,submittedUrl)=>{if(!submittedUrl||!submittedUrl.startsWith(_config.default.wwwroot)&&!isValidUrl(submittedUrl))return null;const url=new URL(submittedUrl),downloadElement=form.querySelector('[name="download"]');null!=downloadElement&&downloadElement.checked&&url.searchParams.append("export",1);const embedElement=form.querySelector('[name="embed"]');null!=embedElement&&embedElement.checked&&url.searchParams.append("embed",1);const copyrightElement=form.querySelector('[name="copyright"]');return null!=copyrightElement&&copyrightElement.checked&&url.searchParams.append("copyright",1),url})(form,submittedUrl);if(!url)return modal.destroy(),displayDialogue(editor,Object.assign({},data,{url:submittedUrl,invalidUrl:!0})),void pendingPromise.resolve();const content=await(0,_templates.renderForPromise)("".concat(_common.component,"/content"),{url:url.toString()});editor.selection.moveToBookmark(openingSelection),editor.execCommand("mceInsertContent",!1,content.html),editor.selection.moveToBookmark(openingSelection),pendingPromise.resolve()},getCurrentH5PData=currentH5P=>{const data={};let url;try{url=new URL(currentH5P.textContent)}catch(error){return data}return url.searchParams.has("export")&&(data.download=!0,data.showOptions=!0,url.searchParams.delete("export")),url.searchParams.has("embed")&&(data.embed=!0,data.showOptions=!0,url.searchParams.delete("embed")),url.searchParams.has("copyright")&&(data.copyright=!0,data.showOptions=!0,url.searchParams.delete("copyright")),data.url=url.toString(),data},displayDialogue=async function(editor){let data=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const selection=editor.selection.getNode(),currentH5P=selection.closest(".h5p-placeholder");currentH5P&&Object.assign(data,getCurrentH5PData(currentH5P));const modal=await _modal.default.create({templateContext:getTemplateContext(editor,data)}),$root=modal.getRoot(),root=$root[0];$root.on(_modal_events.default.save,((event,modal)=>{handleDialogueSubmission(editor,modal,data)})),root.addEventListener("click",(e=>{e.target.closest('[data-target="filepicker"]')&&(0,_utils.displayFilepicker)(editor,"h5p").then((params=>{if(""!==params.url){root.querySelector('form input[name="url"]').value=params.url}return params})).catch()}))}}));
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.handleAction=void 0,_config=_interopRequireDefault(_config),_modal=_interopRequireDefault(_modal),_modal_events=_interopRequireDefault(_modal_events),_pending=_interopRequireDefault(_pending);let openingSelection=null;_exports.handleAction=editor=>{openingSelection=editor.selection.getBookmark(),displayDialogue(editor)};const getTemplateContext=(editor,data)=>{var _ref,_permissions$embed,_data$url;const permissions=(0,_options.getPermissions)(editor),canShowFilePicker=void 0!==(0,_options2.getFilePicker)(editor,"h5p"),canUpload=null!==(_ref=permissions.upload&&canShowFilePicker)&&void 0!==_ref&&_ref,canEmbed=null!==(_permissions$embed=permissions.embed)&&void 0!==_permissions$embed&&_permissions$embed,canUploadAndEmbed=canUpload&&canEmbed;return Object.assign({},{elementid:editor.id,canUpload:canUpload,canEmbed:canEmbed,canUploadAndEmbed:canUploadAndEmbed,showOptions:!1,fileURL:null!==(_data$url=null==data?void 0:data.url)&&void 0!==_data$url?_data$url:"",showDisplayOptions:!1},data)},isValidUrl=url=>!!new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*").test(url),handleDialogueSubmission=async(editor,modal,data)=>{var _form$querySelector;const pendingPromise=new _pending.default("tiny_h5p:handleDialogueSubmission"),form=(0,_normalise.getList)(modal.getRoot())[0].querySelector("form");if(!form)return modal.destroy(),displayDialogue(editor,Object.assign({},data)),void pendingPromise.resolve();const submittedUrl=form.querySelector('input[name="url"]').value,url=((form,submittedUrl)=>{if(!submittedUrl||!submittedUrl.startsWith(_config.default.wwwroot)&&!isValidUrl(submittedUrl))return null;const url=new URL(submittedUrl),downloadElement=form.querySelector('[name="download"]');null!=downloadElement&&downloadElement.checked&&url.searchParams.append("export",1);const embedElement=form.querySelector('[name="embed"]');null!=embedElement&&embedElement.checked&&url.searchParams.append("embed",1);const copyrightElement=form.querySelector('[name="copyright"]');return null!=copyrightElement&&copyrightElement.checked&&url.searchParams.append("copyright",1),url})(form,submittedUrl);if(!url)return modal.destroy(),displayDialogue(editor,Object.assign({},data,{url:submittedUrl,invalidUrl:!0})),void pendingPromise.resolve();const mobileAppAutoPlay=null===(_form$querySelector=form.querySelector('[name="mobileappautoplay"]'))||void 0===_form$querySelector?void 0:_form$querySelector.checked,content=await(0,_templates.renderForPromise)("".concat(_common.component,"/content"),{url:url.toString(),mobileAppAutoPlay:mobileAppAutoPlay});editor.selection.moveToBookmark(openingSelection),editor.execCommand("mceInsertContent",!1,content.html),editor.selection.moveToBookmark(openingSelection),pendingPromise.resolve()},getCurrentH5PData=currentH5P=>{const data={};let url;try{url=new URL(currentH5P.textContent)}catch(error){return data}return url.searchParams.has("export")&&(data.download=!0,data.showOptions=!0,url.searchParams.delete("export")),url.searchParams.has("embed")&&(data.embed=!0,data.showOptions=!0,url.searchParams.delete("embed")),url.searchParams.has("copyright")&&(data.copyright=!0,data.showOptions=!0,url.searchParams.delete("copyright")),"true"==currentH5P.dataset.mobileappAutoplay&&(data.mobileAppAutoPlay=!0,data.showDisplayOptions=!0),data.url=url.toString(),data},displayDialogue=async function(editor){let data=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const selection=editor.selection.getNode(),currentH5P=selection.closest(".h5p-placeholder");currentH5P&&Object.assign(data,getCurrentH5PData(currentH5P));const modal=await _modal.default.create({templateContext:getTemplateContext(editor,data)}),$root=modal.getRoot(),root=$root[0];$root.on(_modal_events.default.save,((event,modal)=>{handleDialogueSubmission(editor,modal,data)})),root.addEventListener("click",(e=>{e.target.closest('[data-target="filepicker"]')&&(0,_utils.displayFilepicker)(editor,"h5p").then((params=>{if(""!==params.url){root.querySelector('form input[name="url"]').value=params.url}return params})).catch()}))}}));
//# sourceMappingURL=ui.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -62,6 +62,7 @@ const getTemplateContext = (editor, data) => {
canUploadAndEmbed,
showOptions: false,
fileURL: data?.url ?? '',
showDisplayOptions: false,
}, data);
};
@ -142,8 +143,11 @@ const handleDialogueSubmission = async(editor, modal, data) => {
return;
}
const mobileAppAutoPlay = form.querySelector('[name="mobileappautoplay"]')?.checked;
const content = await renderForPromise(`${component}/content`, {
url: url.toString(),
mobileAppAutoPlay,
});
editor.selection.moveToBookmark(openingSelection);
@ -179,7 +183,12 @@ const getCurrentH5PData = (currentH5P) => {
url.searchParams.delete('copyright');
}
data.url = url.toString();
if (currentH5P.dataset.mobileappAutoplay == 'true') {
data.mobileAppAutoPlay = true;
data.showDisplayOptions = true;
}
data.url = url.toString();
return data;
};

View File

@ -28,6 +28,7 @@ $string['insert'] = 'Insert H5P content';
$string['pluginname'] = 'Insert H5P';
$string['browserepositories'] = 'Browse repositories...';
$string['copyrightbutton'] = 'Copyright button';
$string['displayoptions'] = 'Display options';
$string['downloadbutton'] = 'Allow download';
$string['embedbutton'] = 'Embed button';
$string['h5p:addembed'] = 'Add embedded H5P';
@ -37,6 +38,7 @@ $string['h5poptions'] = 'H5P options';
$string['h5purl'] = 'H5P URL';
$string['invalidh5purl'] = 'Invalid URL';
$string['instructions'] = 'You can insert H5P content by <strong>either</strong> entering a URL <strong>or</strong> by uploading an H5P file.';
$string['mobileappautoplay'] = 'Auto-play in the mobile app';
$string['noh5pcontent'] = 'No H5P content added';
$string['privacy:metadata'] = 'The H5P plugin for TinyMCE does not store any personal data.';

View File

@ -33,6 +33,6 @@
}
}}
<div class="h5p-placeholder" contenteditable="false">
<div class="h5p-placeholder" contenteditable="false" {{# mobileAppAutoPlay }}data-mobileapp-autoplay="true"{{/ mobileAppAutoPlay }}>
{{ url }}
</div>

View File

@ -154,6 +154,48 @@
</div>
</fieldset>
{{/canUpload}}
<fieldset class="mt-2 collapsible" id="{{elementid}}-{{uniqid}}-display-options">
<legend class="position-relative d-flex ftoggler align-items-center px-1">
<a role="button" data-bs-toggle="collapse"{{!
}} href="#displayoptions"{{!
}} aria-expanded="{{#showDisplayOptions}}true{{/showDisplayOptions}}{{^showDisplayOptions}}false{{/showDisplayOptions}}"{{!
}} aria-controls="displayoptions"{{!
}} class="btn btn-icon me-1 icons-collapse-expand stretched-link fheader {{^showDisplayOptions}}collapsed{{/showDisplayOptions}}"{{!
}}>
<span class="expanded-icon icon-no-margin p-2"
title="{{#str}} collapse, moodle {{/str}}">
<i class="icon fa fa-chevron-down fa-fw " aria-hidden="true"></i>
</span>
<span class="collapsed-icon icon-no-margin p-2"
title="{{#str}} expand, moodle {{/str}}">
<span class="dir-rtl-hide">
<i class="icon fa fa-chevron-right fa-fw " aria-hidden="true"></i>
</span>
<span class="dir-ltr-hide">
<i class="icon fa fa-chevron-left fa-fw " aria-hidden="true"></i>
</span>
</span>
<span class="visually-hidden">{{#str}} displayoptions, tiny_h5p {{/str}}</span>
</a>
<h3 class="d-flex align-self-stretch align-items-center mb-0" aria-hidden="true">
{{#str}} displayoptions, tiny_h5p {{/str}}
</h3>
</legend>
<div id="displayoptions" class="fcontainer collapseable collapse px-1 {{#showDisplayOptions}}show{{/showDisplayOptions}}">
<div class="form-check mb-2">
<input type="checkbox" {{!
}} name="mobileappautoplay"{{!
}} {{# mobileAppAutoPlay }}checked{{/ mobileAppAutoPlay }}{{!
}} class="form-check-input"{{!
}} id="{{elementid}}-{{uniqid}}_display-option-mobileapp-autoplay"{{!
}} />
<label class="form-check-label" for="{{elementid}}-{{uniqid}}_display-option-mobileapp-autoplay">
{{#str}} mobileappautoplay, tiny_h5p{{/str}}
</label>
</div>
</div>
</fieldset>
</div>
</form>
{{/body}}

View File

@ -164,6 +164,38 @@ Feature: Use the TinyMCE editor to upload an h5p package
And I click on "H5P options" "link"
And "input[aria-label=\"Embed button\"]:not([checked=checked])" "css_element" should exist
@javascript
Scenario: Enable/disable display options
Given the following "user private file" exists:
| user | admin |
| filepath | h5p/tests/fixtures/guess-the-answer.h5p |
When I am on the "PageName1" "page activity editing" page logged in as "admin"
And I click on the "Insert H5P content" button for the "Page content" TinyMCE editor
Then "Auto-play in the mobile app" "field" should exist
And the field "Auto-play in the mobile app" matches value "0"
And I click on "Browse repositories..." "button" in the "Insert H5P content" "dialogue"
And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
And I click on "guess-the-answer.h5p" "link"
And I click on "Select this file" "button"
And I click on "Display options" "link"
And I click on "Auto-play in the mobile app" "checkbox"
And I click on "Insert H5P" "button" in the "Insert H5P content" "dialogue"
And I click on "Save and display" "button"
And ".h5p-placeholder[data-mobileapp-autoplay=true]" "css_element" should exist
And I navigate to "Settings" in current page administration
And I select the ".h5p-placeholder" "css_element" in the "Page content" TinyMCE editor
And I click on the "Insert H5P content" button for the "Page content" TinyMCE editor
And the field "Auto-play in the mobile app" matches value "1"
And I click on "Auto-play in the mobile app" "checkbox"
And I click on "Insert H5P" "button" in the "Insert H5P content" "dialogue"
And I wait "1" seconds
And I click on "Save and display" "button"
And ".h5p-placeholder:not([data-mobileapp-autoplay=true])" "css_element" should exist
And I navigate to "Settings" in current page administration
And I select the ".h5p-placeholder" "css_element" in the "Page content" TinyMCE editor
And I click on the "Insert H5P content" button for the "Page content" TinyMCE editor
And the field "Auto-play in the mobile app" matches value "0"
@javascript
Scenario: Private H5P files are shown to students
Given the following "users" exist: