Skip to content
Snippets Groups Projects
browser-preload.browser.js 4.06 KiB
Newer Older
  • Learn to ignore specific revisions
  • James Long's avatar
    James Long committed
    import { initBackend as initSQLBackend } from 'absurd-sql/dist/indexeddb-main-thread';
    
    import * as Platform from 'loot-core/src/client/platform';
    
    
    import packageJson from '../package.json';
    
    
    const backendWorkerUrl = new URL('./browser-server.js', import.meta.url);
    
    James Long's avatar
    James Long committed
    
    // This file installs global variables that the app expects.
    // Normally these are already provided by electron, but in a real
    // browser environment this is where we initialize the backend and
    // everything else.
    
    let IS_DEV = process.env.NODE_ENV === 'development';
    
    let ACTUAL_VERSION = Platform.isPlaywright ? '99.9.9' : packageJson.version;
    
    James Long's avatar
    James Long committed
    
    // *** Start the backend ***
    let worker;
    
    function createBackendWorker() {
    
      worker = new Worker(backendWorkerUrl);
    
    James Long's avatar
    James Long committed
      initSQLBackend(worker);
    
    
      if (window.SharedArrayBuffer) {
        localStorage.removeItem('SharedArrayBufferOverride');
      }
    
    
    James Long's avatar
    James Long committed
      worker.postMessage({
        type: 'init',
        version: ACTUAL_VERSION,
        isDev: IS_DEV,
    
        publicUrl: process.env.PUBLIC_URL,
    
        hash: process.env.REACT_APP_BACKEND_WORKER_HASH,
        isSharedArrayBufferOverrideEnabled: localStorage.getItem(
    
          'SharedArrayBufferOverride',
        ),
    
    James Long's avatar
    James Long committed
      });
    }
    
    createBackendWorker();
    
    global.Actual = {
      IS_DEV,
      ACTUAL_VERSION,
    
      logToTerminal: (...args) => {
        console.log(...args);
      },
    
      relaunch: () => {
        window.location.reload();
      },
    
      openFileDialog: async ({ filters = [], properties }) => {
        return new Promise(resolve => {
    
          let createdElement = false;
          // Attempt to reuse an already-created file input.
          let input = document.body.querySelector(
            'input[id="open-file-dialog-input"]',
          );
          if (!input) {
            createdElement = true;
            input = document.createElement('input');
          }
    
    
    James Long's avatar
    James Long committed
          input.type = 'file';
    
          input.id = 'open-file-dialog-input';
          input.value = null;
    
    James Long's avatar
    James Long committed
    
          let filter = filters.find(filter => filter.extensions);
          if (filter) {
            input.accept = filter.extensions.map(ext => '.' + ext).join(',');
          }
    
          input.style.position = 'absolute';
          input.style.top = '0px';
          input.style.left = '0px';
    
          input.style.display = 'none';
    
    James Long's avatar
    James Long committed
    
    
          input.onchange = e => {
    
    James Long's avatar
    James Long committed
            let file = e.target.files[0];
            let filename = file.name.replace(/.*(\.[^.]*)/, 'file$1');
    
            if (file) {
              var reader = new FileReader();
              reader.readAsArrayBuffer(file);
    
              reader.onload = async function (ev) {
    
    James Long's avatar
    James Long committed
                let filepath = `/uploads/${filename}`;
    
                window.__actionsForMenu
                  .uploadFile(filename, ev.target.result)
                  .then(() => resolve([filepath]));
              };
    
              reader.onerror = function (ev) {
    
    James Long's avatar
    James Long committed
                alert('Error reading file');
              };
            }
    
          };
    
          // In Safari the file input has to be in the DOM for change events to
          // reliably fire.
          if (createdElement) {
            document.body.appendChild(input);
          }
    
          input.click();
    
    James Long's avatar
    James Long committed
        });
      },
    
      saveFile: (contents, defaultFilename, dialogTitle) => {
        const temp = document.createElement('a');
        temp.style = 'display: none';
        temp.download = defaultFilename;
        temp.rel = 'noopener';
    
        const blob = new Blob([contents]);
        temp.href = URL.createObjectURL(blob);
        temp.dispatchEvent(new MouseEvent('click'));
      },
    
      openURLInBrowser: url => {
        window.open(url, '_blank');
      },
      onEventFromMain: (type, handler) => {},
      applyAppUpdate: () => {},
      updateAppMenu: isBudgetOpen => {},
    
      getServerSocket: async () => {
        return worker;
    
    James Long's avatar
    James Long committed
    };
    
    document.addEventListener('keydown', e => {
      if (e.metaKey || e.ctrlKey) {
        // Cmd/Ctrl+o
    
        if (e.key === 'o') {
    
    James Long's avatar
    James Long committed
          e.preventDefault();
          window.__actionsForMenu.closeBudget();
        }
        // Cmd/Ctrl+z
    
        else if (e.key.toLowerCase() === 'z') {
    
          if (
            e.target.tagName === 'INPUT' ||
            e.target.tagName === 'TEXTAREA' ||
            e.target.isContentEditable
          ) {
            return;
          }
          e.preventDefault();
    
    James Long's avatar
    James Long committed
          if (e.shiftKey) {
            // Redo
            window.__actionsForMenu.redo();
          } else {
            // Undo
            window.__actionsForMenu.undo();
          }
        }
      }
    });