完成品
option(alt) + Spaceで表示/非表示が切り替えられます。
ソースコード
はじめに
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
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()
}
})
<!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は以下のように書き換えます。
{
"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が表示されると思います。
どこからでもショートカットでアプリを呼び出せるようにする
このままではwindowの表示/非表示を切り替えられないし、PCの起動時に毎回アプリを立ち上げる必要があります。
Alfredのような挙動を実現するには
1. electronアプリを常駐で起動させておいて、
2. 表示/非表示を切り替えるショートカットを登録する
必要があります。
1. electronアプリを常駐で起動させる
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ではログイン時に起動されるアプリは
ユーザーとグループ > ログイン項目
に追加されます。
2. 表示/非表示を切り替えるショートカットを登録する
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アプリがフォアグラウンドになっている場合にしか反応しません。
#### このように動くと思います!
Tips
Windowをドラッグできるようにする
<body style="-webkit-app-region: drag">
参考: https://www.electronjs.org/docs/api/frameless-window#draggable-region
まとめ
ご覧いただきありがとうございました!
次回はGithub APIからIssueを取得して表示する部分を作成していきます!
Twitterのフォローもお願い致します!
https://twitter.com/1keiuu