contentscript.js 2.4 KiB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import html from 'nanohtml';
  2. import { remoteFunction } from 'webextension-rpc';
  3. import { createMediaFragmentIdentifier } from '../util/media-fragment-identifier';
  4. function createPreciseUrl(url, selector) {
  5. const properUrl = url.split('#')[0];
  6. let fragmentIdentifier;
  7. if (selector.type === 'FragmentSelector') {
  8. fragmentIdentifier = selector.value;
  9. } else {
  10. throw new Error('Unsupported selector type');
  11. }
  12. return properUrl + '#' + fragmentIdentifier;
  13. }
  14. function describeMediaFragment({ start, end }) {
  15. const fragmentIdentifier = createMediaFragmentIdentifier({ start, end });
  16. const selector = {
  17. type: 'FragmentSelector',
  18. conformsTo: 'http://www.w3.org/TR/media-frags/',
  19. value: fragmentIdentifier,
  20. };
  21. return selector;
  22. }
  23. async function init() {
  24. let menuEl;
  25. function hideMenu() {
  26. if (!menuEl) return;
  27. menuEl.parentNode.removeChild(menuEl);
  28. menuEl = undefined;
  29. }
  30. function onContextMenu(event) {
  31. event.preventDefault();
  32. const left = event.pageX;
  33. const top = event.pageY;
  34. const playlist = self.playlist;
  35. if (!playlist) {
  36. throw new Error('Player has not been initialised.');
  37. }
  38. const trackDuration = playlist.duration;
  39. let { start, end } = playlist.getTimeSelection();
  40. if (start === undefined) return;
  41. // Waveform Playlist tells us end=start when the selection is just a single line.
  42. if (end === start) end = undefined;
  43. // Round the numbers to two decimals.
  44. // Also, as Waveform Playlist might report a slightly negative number, first cap it to zero.
  45. start = Math.round(Math.max(0, start) * 100) / 100;
  46. if (end !== undefined) end = Math.round(Math.max(0, end) * 100) / 100;
  47. async function createBookmark() {
  48. const fileUrl = document.URL;
  49. const selector = describeMediaFragment({ start, end });
  50. const bookmarkUrl = createPreciseUrl(fileUrl, selector);
  51. await remoteFunction('createBookmark')({ url: bookmarkUrl, start, end, trackDuration });
  52. }
  53. hideMenu();
  54. menuEl = html`
  55. <ul class="context-menu" style="top: ${top}; left: ${left};">
  56. <li>
  57. <button onclick=${createBookmark}>
  58. ${browser.i18n.getMessage(end !== undefined
  59. ? 'bookmarkSelectionContextMenuItemForFragment'
  60. : 'bookmarkSelectionContextMenuItemForSingleMoment'
  61. )}
  62. </button>
  63. </li>
  64. </ul>
  65. `;
  66. document.body.appendChild(menuEl);
  67. }
  68. document.addEventListener('contextmenu', onContextMenu, false);
  69. document.addEventListener('click', event => { hideMenu(); });
  70. }
  71. init();