app.js 6.5 KB
Newer Older
aaronchen2k2k's avatar
aaronchen2k2k 已提交
1
import {app, BrowserWindow, Menu, shell} from 'electron';
2

aaronchen2k2k's avatar
aaronchen2k2k 已提交
3
import {IS_MAC_OSX} from './utils/env';
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
4 5
import Lang, {initLang} from './core/lang';

aaronchen2k2k's avatar
aaronchen2k2k 已提交
6
import {logInfo, logErr} from './utils/log';
aaronchen2k2k's avatar
aaronchen2k2k 已提交
7 8
import {startUIService} from "./core/ui";
import {startZtfServer, killZtfServer} from "./core/ztf";
aaronchen2k2k's avatar
aaronchen2k2k 已提交
9
import main from "@electron/remote/main";
10 11

export default class ZtfApp {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
12
    constructor() {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
13
        this.startZtfServer()
14

aaronchen2k2k's avatar
aaronchen2k2k 已提交
15
        this._windows = new Map();
16
        this.bindElectronEvents();
aaronchen2k2k's avatar
aaronchen2k2k 已提交
17
        logInfo(`>> ztf app created`);
18 19
    }

aaronchen2k2k's avatar
aaronchen2k2k 已提交
20 21 22
    async startZtfServer() {
        try {
            const ztfServerUrl = await startZtfServer();
aaronchen2k2k's avatar
aaronchen2k2k 已提交
23
            logInfo(`>> ztf server started successfully: ${ztfServerUrl}`);
aaronchen2k2k's avatar
aaronchen2k2k 已提交
24
        } catch (error) {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
25
            logErr('>> ztf server started failed: ' + error);
aaronchen2k2k's avatar
aaronchen2k2k 已提交
26
            process.exit(1);
aaronchen2k2k's avatar
aaronchen2k2k 已提交
27
            return;
28 29 30 31
        }
    }

    showAndFocus() {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
32
        logInfo(`>> ztf app: AppWindow[${this.name}]: show and focus`);
33 34 35 36 37 38 39 40 41 42 43

        const {browserWindow} = this;
        if (browserWindow.isMinimized()) {
            browserWindow.restore();
        } else {
            browserWindow.setOpacity(1);
            browserWindow.show();
        }
        browserWindow.focus();
    }

aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
44
    async createWindow() {
45 46
        process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';

aaronchen2k2k's avatar
aaronchen2k2k 已提交
47 48
        const remote = require('@electron/remote/main')
        remote.initialize()
49

aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
50
        const mainWin = new BrowserWindow({
51 52 53
            show: false,
            webPreferences: {nodeIntegration: true, contextIsolation: false}
        })
aaronchen2k2k's avatar
aaronchen2k2k 已提交
54
        remote.enable(mainWin.webContents)
55

aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
56 57
        mainWin.maximize()
        mainWin.show()
58

aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
59
        this._windows.set('main', mainWin.l);
aaronchen2k2k's avatar
aaronchen2k2k 已提交
60

aaronchen2k2k's avatar
aaronchen2k2k 已提交
61
        const url = await startUIService()
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
62 63
        await mainWin.loadURL(url);
        mainWin.webContents.openDevTools({mode: 'bottom'});
64 65
    };

aaronchen2k2k's avatar
aaronchen2k2k 已提交
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
    openOrCreateWindow() {
        const mainWin = this._windows.get('main');
        if (mainWin) {
            this.showAndFocus(mainWin)
        } else {
            this.createWindow();
        }
    }

    showAndFocus(mainWin) {
        if (mainWin.isMinimized()) {
            mainWin.restore();
        } else {
            mainWin.setOpacity(1);
            mainWin.show();
        }
        mainWin.focus();
    }

aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
85
    async ready() {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
86
        logInfo('>> ztf app ready.');
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
87 88

        initLang()
aaronchen2k2k's avatar
aaronchen2k2k 已提交
89 90 91 92 93 94 95 96
        this.openOrCreateWindow();
        this.buildAppMenu();
    }

    quit() {
        killZtfServer();
    }

97 98
    bindElectronEvents() {
        app.on('window-all-closed', () => {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
99
            logInfo(`>> event: window-all-closed`)
100 101 102 103
            app.quit();
        });

        app.on('quit', () => {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
104
            logInfo(`>> event: quit`)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
105
            this.quit();
106 107 108
        });

        app.on('activate', () => {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
109
            logInfo('>> event: activate');
110 111 112

            // 在 OS X 系统上,可能存在所有应用窗口关闭了,但是程序还没关闭,此时如果收到激活应用请求需要
            // 重新打开应用窗口并创建应用菜单
aaronchen2k2k's avatar
aaronchen2k2k 已提交
113 114
            this.openOrCreateWindow();
            this.buildAppMenu();
115 116 117
        });
    }

aaronchen2k2k's avatar
aaronchen2k2k 已提交
118 119 120 121 122
    get windows() {
        return this._windows;
    }

    buildAppMenu() {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
123
        logInfo('>> ztf app: build application menu.');
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
124

aaronchen2k2k's avatar
aaronchen2k2k 已提交
125 126 127 128 129 130 131 132 133
        if (!IS_MAC_OSX) {
            return;
        }

        const template = [
            {
                label: 'ZTF',
                submenu: [
                    {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
134
                        label: Lang.string('app.about'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
135 136
                        selector: 'orderFrontStandardAboutPanel:'
                    }, {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
137
                        label: Lang.string('app.exit'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
138 139
                        accelerator: 'Command+Q',
                        click: () => {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
140
                            app.quit();
aaronchen2k2k's avatar
aaronchen2k2k 已提交
141 142 143 144 145
                        }
                    }
                ]
            },
            {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
146
                label: Lang.string('app.edit'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
147
                submenu: [{
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
148
                    label: Lang.string('app.undo'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
149 150 151
                    accelerator: 'Command+Z',
                    selector: 'undo:'
                }, {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
152
                    label: Lang.string('app.redo'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
153 154 155 156 157
                    accelerator: 'Shift+Command+Z',
                    selector: 'redo:'
                }, {
                    type: 'separator'
                }, {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
158
                    label: Lang.string('app.cut'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
159 160 161
                    accelerator: 'Command+X',
                    selector: 'cut:'
                }, {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
162
                    label: Lang.string('app.copy'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
163 164 165
                    accelerator: 'Command+C',
                    selector: 'copy:'
                }, {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
166
                    label: Lang.string('app.paste'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
167 168 169
                    accelerator: 'Command+V',
                    selector: 'paste:'
                }, {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
170
                    label: Lang.string('app.select_all'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
171 172 173 174 175
                    accelerator: 'Command+A',
                    selector: 'selectAll:'
                }]
            },
            {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
176
                label: Lang.string('app.view'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
177 178
                submenu:  [
                    {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
179
                        label: Lang.string('app.switch_to_full_screen'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
180 181 182 183 184 185 186 187 188
                        accelerator: 'Ctrl+Command+F',
                        click: () => {
                            const mainWin = this._windows.get('main');
                            mainWin.browserWindow.setFullScreen(!mainWin.browserWindow.isFullScreen());
                        }
                    }
                ]
            },
            {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
189
                label: Lang.string('app.window'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
190 191
                submenu: [
                    {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
192
                        label: Lang.string('app.minimize'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
193 194 195 196
                        accelerator: 'Command+M',
                        selector: 'performMiniaturize:'
                    },
                    {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
197
                        label: Lang.string('app.close'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
198 199 200 201 202 203 204
                        accelerator: 'Command+W',
                        selector: 'performClose:'
                    },
                    {
                        type: 'separator'
                    },
                    {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
205
                        label: Lang.string('app.bring_all_to_front'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
206 207 208 209 210
                        selector: 'arrangeInFront:'
                    }
                ]
            },
            {
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
211
                label: Lang.string('app.help'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
212
                submenu: [{
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
213
                    label: Lang.string('app.website'),
aaronchen2k2k's avatar
aaronchen2k2k 已提交
214 215 216 217 218 219 220 221 222
                    click: () => {
                        shell.openExternal('http://ztf.im');
                    }
                }]
            }];

        const menu = Menu.buildFromTemplate(template);
        Menu.setApplicationMenu(menu);
    }
223
}