🐈

【Electron入門】GithubのIssueを一瞬で確認できるアプリを作って業務効率化してみた #1

2020/11/21に公開

完成品

option(alt) + Spaceで表示/非表示が切り替えられます。
※#1ではwindowを作る所までです。#2でGithubAPIを導入していきます。

ソースコード

https://github.com/ikkei12/git-app.pub

はじめに

image.png

Alfred最高ですよね。
彼のおかげでマウスを使う頻度が激減して助かっています。

Alfredと同じ手軽さで、自分がアサインされているissueを確認できるデスクトップアプリが作りたいなと思ったので、Electronで作ってみようと思いました。

Electronには

  • JavaScriptで作れる
  • Chromiumベースなのでwebエンジニアにも優しい

といった利点があり、HTML/CSS/JavaScriptを学んだ初心者の方でも扱いやすいかと思います!

Electronのはじめかた

基本的に公式ドキュメントを参考にElectronのセットアップをするだけですが、一部変更を加えています。

1. 以下のコマンドを実行

mkdir git-app && cd git-app
npm init -y
npm i --save-dev electron
npm i --save-dev electron-builder

2. html/jsファイルを作成

標準的なNode.jsアプリと同様に以下のような構成で始めます。

git-app/
├── package.json
├── main.js
└── index.html
main.js
const { app, BrowserWindow } = require('electron')

function createWindow () {
  const win = new BrowserWindow({
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
    },
    frame: false,
    alwaysOnTop: true,
    useContentSize: true,
    transparent: true,
  })

  win.loadFile('index.html')

  win.on("blur", (e) => {
    // window外をクリックしたタイミング(blur)で閉じる
    app.hide();
  });
}

app.whenReady().then(createWindow)

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})
index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World!</title>
    <meta
      http-equiv="Content-Security-Policy"
      content="script-src 'self' 'unsafe-inline';"
    />
  </head>
  <body style="-webkit-app-region: drag">
    <div style="background: #fff; height: 300px">
      <h1>Hello World!</h1>
    </div>
  </body>
</html>

3. package.jsonを修正

package.jsonは以下のように書き換えます。

package.json
{
  "name": "git-app",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "NODE_ENV=development electron .",
    "build": "NODE_ENV=production electron-builder"
  },
  "build": {
    "appId": "git-app",
    "mac": {
      "category": "git-app"
    }
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "electron": "^10.1.5"
  }
}

4. 起動

npm start
でこのようなwindowが表示されると思います。

image.png

どこからでもショートカットでアプリを呼び出せるようにする

このままではwindowの表示/非表示を切り替えられないし、PCの起動時に毎回アプリを立ち上げる必要があります。

Alfredのような挙動を実現するには
 1. electronアプリを常駐で起動させておいて、
 2. 表示/非表示を切り替えるショートカットを登録する
必要があります。

1. electronアプリを常駐で起動させる

main.js
app.dock.hide();

if (process.env.NODE_ENV !== "development") {
  app.setLoginItemSettings({
    openAtLogin: true,
    path: app.getPath("exe"),
  });
}

解説

app.dock.hide()
常駐のアプリをDockに表示したくないので、Dockから非表示にします。

app.setLoginItemSettings()
でログイン時に自動で起動してくれるようになります。
ローカルでは起動したくないので、NODE_ENVで判定しています。

・macではログイン時に起動されるアプリは
ユーザーとグループ > ログイン項目に追加されます。
image.png

2. 表示/非表示を切り替えるショートカットを登録する

main.js
app.on("ready", function () {
  globalShortcut.register("alt+space", function () {
    // 現在focusしているwindowを取得
    const window = BrowserWindow.getFocusedWindow();
    // windowが存在すればhide、なければshow
    window ? hideWindow(window) : showWindow();
  });
});

app.on("will-quit", function () {
  // 終了するタイミングで全てのglobalShortcutを解除
  globalShortcut.unregisterAll();
});

function showWindow() {
  // focusさせる事でBrowserWindowのblurイベントを検知させる
  app.focus({ steal: true });
  app.show();
}

function hideWindow(window) {
  // center()する事でshowする時に中央で表示される
  window.center();
  app.hide();
}

解説

・アプリがready状態になった段階で、ショートカットキーを登録しています。自分はalt+spaceで起動したいのでregisterの第一引数に渡しています。

・第二引数ではショートカットキーが押されたタイミングで実行する関数を登録しています。現在focusされているwindowを取得し、存在する場合はhideメソッド、しなければshowメソッドを実行する事で表示を切り替えています。

globalShortcutと言うのがポイントで、普通のショートカット(localShortcut)ではElectronアプリがフォアグラウンドになっている場合にしか反応しません。

このように動くと思います!

test.gif

Tips

Windowをドラッグできるようにする

<body style="-webkit-app-region: drag">

参考: https://www.electronjs.org/docs/api/frameless-window#draggable-region

まとめ

ご覧いただきありがとうございました!
次回はGithub APIからIssueを取得して表示する部分を作成していきます!

#2 GithubAPI編

Twitterのフォローもお願い致します!
https://twitter.com/1keiuu

Discussion