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

aaronchen2k2k's avatar
aaronchen2k2k 已提交
4
import {DEBUG} from './utils/consts';
aaronchen2k2k's avatar
aaronchen2k2k 已提交
5
import {IS_MAC_OSX} from './utils/env';
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
6
import Lang, {initLang} from './core/lang';
aaronchen2k2k's avatar
aaronchen2k2k 已提交
7
import {logInfo, logErr} from './utils/log';
aaronchen2k2k's avatar
aaronchen2k2k 已提交
8 9
import {startUIService} from "./core/ui";
import {startZtfServer, killZtfServer} from "./core/ztf";
10 11

export default class ZtfApp {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
12
    constructor() {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
13
        this._windows = new Map();
14

aaronchen2k2k's avatar
aaronchen2k2k 已提交
15
        startZtfServer().then((ztfServerUrl)=> {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
16
            if (ztfServerUrl) logInfo(`>> ztf server started successfully on : ${ztfServerUrl}`);
aaronchen2k2k's avatar
aaronchen2k2k 已提交
17 18
            this.bindElectronEvents();
        }).catch((err) => {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
19
            logErr('>> ztf server started failed, err: ' + err);
aaronchen2k2k's avatar
aaronchen2k2k 已提交
20
            process.exit(1);
aaronchen2k2k's avatar
aaronchen2k2k 已提交
21
            return;
aaronchen2k2k's avatar
aaronchen2k2k 已提交
22
        })
23 24 25
    }

    showAndFocus() {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
26
        logInfo(`>> ztf app: AppWindow[${this.name}]: show and focus`);
27 28 29 30 31 32 33 34 35 36 37

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

aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
38
    async createWindow() {
39 40
        process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';

aaronchen2k2k's avatar
aaronchen2k2k 已提交
41 42
        const remoteMain = require('@electron/remote/main')
        remoteMain.initialize()
43

aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
44
        const mainWin = new BrowserWindow({
45 46 47
            show: false,
            webPreferences: {nodeIntegration: true, contextIsolation: false}
        })
aaronchen2k2k's avatar
aaronchen2k2k 已提交
48
        remoteMain.enable(mainWin.webContents)
49

aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
50 51
        mainWin.maximize()
        mainWin.show()
52

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

aaronchen2k2k's avatar
aaronchen2k2k 已提交
55
        const url = await startUIService()
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
56
        await mainWin.loadURL(url);
aaronchen2k2k's avatar
aaronchen2k2k 已提交
57 58 59 60

        if (DEBUG) {
            mainWin.webContents.openDevTools({mode: 'bottom'});
        }
61 62
    };

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

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

aaronchen2k2k's avatar
aaronchen2k2k 已提交
82
    ready() {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
83
        logInfo('>> ztf app ready.');
aaronchen2k2k's avatar
i118  
aaronchen2k2k 已提交
84 85

        initLang()
aaronchen2k2k's avatar
aaronchen2k2k 已提交
86
        this.buildAppMenu();
aaronchen2k2k's avatar
aaronchen2k2k 已提交
87
        this.openOrCreateWindow()
aaronchen2k2k's avatar
aaronchen2k2k 已提交
88 89 90 91 92 93
    }

    quit() {
        killZtfServer();
    }

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

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

        app.on('activate', () => {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
106
            logInfo('>> event: activate');
107 108 109

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

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

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

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

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

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