diff --git a/.github/workflows/build-app.yml b/.github/workflows/build-app.yml index 043776872..d1ce878e5 100644 --- a/.github/workflows/build-app.yml +++ b/.github/workflows/build-app.yml @@ -37,5 +37,39 @@ jobs: - uses: actions/upload-artifact@v1 with: - name: Gitify-dist + name: Gitify-dist-mac + path: dist + + build-windows: + runs-on: windows-2019 + + steps: + - uses: actions/checkout@v2 + + - name: Get yarn cache + id: yarn-cache + run: echo "::set-output name=dir::$(yarn cache dir)" + + - uses: actions/cache@v1 + with: + path: ${{ steps.yarn-cache.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Install Dependencies + run: yarn install + + - name: Build + run: yarn build + + - name: Make Windows (electron-builder) + run: yarn make:win + + - name: Clean up builds + run: Remove-Item dist/win-unpacked -Recurse + + - uses: actions/upload-artifact@v1 + with: + name: Gitify-dist-win path: dist diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 65392b4b8..b7e3a46c4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,4 +40,35 @@ jobs: CSC_KEY_PASSWORD: ${{ secrets.mac_certs_password }} GH_TOKEN: ${{ secrets.gh_token }} NOTARIZE: true - run: yarn electron-builder --publish onTagOrDraft + run: yarn make:mac --publish onTagOrDraft + + release-windows: + runs-on: windows-2019 + + steps: + - uses: actions/checkout@v2 + + - name: Get yarn cache + id: yarn-cache + run: echo "::set-output name=dir::$(yarn cache dir)" + + - uses: actions/cache@v1 + with: + path: ${{ steps.yarn-cache.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Install Dependencies + run: yarn install + + - name: Build + env: + OAUTH_CLIENT_ID: ${{ secrets.oauth_client_id }} + OAUTH_CLIENT_SECRET: ${{ secrets.oauth_client_secret }} + run: yarn build + + - name: Publish Windows (electron-builder) + env: + GH_TOKEN: ${{ secrets.gh_token }} + run: yarn make:win --publish onTagOrDraft diff --git a/assets/images/app-icon.ico b/assets/images/app-icon.ico new file mode 100644 index 000000000..3791a557c Binary files /dev/null and b/assets/images/app-icon.ico differ diff --git a/main.js b/main.js index 966b86429..feffefa88 100644 --- a/main.js +++ b/main.js @@ -1,17 +1,11 @@ const { ipcMain } = require('electron'); const { menubar } = require('menubar'); -const { autoUpdater } = require("electron-updater") +const { autoUpdater } = require('electron-updater'); const path = require('path'); -const AutoLaunch = require('auto-launch'); const iconIdle = path.join(__dirname, 'assets', 'images', 'tray-idleTemplate.png'); const iconActive = path.join(__dirname, 'assets', 'images', 'tray-active.png'); - -const autoStart = new AutoLaunch({ - name: 'Gitify', - path: process.execPath.match(/.*?\.app/)[0], - isHidden: true, -}); +const isDarwin = process.platform === 'darwin'; const browserWindowOpts = { width: 500, @@ -38,8 +32,6 @@ menubarApp.on('ready', () => { autoUpdater.checkForUpdatesAndNotify(); ipcMain.on('reopen-window', () => menubarApp.showWindow()); - ipcMain.on('startup-enable', () => autoStart.enable()); - ipcMain.on('startup-disable', () => autoStart.disable()); ipcMain.on('app-quit', () => menubarApp.app.quit()); ipcMain.on('update-icon', (_, arg) => { if (!menubarApp.tray.isDestroyed()) { diff --git a/package.json b/package.json index 41991f7a4..c8f1fcf08 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "build": "webpack --config webpack.prod.js", "watch": "webpack --config webpack.common.js --watch", + "make:win": "electron-builder --win", "make:macos": "electron-builder --mac", "prettier-check": "prettier --check 'src/**/*.{js,ts,tsx}'", "prettier": "prettier --single-quote --trailing-comma es5 --write 'src/**/*.{js,ts,tsx}'", @@ -85,11 +86,17 @@ "icon": "assets/images/app-icon.icns", "sign": false }, + "win": { + "target": "nsis", + "icon": "assets/images/app-icon.ico" + }, + "nsis": { + "oneClick": false + }, "afterSign": "scripts/notarize.js" }, "dependencies": { "@primer/octicons-react": "^9.6.0", - "auto-launch": "=5.0.5", "axios": "=0.19.2", "date-fns": "^2.11.1", "electron-updater": "^4.2.5", diff --git a/scripts/notarize.js b/scripts/notarize.js index 4f56fddb9..8532363ea 100644 --- a/scripts/notarize.js +++ b/scripts/notarize.js @@ -10,10 +10,14 @@ const notarizeApp = async (context) => { const shouldNotarize = process.env.NOTARIZE === 'true'; if (!shouldNotarize || !isMacOS) { - console.log('Either should not notarize or not building for macOS.'); + console.log( + ' • notarizing either should not notarize or not building for macOS' + ); return; } + console.log(' • notarizing started'); + return await notarize({ appBundleId, appPath: `${appOutDir}/${appName}.app`, diff --git a/src/js/__mocks__/electron.js b/src/js/__mocks__/electron.js index 1ca3152d5..27c2f3e96 100644 --- a/src/js/__mocks__/electron.js +++ b/src/js/__mocks__/electron.js @@ -51,6 +51,8 @@ module.exports = { dialog: dialog, app: { getVersion: () => '0.0.1', + getLoginItemSettings: jest.fn(), + setLoginItemSettings: () => {}, }, getCurrentWindow: jest.fn(() => browserWindow), }, diff --git a/src/js/middleware/settings.test.ts b/src/js/middleware/settings.test.ts index 2b42036cd..ba9714d2e 100644 --- a/src/js/middleware/settings.test.ts +++ b/src/js/middleware/settings.test.ts @@ -1,4 +1,4 @@ -const { ipcRenderer } = require('electron'); +const { remote } = require('electron'); import * as actions from '../actions'; import settingsMiddleware from './settings'; @@ -13,11 +13,9 @@ const dispatchWithStoreOf = (_, action) => { }; describe('middleware/settings.js', () => { - beforeEach(function () { - spyOn(ipcRenderer, 'send'); - }); - it('should toggle the openAtStartup setting', () => { + spyOn(remote.app, 'setLoginItemSettings'); + const action = { type: actions.UPDATE_SETTING, setting: 'openAtStartup', @@ -26,7 +24,6 @@ describe('middleware/settings.js', () => { expect(dispatchWithStoreOf({}, action)).toEqual(action); - expect(ipcRenderer.send).toHaveBeenCalledTimes(1); - expect(ipcRenderer.send).toHaveBeenCalledWith('startup-enable'); + expect(remote.app.setLoginItemSettings).toHaveBeenCalledTimes(1); }); }); diff --git a/src/js/utils/comms.test.ts b/src/js/utils/comms.test.ts index d42e4e367..d9b787a60 100644 --- a/src/js/utils/comms.test.ts +++ b/src/js/utils/comms.test.ts @@ -5,7 +5,7 @@ import { setAutoLaunch, } from './comms'; -const { ipcRenderer, shell } = require('electron'); +const { ipcRenderer, remote, shell } = require('electron'); describe('utils/comms.ts', () => { beforeEach(function () { @@ -39,14 +39,24 @@ describe('utils/comms.ts', () => { }); it('should setAutoLaunch (true)', () => { + spyOn(remote.app, 'setLoginItemSettings'); + setAutoLaunch(true); - expect(ipcRenderer.send).toHaveBeenCalledTimes(1); - expect(ipcRenderer.send).toHaveBeenCalledWith('startup-enable'); + expect(remote.app.setLoginItemSettings).toHaveBeenCalledTimes(1); + expect(remote.app.setLoginItemSettings).toHaveBeenCalledWith({ + openAtLogin: true, + openAsHidden: true, + }); }); it('should setAutoLaunch (false)', () => { + spyOn(remote.app, 'setLoginItemSettings'); + setAutoLaunch(false); - expect(ipcRenderer.send).toHaveBeenCalledTimes(1); - expect(ipcRenderer.send).toHaveBeenCalledWith('startup-disable'); + expect(remote.app.setLoginItemSettings).toHaveBeenCalledTimes(1); + expect(remote.app.setLoginItemSettings).toHaveBeenCalledWith({ + openAtLogin: false, + openAsHidden: false, + }); }); }); diff --git a/src/js/utils/comms.ts b/src/js/utils/comms.ts index 96a91c9a5..82be8ceea 100644 --- a/src/js/utils/comms.ts +++ b/src/js/utils/comms.ts @@ -1,17 +1,16 @@ -import { SettingsState } from '../../types/reducers'; +const { ipcRenderer, remote, shell } = require('electron'); -const { ipcRenderer, shell } = require('electron'); +import { SettingsState } from '../../types/reducers'; export function openExternalLink(url) { shell.openExternal(url); } export function setAutoLaunch(value) { - if (value) { - ipcRenderer.send('startup-enable'); - } else { - ipcRenderer.send('startup-disable'); - } + remote.app.setLoginItemSettings({ + openAtLogin: value, + openAsHidden: value, + }); } export function updateTrayIcon(notificationsLength = 0) { diff --git a/yarn.lock b/yarn.lock index 7535ff1a2..94b2e9df1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1155,10 +1155,6 @@ app-builder-lib@22.4.1, app-builder-lib@~22.4.1: semver "^7.1.3" temp-file "^3.3.7" -applescript@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/applescript/-/applescript-1.0.0.tgz#bb87af568cad034a4e48c4bdaf6067a3a2701317" - aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -1269,17 +1265,6 @@ atob@^2.1.1: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -auto-launch@=5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/auto-launch/-/auto-launch-5.0.5.tgz#d14bd002b1ef642f85e991a6195ff5300c8ad3c0" - integrity sha512-ppdF4mihhYzMYLuCcx9H/c5TUOCev8uM7en53zWVQhyYAJrurd2bFZx3qQVeJKF2jrc7rsPRNN5cD+i23l6PdA== - dependencies: - applescript "^1.0.0" - mkdirp "^0.5.1" - path-is-absolute "^1.0.0" - untildify "^3.0.2" - winreg "1.2.4" - aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -6760,10 +6745,6 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -untildify@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/untildify/-/untildify-3.0.2.tgz#7f1f302055b3fea0f3e81dc78eb36766cb65e3f1" - upath@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" @@ -7045,11 +7026,6 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" -winreg@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.4.tgz#ba065629b7a925130e15779108cf540990e98d1b" - integrity sha1-ugZWKbepJRMOFXeRCM9UCZDpjRs= - wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"