lib/editor/tiny/plugins/media/amd/src/embed.js

  1. // This file is part of Moodle - http://moodle.org/
  2. //
  3. // Moodle is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation, either version 3 of the License, or
  6. // (at your option) any later version.
  7. //
  8. // Moodle is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  15. /**
  16. * Tiny Media plugin Embed class for Moodle.
  17. *
  18. * @module tiny_media/embed
  19. * @copyright 2022 Huong Nguyen <huongnv13@gmail.com>
  20. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  21. */
  22. import EmbedModal from './embedmodal';
  23. import {getEmbedPermissions} from './options';
  24. import {getFilePicker, getContextId} from 'editor_tiny/options';
  25. import {EmbedHandler} from './embed/embedhandler';
  26. import {insertMediaTemplateContext, getSelectedMediaElement} from './embed/embedhelpers';
  27. import {EmbedInsert} from './embed/embedinsert';
  28. import {startMediaLoading} from './helpers';
  29. import Selectors from "./selectors";
  30. export default class MediaEmbed {
  31. editor = null;
  32. canShowFilePicker = false;
  33. canShowFilePickerTrack = false;
  34. canShowDropZone = false;
  35. constructor(editor) {
  36. const permissions = getEmbedPermissions(editor);
  37. const options = getFilePicker(editor, 'media');
  38. // Indicates whether the file picker can be shown.
  39. this.canShowFilePicker = permissions.filepicker
  40. && (typeof options !== 'undefined')
  41. && Object.keys(options.repositories).length > 0;
  42. this.canShowFilePickerTrack = permissions.filepicker && (typeof getFilePicker(editor, 'subtitle') !== 'undefined');
  43. this.canShowDropZone = Object.values(options.repositories).some(repository => repository.type === 'upload');
  44. this.editor = editor;
  45. this.acceptedMediaTypes = options.accepted_types;
  46. this.contextId = getContextId(editor);
  47. // Image options.
  48. const imageOptions = getFilePicker(editor, 'image');
  49. this.acceptedImageTypes = imageOptions.accepted_types;
  50. this.canShowImageFilePicker = permissions.filepicker
  51. && (typeof imageOptions !== 'undefined')
  52. && Object.keys(imageOptions.repositories).length > 0;
  53. }
  54. /**
  55. * Displays media modal accordingly.
  56. */
  57. displayDialogue = async() => {
  58. const [mediaType, selectedMedia] = getSelectedMediaElement(this.editor);
  59. this.mediaType = mediaType;
  60. this.selectedMedia = selectedMedia;
  61. if (this.selectedMedia) {
  62. // Preview the selected media.
  63. this.isUpdating = true;
  64. this.loadSelectedMedia();
  65. } else {
  66. // Create media modal.
  67. await this.createMediaModal();
  68. // Load insert media modal.
  69. await this.loadInsertMediaModal();
  70. }
  71. };
  72. /**
  73. * Load insert media modal.
  74. */
  75. loadInsertMediaModal = async() => {
  76. const embedHandler = new EmbedHandler(this);
  77. embedHandler.loadTemplatePromise(insertMediaTemplateContext(this));
  78. await embedHandler.registerEventListeners();
  79. };
  80. /**
  81. * Create media modal.
  82. */
  83. createMediaModal = async() => {
  84. this.currentModal = await EmbedModal.create({
  85. large: true,
  86. templateContext: {elementid: this.editor.getElement().id},
  87. });
  88. this.modalRoot = this.currentModal.getRoot();
  89. this.root = this.modalRoot[0];
  90. };
  91. /**
  92. * Load media preview based on the selected media.
  93. */
  94. loadSelectedMedia = async() => {
  95. let mediaSource = null;
  96. if (['video', 'audio'].includes(this.mediaType)) {
  97. mediaSource = this.selectedMedia.querySelector('source').src;
  98. // If the selected media has more than one sources, it has main source and alternative sources.
  99. const sources = this.selectedMedia.querySelectorAll('source');
  100. if (sources.length > 1) {
  101. let alternativeSources = [];
  102. Object.keys(sources).forEach(function(source) {
  103. alternativeSources.push(sources[source].src);
  104. });
  105. this.alternativeSources = alternativeSources; // Used to later check if the embedded media has alternative sources.
  106. }
  107. } else if (this.selectedMedia.classList.contains(Selectors.EMBED.externalMediaProvider)) {
  108. mediaSource = this.selectedMedia.href;
  109. this.mediaType = 'link';
  110. }
  111. // Load media preview.
  112. if (this.mediaType) {
  113. // Create media modal.
  114. await this.createMediaModal();
  115. // Start the spinner.
  116. startMediaLoading(this.root, Selectors.EMBED.type);
  117. const embedInsert = new EmbedInsert(this);
  118. embedInsert.init();
  119. embedInsert.loadMediaPreview(mediaSource);
  120. await (new EmbedHandler(this)).registerEventListeners();
  121. } else {
  122. // Create media modal.
  123. await this.createMediaModal();
  124. // Load insert media modal.
  125. this.loadInsertMediaModal();
  126. }
  127. };
  128. }