• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gitify-app / gitify / 13031932468

29 Jan 2025 01:03PM UTC coverage: 87.981% (+0.09%) from 87.888%
13031932468

Pull #1781

github

web-flow
Merge 2d8847eff into 73b203001
Pull Request #1781: feat(auth): use system browser for GitHub SSO / OAuth authentication

651 of 725 branches covered (89.79%)

Branch coverage included in aggregate %.

32 of 39 new or added lines in 4 files covered. (82.05%)

26 existing lines in 1 file now uncovered.

1728 of 1979 relevant lines covered (87.32%)

23.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/main.ts
1
import { app, globalShortcut, ipcMain as ipc } from 'electron';
×
2
import log from 'electron-log';
×
3
import { menubar } from 'menubar';
×
4

5
import { APPLICATION } from '../shared/constants';
×
6
import { namespacedEvent } from '../shared/events';
×
7
import { isMacOS, isWindows } from '../shared/platform';
×
8
import { onFirstRunMaybe } from './first-run';
×
9
import { TrayIcons } from './icons';
×
10
import MenuBuilder from './menu';
×
11
import Updater from './updater';
×
12

13
log.initialize();
×
14

15
const browserWindowOpts = {
×
16
  width: 500,
17
  height: 400,
18
  minWidth: 500,
19
  minHeight: 400,
20
  resizable: false,
21
  skipTaskbar: true, // Hide the app from the Windows taskbar
22
  // TODO ideally we would disable this as use a preload script with a context bridge
23
  webPreferences: {
24
    nodeIntegration: true,
25
    contextIsolation: false,
26
  },
27
};
28

UNCOV
29
const mb = menubar({
×
30
  icon: TrayIcons.idle,
31
  index: `file://${__dirname}/index.html`,
32
  browserWindow: browserWindowOpts,
33
  preloadWindow: true,
34
  showDockIcon: false, // Hide the app from the macOS dock
35
});
36

37
const menuBuilder = new MenuBuilder(mb);
×
UNCOV
38
const contextMenu = menuBuilder.buildMenu();
×
39

40
// Register your app as the handler for a custom protocol
NEW
41
app.setAsDefaultProtocolClient('gitify');
×
42

NEW
43
if (isMacOS() || isWindows()) {
×
44
  /**
45
   * Electron Auto Updater only supports macOS and Windows
46
   * https://github.com/electron/update-electron-app
47
   */
48
  const updater = new Updater(mb, menuBuilder);
×
UNCOV
49
  updater.initialize();
×
50
}
51

UNCOV
52
let shouldUseAlternateIdleIcon = false;
×
53

54
app.whenReady().then(async () => {
×
UNCOV
55
  await onFirstRunMaybe();
×
56

57
  mb.on('ready', () => {
×
UNCOV
58
    mb.app.setAppUserModelId(APPLICATION.ID);
×
59

60
    // Tray configuration
61
    mb.tray.setToolTip(APPLICATION.NAME);
×
62
    mb.tray.setIgnoreDoubleClickEvents(true);
×
63
    mb.tray.on('right-click', (_event, bounds) => {
×
UNCOV
64
      mb.tray.popUpContextMenu(contextMenu, { x: bounds.x, y: bounds.y });
×
65
    });
66

67
    // Custom key events
68
    mb.window.webContents.on('before-input-event', (event, input) => {
×
69
      if (input.key === 'Escape') {
×
70
        mb.window.hide();
×
UNCOV
71
        event.preventDefault();
×
72
      }
73
    });
74

75
    // DevTools configuration
76
    mb.window.webContents.on('devtools-opened', () => {
×
77
      mb.window.setSize(800, 600);
×
78
      mb.window.center();
×
79
      mb.window.resizable = true;
×
UNCOV
80
      mb.window.setAlwaysOnTop(true);
×
81
    });
82

83
    mb.window.webContents.on('devtools-closed', () => {
×
84
      const trayBounds = mb.tray.getBounds();
×
85
      mb.window.setSize(browserWindowOpts.width, browserWindowOpts.height);
×
86
      mb.positioner.move('trayCenter', trayBounds);
×
UNCOV
87
      mb.window.resizable = false;
×
88
    });
89
  });
90

91
  /**
92
   * Gitify custom IPC events
93
   */
UNCOV
94
  ipc.handle(namespacedEvent('version'), () => app.getVersion());
×
95

UNCOV
96
  ipc.on(namespacedEvent('window-show'), () => mb.showWindow());
×
97

UNCOV
98
  ipc.on(namespacedEvent('window-hide'), () => mb.hideWindow());
×
99

UNCOV
100
  ipc.on(namespacedEvent('quit'), () => mb.app.quit());
×
101

UNCOV
102
  ipc.on(
×
103
    namespacedEvent('use-alternate-idle-icon'),
104
    (_, useAlternateIdleIcon) => {
UNCOV
105
      shouldUseAlternateIdleIcon = useAlternateIdleIcon;
×
106
    },
107
  );
108

109
  ipc.on(namespacedEvent('icon-error'), () => {
×
110
    if (!mb.tray.isDestroyed()) {
×
UNCOV
111
      mb.tray.setImage(TrayIcons.error);
×
112
    }
113
  });
114

115
  ipc.on(namespacedEvent('icon-active'), () => {
×
116
    if (!mb.tray.isDestroyed()) {
×
UNCOV
117
      mb.tray.setImage(
×
118
        menuBuilder.isUpdateAvailable()
×
119
          ? TrayIcons.activeWithUpdate
120
          : TrayIcons.active,
121
      );
122
    }
123
  });
124

125
  ipc.on(namespacedEvent('icon-idle'), () => {
×
126
    if (!mb.tray.isDestroyed()) {
×
127
      if (shouldUseAlternateIdleIcon) {
×
UNCOV
128
        mb.tray.setImage(
×
129
          menuBuilder.isUpdateAvailable()
×
130
            ? TrayIcons.idleAlternateWithUpdate
131
            : TrayIcons.idleAlternate,
132
        );
133
      } else {
UNCOV
134
        mb.tray.setImage(
×
135
          menuBuilder.isUpdateAvailable()
×
136
            ? TrayIcons.idleWithUpdate
137
            : TrayIcons.idle,
138
        );
139
      }
140
    }
141
  });
142

143
  ipc.on(namespacedEvent('update-title'), (_, title) => {
×
144
    if (!mb.tray.isDestroyed()) {
×
UNCOV
145
      mb.tray.setTitle(title);
×
146
    }
147
  });
148

UNCOV
149
  ipc.on(
×
150
    namespacedEvent('update-keyboard-shortcut'),
151
    (_, { enabled, keyboardShortcut }) => {
152
      if (!enabled) {
×
153
        globalShortcut.unregister(keyboardShortcut);
×
UNCOV
154
        return;
×
155
      }
156

157
      globalShortcut.register(keyboardShortcut, () => {
×
158
        if (mb.window.isVisible()) {
×
UNCOV
159
          mb.hideWindow();
×
160
        } else {
UNCOV
161
          mb.showWindow();
×
162
        }
163
      });
164
    },
165
  );
166

167
  ipc.on(namespacedEvent('update-auto-launch'), (_, settings) => {
×
UNCOV
168
    app.setLoginItemSettings(settings);
×
169
  });
170
});
171

172
// Handle gitify:// custom protocol URL events for OAuth 2.0 callback
NEW
173
app.on('open-url', (event, url) => {
×
NEW
174
  event.preventDefault();
×
NEW
175
  mb.window.webContents.send(namespacedEvent('auth-callback'), url);
×
176
});
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc