kumabook/stickynotes

View on GitHub
src/content_script.js

Summary

Maintainability
B
6 hrs
Test Coverage
import browser from 'webextension-polyfill';
import logger from 'kiroku';
import StickyView from './content_scripts/StickyView';

if (process.env.NODE_ENV === 'production') {
  logger.setLevel('INFO');
}

const portName = `content-script-${window.location.href}`;
let port;
const mounsePosition = {
  x: 0,
  y: 0,
};

/* eslint-disable no-underscore-dangle */
window.__stickynotes_state = {};

function watchClickPosition(event) {
  try {
    mounsePosition.x = event.clientX + window.top.pageXOffset;
    mounsePosition.y = event.clientY + window.top.pageYOffset;
  } catch (e) {
    logger.log(e);
  }
}
function onHashChange(e) {
  logger.info(`hashchange: ${e.newURL}`);
  port.postMessage({
    portName,
    type: 'reload-stickies',
    url:  e.newURL,
  });
}

function onPopState(e) {
  logger.info(`popstate: ${e.state} , ${document.location.href}`);
  port.postMessage({
    portName,
    type: 'reload-stickies',
    url:  document.location.href,
  });
}

document.addEventListener('mousedown', watchClickPosition, true);
window.addEventListener('hashchange', onHashChange);
window.addEventListener('popstate', onPopState);

function isChildWindow() {
  return window !== window.parent;
}

function saveSticky(sticky) {
  port.postMessage({
    type: 'save-sticky',
    portName,
    sticky,
  });
}

function setTags(sticky, tagNames) {
  /* eslint-disable  no-param-reassign */
  sticky.tagNames = tagNames;
  saveSticky(sticky);
}

function deleteSticky(sticky) {
  if (isChildWindow()) {
    return;
  }
  port.postMessage({
    type: 'delete-sticky',
    portName,
    sticky,
  });
}

function getParentNode() {
  if (document.body.nodeName === 'FRAMESET') {
    return document.body.parentNode;
  }
  return document.body;
}

function addStickyView(sticky) {
  const stickyView = new StickyView({
    sticky,
    onClickDeleteButton:   () => setTimeout(() => deleteSticky(sticky), 0),
    onClickMinimizeButton: () => stickyView.minimize(),
    onClickEditTagButton:  () => stickyView.toggleTagDialog(),
    onClickMenuButton:     () => stickyView.toggleMenuDialog(),
    onTextareaChange:      () => {
      stickyView.sticky.content = stickyView.textarea.value;
      saveSticky(stickyView.sticky);
    },
    onColorChange: (colorItem) => {
      stickyView.sticky.color = colorItem.id;
      saveSticky(stickyView.sticky, { color: colorItem.id });
    },
    onTagsChange: tags => setTags(stickyView.sticky, tags),
    onMoveEnd:    () => {
      stickyView.sticky.left = parseInt(stickyView.dom.style.left, 10);
      stickyView.sticky.top  = parseInt(stickyView.dom.style.top, 10);
      setTimeout(() => saveSticky(stickyView.sticky), 0);
      // Wait for minized button handler
    },
    onResizeEnd: () => {
      if (!stickyView.isMinimized()) {
        stickyView.sticky.width  = parseInt(stickyView.dom.style.width, 10);
        stickyView.sticky.height = parseInt(stickyView.dom.style.height, 10) + 7;
        saveSticky(stickyView.sticky);
      }
    },
  });
  if (!document.getElementById(stickyView.dom.id)) {
    getParentNode().appendChild(stickyView.dom);
  }
  return stickyView;
}

function loadStickies(stickies, url) {
  if ((window.location && url !== window.location.href) || isChildWindow()) {
    return;
  }
  StickyView.deleteAll();
  stickies.forEach(addStickyView);
}

function createSticky() {
  if (isChildWindow()) {
    return;
  }
  port.postMessage({
    portName,
    type:   'create-sticky',
    sticky: {
      left:     mounsePosition.x,
      top:      mounsePosition.y,
      width:    150,
      height:   100,
      url:      window.location.href,
      title:    window.document.title,
      content:  '',
      color:    'yellow',
      tags:     [],
      tagNames: [],
      state:    StickyView.State.Normal,
    },
  });
  mounsePosition.x += 10;
  mounsePosition.y += 10;
}

function deleteStickyView(sticky) {
  StickyView.deleteDom(sticky);
}

function load(stickies) {
  stickies.forEach((s) => {
    if (s.state !== StickyView.State.Deleted) {
      addStickyView(s);
    }
  });
}

function importedStickies(createdStickies, updatedStickies) {
  load(createdStickies);
  updatedStickies.forEach((sticky) => {
    if (sticky.state === StickyView.State.Deleted) {
      StickyView.deleteDom(sticky);
    } else {
      StickyView.updateDom(sticky);
    }
  });
}

function messageListener(msg) {
  const { type } = msg;
  switch (type) {
    case 'load-stickies':
      loadStickies(msg.stickies, msg.targetUrl);
      break;
    case 'create-sticky':
      if (msg.targetUrl !== window.location.href) {
        return;
      }
      createSticky();
      break;
    case 'created-sticky':
      addStickyView(msg.payload).focus();
      break;
    case 'saved-sticky': {
      const sticky = msg.payload;
      if (sticky.state === StickyView.State.Deleted) {
        StickyView.deleteDom(sticky);
      } else {
        StickyView.updateDom(sticky, { force: true });
      }
      break;
    }
    case 'delete-sticky':
      deleteSticky(msg.payload);
      break;
    case 'deleted-sticky':
      deleteStickyView(msg.payload);
      break;
    case 'cleared-stickies':
      StickyView.deleteAll();
      break;
    case 'imported-stickies': {
      const { createdStickies, updatedStickies } = msg.payload;
      importedStickies(createdStickies, updatedStickies);
      break;
    }
    case 'toggle-visibility':
      if (msg.targetUrl !== window.location.href) {
        return;
      }
      StickyView.toggleVisibilityAllStickies();
      break;
    case 'jump-sticky':
      break;
    case 'focus-sticky': {
      if (msg.targetUrl !== window.location.href) {
        return;
      }
      const sticky = msg.payload;
      const id = `sticky_id_${sticky.id}`;
      const e = document.getElementById(id);
      if (e) {
        e.scrollIntoView();
        e.focus();
      }
      break;
    }
    case 'import':
      break;
    case 'reload':
      break;
    case 'load-options':
      window.__stickynotes_state = msg.payload;
      break;
    case 'history-state-updated':
      if (msg.targetUrl !== window.location.href) {
        return;
      }
      port.postMessage({
        portName,
        type: 'reload-stickies',
        url:  window.location.href,
      });
      break;
    default:
      break;
  }
}

setTimeout(() => {
  port = browser.runtime.connect({ name: portName });
  port.onMessage.addListener(messageListener);
  port.postMessage({
    portName,
    type: 'load-options',
  });
  port.postMessage({
    portName,
    type: 'load-stickies',
    url:  window.location.href,
  });
}, 500);