contentscript.js 2.0 KiB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import { makeRemotelyCallable, remoteFunction } from 'webextension-rpc';
  2. import { parseMediaFragmentIdentifier } from '../util/media-fragment-identifier';
  3. const retrieveBookmarks = remoteFunction('retrieveBookmarks');
  4. function fragmentIdentifierToSelector(fragmentIdentifier) {
  5. if (fragmentIdentifier.startsWith('#')) {
  6. fragmentIdentifier = fragmentIdentifier.substring(1);
  7. }
  8. const selector = {
  9. type: 'FragmentSelector',
  10. value: fragmentIdentifier,
  11. };
  12. return selector;
  13. }
  14. function selectorToTime(selector) {
  15. if (selector.type !== 'FragmentSelector') {
  16. throw new Error(`Unsupported selector type: '${selector.type}'`);
  17. }
  18. const { start, end } = parseMediaFragmentIdentifier(selector.value);
  19. return { start, end };
  20. }
  21. export default async function init(playlist) {
  22. const eventEmitter = playlist.getEventEmitter();
  23. async function displayBookmarksInPage() {
  24. const bookmarks = await retrieveBookmarks({ url: document.URL });
  25. const bookmarksWithTime = bookmarks.map(bookmark => {
  26. const fragmentIdentifier = bookmark.url.split('#')[1];
  27. if (fragmentIdentifier === undefined) return null;
  28. const selector = fragmentIdentifierToSelector(fragmentIdentifier);
  29. try {
  30. const { start, end } = selectorToTime(selector);
  31. return { bookmark, start, end };
  32. } catch (err) {
  33. // Likely a fragment identifier we do not understand; skip it.
  34. return null;
  35. }
  36. }).filter(value => value !== null);
  37. bookmarksWithTime.sort(({ start: t1 }, { start: t2 }) => t1 - t2);
  38. const annotations = bookmarksWithTime.map(({ bookmark, start, end }) => ({
  39. start,
  40. end,
  41. id: bookmark.title,
  42. elementType: 'a',
  43. elementAttributes: {
  44. title: bookmark.title,
  45. href: bookmark.url,
  46. onclick: () => { eventEmitter.emit('select', start, end); },
  47. },
  48. }));
  49. playlist.setAnnotations({ annotations, annotationFormat: 'raw', editable: false });
  50. playlist.drawRequest();
  51. }
  52. makeRemotelyCallable({
  53. displayBookmarksInPage,
  54. });
  55. await displayBookmarksInPage();
  56. }