Skip to content
Snippets Groups Projects
global-events.js 4.55 KiB
Newer Older
  • Learn to ignore specific revisions
  • import * as sharedListeners from 'loot-core/src/client/shared-listeners';
    
    import { listen } from 'loot-core/src/platform/client/fetch';
    
    James Long's avatar
    James Long committed
    import * as undo from 'loot-core/src/platform/client/undo';
    
    export function handleGlobalEvents(actions, store) {
      global.Actual.onEventFromMain('update-downloaded', (event, info) => {
        actions.setAppState({ updateInfo: info });
      });
    
      global.Actual.onEventFromMain('update-error', msg => {
        // Ignore errors. We don't want to constantly bug the user if they
        // always have a flaky connection or have intentionally disabled
        // updates. They will see the error in the about page if they try
        // to update.
      });
    
      listen('server-error', info => {
        actions.addGenericErrorNotification();
      });
    
      listen('update-loading-status', status => {
        switch (status) {
          case 'updating':
            actions.updateStatusText('Updating...');
            break;
          default:
        }
      });
    
      listen('orphaned-payees', ({ orphanedIds, updatedPayeeIds }) => {
        // Right now, it prompts to merge into the first payee
        actions.pushModal('merge-unused-payees', {
          payeeIds: orphanedIds,
    
          targetPayeeId: updatedPayeeIds[0],
    
    James Long's avatar
    James Long committed
        });
      });
    
      listen('schedules-offline', ({ payees }) => {
    
        actions.pushModal(`schedule-posts-offline-notification`, { payees });
    
    James Long's avatar
    James Long committed
      });
    
      // This is experimental: we sync data locally automatically when
      // data changes from the backend
      listen('sync-event', async ({ type, tables }) => {
        // We don't need to query anything until the file is loaded, and
        // sync events might come in if the file is being synced before
        // being loaded (happens when downloading)
        let prefs = store.getState().prefs.local;
        if (prefs && prefs.id) {
          if (type === 'applied') {
            if (tables.includes('payees') || tables.includes('payee_mapping')) {
              actions.getPayees();
            }
          }
        }
      });
    
      // TODO: Should this run on mobile too?
      listen('sync-event', async ({ type }) => {
        if (type === 'unauthorized') {
          actions.addNotification({
            type: 'warning',
            message: 'Unable to authenticate with server',
            sticky: true,
    
    James Long's avatar
    James Long committed
          });
        }
      });
    
      sharedListeners.listenForSyncEvent(actions, store);
    
      listen('undo-event', undoState => {
    
        let { tables, undoTag } = undoState;
    
    James Long's avatar
    James Long committed
        let promises = [];
    
        if (
          tables.includes('categories') ||
          tables.includes('category_groups') ||
          tables.includes('category_mapping')
        ) {
          promises.push(actions.getCategories());
        }
    
        if (tables.includes('accounts')) {
          promises.push(actions.getAccounts());
        }
    
        let tagged = undo.getTaggedState(undoTag);
    
        if (tagged) {
          Promise.all(promises).then(() => {
            actions.setLastUndoState(undoState);
    
            // If a modal has been tagged, open it instead of navigating
            if (tagged.openModal) {
              let { modalStack } = store.getState().modals;
    
              if (
                modalStack.length === 0 ||
                modalStack[modalStack.length - 1].name !== tagged.openModal
              ) {
                actions.replaceModal(tagged.openModal);
              }
            } else {
              actions.closeModal();
    
    
              if (
                window.location.href.replace(window.location.origin, '') !==
                tagged.url
              ) {
                window.__navigate(tagged.url);
    
    James Long's avatar
    James Long committed
                // This stops propagation of the undo event, which is
                // important because if we are changing URLs any existing
                // undo listeners on the current page don't need to be run
                return true;
              }
            }
          });
        }
      });
    
      listen('fallback-write-error', () => {
        actions.addNotification({
          type: 'error',
          title: 'Unable to save changes',
          sticky: true,
          message:
            'This browser only supports using the app in one tab at a time, ' +
            'and another tab has opened the app. No changes will be saved ' +
    
            'from this tab; please close it and continue working in the other one.',
    
    James Long's avatar
    James Long committed
        });
      });
    
      listen('start-load', () => {
        actions.closeBudgetUI();
        actions.setAppState({ loadingText: '' });
      });
    
      listen('finish-load', () => {
        actions.closeModal();
        actions.setAppState({ loadingText: null });
        actions.loadPrefs();
      });
    
      listen('start-import', () => {
        actions.closeBudgetUI();
      });
    
      listen('finish-import', () => {
        actions.closeModal();
        actions.setAppState({ loadingText: null });
        actions.loadPrefs();
      });
    
      listen('show-budgets', () => {
        actions.closeBudgetUI();
        actions.setAppState({ loadingText: null });
      });
    }