「Electronではじめるアプリ開発」を写経してみた ④
G.W.は、何もしないで終わってしまったので、また写経を再開しました。チャットアプリ の続きをやります。
目次:
npmスクリプトの登録
package.jsonにnpmスクリプト(scripts)を記述すると コマンドのエイリアス登録をできます。
"scripts": { "watch": "babel --out-dir .tmp src --watch", "start": "electron .", },
$ npm start で electron . と同様となります。
ルーティングの実装
react と react-router で各画面とルーティングを実装していきます。
src/main/Login.jsx(ログイン画面)
import React from "react"; import { Link } from "react-router"; export default class Login extends React.Component { render() { return ( <div> <h2>Login</h2> <Link to="/rooms">Login</Link> <br /> <Link to="/signup">Create new account</Link> </div> ); } }
src/main/SignUp.jsx(サインアップ画面)
import React from "react"; import { Link } from "react-router"; export default class Login extends React.Component { render() { return ( <div> <h2>Signup</h2> <Link to="/rooms">Login</Link> <br /> <Link to="/login">cancel</Link> </div> ); } }
src/main/Rooms.jsx(チャットルーム一覧画面)
import React from "react"; import { Link } from "react-router"; export default class Login extends React.Component { render() { return ( <div> <h2>Rooms</h2> <ul> <li><Link to="/rooms/1">Room 1</Link></li> <li><Link to="/rooms/2">Room 2</Link></li> </ul> <div>{this.props.children}</div> </div> ); } }
src/main/Room.jsx(チャットルーム詳細画面)
import React from "react"; export default class Login extends React.Component { render() { return ( <div> <h3>Room</h3> </div> ); } }
src/renderer/app.jsx(ルーティングの実装)
import React from "react"; import { render } from "react-dom"; import { Router, Route, hashHistory } from "react-router"; import Login from "./Login"; import Signup from "./Signup"; import Rooms from "./Rooms"; import Room from "./Room"; const appRouting = ( <Router history={hashHistory}> <Route path="/"> <Route path="login" component={Login} /> <Route path="signup" component={Signup} /> <Route path="rooms" component={Rooms}> <Route path=":roomId" component={Room} /> </Route> </Route> </Router> ); if (!location.hash.length) { location.hash = "#/login"; } render(appRouting, document.getElementById("app"));
メニューの作成
もろもろメニュー項目を追加します。 単純作業で地味にツラったです・・
src/main/setAppMenu.jsx(ルーティングの実装)
import { app, Menu } from "electron"; import createWindow from "./createWindow"; function setAppMenu() { const template = [ { label: "File", submenu: [ { label: "New Window", accelerator: "CmdOrCtrl+N", click: createWindow }, { type: "separator" }, { label: "Close", accelerator: "CmdOrCtrl+W", role: "close" }, ], }, { label: "Edit", submenu: [ { label: "Copy", accelerator: "CmdOrCtrl+C", role: "copy" }, { label: "Paste", accelerator: "CmdOrCtrl+V", role: "paste" }, { label: "Cut", accelerator: "CmdOrCtrl+X", role: "cut" }, { label: "Select All", accelerator: "CmdOrCtrl+A", role: "selectall" } ], }, { label: "View", submenu: [ { label: "Reload", accelerator: "CmdOrCtrl+R", click: (item, focusedWindow) => focusedWindow && focusedWindow.reload() }, ], }, { label: "Toggle DevTools", submenu: [ { label: "Reload", accelerator: process.platform === "darwin" ? "Alt+Command+I" : "Ctrl+Shift+I", click: (item, focusedWindow) => focusedWindow && focusedWindow.toggleDevTools() }, ], }, ]; if (process.platform === "darwin") { template.unshift({ label: app.getName(), submenu: [ { role: "about" }, { type: "separator" }, { role: "services", submenu:[] }, { type: "separator" }, { role: "hide" }, { role: "hideothers" }, { role: "unhide" }, { type: "separator" }, { role: "quit" } ], }); } template.push({ role: "window", submenu: [ { role: "minimize" }, { role: "zoom" }, ] }); const appMenu = Menu.buildFromTemplate(template); Menu.setApplicationMenu(appMenu); } export default setAppMenu;
src/main/index.js(アプリケーションメニューを追加)
import { app } from "electron"; import createWindow from "./createWindow"; import setAppMenu from "./setAppMenu"; app.on("ready", () => { setAppMenu(); createWindow(); }); app.on("window-all-closed", () => { if(process.platform !== "darwin") { app.quit(); } }); app.on("activate", (_e, hasVisibleWindows) => { if(!hasVisibleWindows) { createWindow(); } });
こんな感じになりました。
今回は、メニュー作成するのが少々単純作業で辛かったです・・。 次回は、Firebaseを使用するので、テクニカルな面白味はありそうです。