fchat-rising/electron/main.ts

821 lines
32 KiB
TypeScript
Raw Permalink Normal View History

2017-09-02 01:50:31 +00:00
/**
* @license
* MIT License
*
* Copyright (c) 2018 F-List
2017-09-02 01:50:31 +00:00
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* This license header applies to this file and all of the non-third-party assets it includes.
* @file The entry point for the Electron main thread of F-Chat 3.0.
* @copyright 2018 F-List
2017-09-02 01:50:31 +00:00
* @author Maya Wolf <maya@f-list.net>
* @version 3.0
* @see {@link https://github.com/f-list/exported|GitHub repo}
*/
// import { DebugLogger } from './debug-logger';
// // @ts-ignore
// const dl = new DebugLogger('main');
2017-09-02 01:50:31 +00:00
import * as electron from 'electron';
2021-09-11 01:59:05 +00:00
import * as remoteMain from '@electron/remote/main';
import log from 'electron-log'; //tslint:disable-line:match-default-export-name
2018-01-06 16:14:21 +00:00
import * as fs from 'fs';
2017-09-02 01:50:31 +00:00
import * as path from 'path';
2020-03-15 16:23:39 +00:00
// import * as url from 'url';
2018-01-06 16:14:21 +00:00
import l from '../chat/localize';
2019-09-17 17:14:14 +00:00
import {defaultHost, GeneralSettings} from './common';
import { getSafeLanguages, knownLanguageNames, updateSupportedLanguages } from './language';
2017-09-02 01:50:31 +00:00
import * as windowState from './window_state';
2021-09-11 01:59:05 +00:00
// import BrowserWindow = electron.BrowserWindow;
import MenuItem = electron.MenuItem;
import MenuItemConstructorOptions = electron.MenuItemConstructorOptions;
2020-04-03 00:46:36 +00:00
import * as _ from 'lodash';
2021-09-11 01:59:05 +00:00
import DownloadItem = electron.DownloadItem;
import { AdCoordinatorHost } from '../chat/ads/ad-coordinator-host';
import { IpcMainEvent } from 'electron';
2021-09-11 20:43:33 +00:00
import { BlockerIntegration } from './blocker/blocker';
2017-09-02 01:50:31 +00:00
2020-06-29 22:01:06 +00:00
//tslint:disable-next-line:no-require-imports
2020-06-23 23:38:16 +00:00
const pck = require('./package.json');
2017-09-02 01:50:31 +00:00
// Module to control application life.
const app = electron.app;
2021-12-24 04:51:27 +00:00
// tslint:disable-next-line:no-require-imports
const pngIcon = path.join(__dirname, <string>require('./build/icon.png').default);
// tslint:disable-next-line:no-require-imports
const winIcon = path.join(__dirname, <string>require('./build/icon.ico').default);
2021-09-11 01:59:05 +00:00
remoteMain.initialize();
2017-09-02 01:50:31 +00:00
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
2021-09-11 01:59:05 +00:00
const windows: electron.BrowserWindow[] = [];
2018-01-06 16:14:21 +00:00
const characters: string[] = [];
let tabCount = 0;
2017-09-02 01:50:31 +00:00
const baseDir = app.getPath('userData');
2019-09-17 17:14:14 +00:00
fs.mkdirSync(baseDir, {recursive: true});
2018-08-10 16:59:37 +00:00
let shouldImportSettings = false;
const settingsDir = path.join(baseDir, 'data');
2019-09-17 17:14:14 +00:00
fs.mkdirSync(settingsDir, {recursive: true});
2018-08-10 16:59:37 +00:00
const settingsFile = path.join(settingsDir, 'settings');
const settings = new GeneralSettings();
2017-09-02 01:50:31 +00:00
2018-09-28 00:08:10 +00:00
if(!fs.existsSync(settingsFile)) shouldImportSettings = true;
else
try {
Object.assign(settings, <GeneralSettings>JSON.parse(fs.readFileSync(settingsFile, 'utf8')));
} catch(e) {
log.error(`Error loading settings: ${e}`);
}
if(!settings.hwAcceleration) {
log.info('Disabling hardware acceleration.');
app.disableHardwareAcceleration();
}
2020-04-03 00:46:36 +00:00
// async function setDictionary(lang: string | undefined): Promise<void> {
// if(lang !== undefined) await ensureDictionary(lang);
// settings.spellcheckLang = lang;
// setGeneralSettings(settings);
// }
export function updateSpellCheckerLanguages(langs: string[]): void {
2020-04-12 14:07:09 +00:00
// console.log('UPDATESPELLCHECKERLANGUAGES', langs);
2020-04-03 00:46:36 +00:00
// console.log('Language support:', langs);
2020-04-11 14:48:09 +00:00
electron.session.defaultSession.setSpellCheckerLanguages(langs);
2020-04-03 00:46:36 +00:00
for (const w of windows) {
// console.log('LANG SEND');
2020-04-11 14:48:09 +00:00
w.webContents.session.setSpellCheckerLanguages(langs);
2020-04-03 00:46:36 +00:00
w.webContents.send('update-dictionaries', langs);
}
}
async function toggleDictionary(lang: string): Promise<void> {
const activeLangs = getSafeLanguages(settings.spellcheckLang);
// console.log('INITIAL LANG', activeLangs, lang);
let newLangs: string[] = [];
if (_.indexOf(activeLangs, lang) >= 0) {
newLangs = _.reject(activeLangs, (al) => (al === lang));
} else {
activeLangs.push(lang);
newLangs = activeLangs;
}
2022-09-03 18:47:11 +00:00
settings.spellcheckLang = _.uniq(newLangs);
2020-04-03 00:46:36 +00:00
2018-01-06 16:14:21 +00:00
setGeneralSettings(settings);
2020-04-03 00:46:36 +00:00
// console.log('NEW LANG', newLangs);
updateSpellCheckerLanguages(newLangs);
2018-01-06 16:14:21 +00:00
}
2017-09-02 01:50:31 +00:00
2018-01-06 16:14:21 +00:00
function setGeneralSettings(value: GeneralSettings): void {
fs.writeFileSync(path.join(settingsDir, 'settings'), JSON.stringify(value));
for(const w of electron.webContents.getAllWebContents()) w.send('settings', settings);
2020-06-30 21:51:06 +00:00
2018-01-06 16:14:21 +00:00
shouldImportSettings = false;
2020-06-30 21:51:06 +00:00
log.transports.file.level = settings.risingSystemLogLevel;
log.transports.console.level = settings.risingSystemLogLevel;
2017-09-02 01:50:31 +00:00
}
2021-09-11 01:59:05 +00:00
async function addSpellcheckerItems(menu: electron.Menu): Promise<void> {
2020-04-03 00:46:36 +00:00
const selected = getSafeLanguages(settings.spellcheckLang);
const langs = electron.session.defaultSession.availableSpellCheckerLanguages;
const sortedLangs = _.sortBy(
_.map(
langs,
(lang) => ({lang, name: (lang in knownLanguageNames) ? `${(knownLanguageNames as any)[lang]} (${lang})` : lang})
),
'name'
);
for (const lang of sortedLangs)
2018-01-06 16:14:21 +00:00
menu.append(new electron.MenuItem({
2020-04-03 00:46:36 +00:00
type: 'checkbox',
label: lang.name,
checked: (_.indexOf(selected, lang.lang) >= 0),
click: async() => toggleDictionary(lang.lang)
2018-01-06 16:14:21 +00:00
}));
}
function openURLExternally(linkUrl: string): void {
// check if user set a path and whether it exists
const pathIsValid = (settings.browserPath !== '' && fs.existsSync(settings.browserPath));
if(pathIsValid) {
// also check if the user can execute whatever is located at the selected path
let fileIsExecutable = false;
try {
fs.accessSync(settings.browserPath, fs.constants.X_OK);
fileIsExecutable = true;
} catch (err) {
log.error(`Selected browser is not executable by user. Path: "${settings.browserPath}"`);
}
if (fileIsExecutable) {
// regular expression that looks for an encoded % symbol followed by two hexadecimal characters
// using this expression, we can find parts of the URL that were encoded twice
const re = new RegExp('%25([0-9a-f]{2})', 'ig');
// encode the URL no matter what
linkUrl = encodeURI(linkUrl);
// eliminate double-encoding using expression above
linkUrl = linkUrl.replace(re, '%$1');
if (!settings.browserArgs.includes('%s')) {
// append %s to params if it is not already there
settings.browserArgs += ' %s';
}
// replace %s in arguments with URL and encapsulate in quotes to prevent issues with spaces and special characters in the path
let link = settings.browserArgs.replace('%s', '\"' + linkUrl + '\"');
const execFile = require('child_process').exec;
if (process.platform === "darwin") {
// NOTE: This is seemingly bugged on MacOS when setting Safari as the external browser while using a different default browser.
// In that case, this will open the URL in both the selected application AND the default browser.
// Other browsers work fine. (Tested with Chrome with Firefox as the default browser.)
// https://developer.apple.com/forums/thread/685385
execFile(`open -a "${settings.browserPath}" ${link}`);
} else {
execFile(`"${settings.browserPath}" ${link}`);
}
return;
}
}
electron.shell.openExternal(linkUrl);
}
2021-09-11 01:59:05 +00:00
function setUpWebContents(webContents: electron.WebContents): void {
2021-12-23 22:59:09 +00:00
remoteMain.enable(webContents);
2017-09-02 01:50:31 +00:00
const openLinkExternally = (e: Event, linkUrl: string) => {
e.preventDefault();
const profileMatch = linkUrl.match(/^https?:\/\/(www\.)?f-list.net\/c\/([^/#]+)\/?#?/);
if(profileMatch !== null && settings.profileViewer) {
webContents.send('open-profile', decodeURIComponent(profileMatch[2]));
return;
}
// otherwise, try to open externally
openURLExternally(linkUrl);
2017-09-02 01:50:31 +00:00
};
2021-09-07 00:57:01 +00:00
webContents.setVisualZoomLevelLimits(1, 5);
2018-01-06 16:14:21 +00:00
webContents.on('will-navigate', openLinkExternally);
2021-09-11 02:20:31 +00:00
// webContents.setWindowOpenHandler(openLinkExternally);
2018-01-06 16:14:21 +00:00
webContents.on('new-window', openLinkExternally);
2017-09-02 01:50:31 +00:00
}
2021-09-11 01:59:05 +00:00
function createWindow(): electron.BrowserWindow | undefined {
2018-01-06 16:14:21 +00:00
if(tabCount >= 3) return;
2017-09-02 01:50:31 +00:00
const lastState = windowState.getSavedWindowState();
2021-09-11 01:59:05 +00:00
const windowProperties: electron.BrowserWindowConstructorOptions & {maximized: boolean} = {
2021-12-23 22:59:09 +00:00
...lastState,
center: lastState.x === undefined,
show: false,
icon: process.platform === 'win32' ? winIcon : pngIcon,
2021-09-11 01:59:05 +00:00
webPreferences: {
webviewTag: true, nodeIntegration: true, nodeIntegrationInWorker: true, spellcheck: true,
2021-09-11 20:43:33 +00:00
enableRemoteModule: true, contextIsolation: false, partition: 'persist:fchat'
2021-09-11 01:59:05 +00:00
} as any
2018-01-06 16:14:21 +00:00
};
2020-03-15 15:22:55 +00:00
if(process.platform === 'darwin') {
2020-03-15 16:23:39 +00:00
windowProperties.titleBarStyle = 'hiddenInset';
// windowProperties.frame = true;
2020-03-15 15:22:55 +00:00
} else {
windowProperties.frame = false;
}
const window = new electron.BrowserWindow(windowProperties);
2021-12-23 22:59:09 +00:00
remoteMain.enable(window.webContents);
windows.push(window);
2017-09-02 01:50:31 +00:00
2021-12-24 04:51:27 +00:00
// window.setIcon(process.platform === 'win32' ? winIcon : pngIcon);
2021-12-23 22:59:09 +00:00
window.webContents.on('will-attach-webview', () => {
const all = electron.webContents.getAllWebContents();
all.forEach((item) => {
remoteMain.enable(item);
});
});
2020-04-12 14:07:09 +00:00
updateSupportedLanguages(electron.session.defaultSession.availableSpellCheckerLanguages);
const safeLanguages = getSafeLanguages(settings.spellcheckLang);
// console.log('CREATEWINDOW', safeLanguages);
2020-04-03 00:46:36 +00:00
electron.session.defaultSession.setSpellCheckerLanguages(safeLanguages);
2020-04-11 14:48:09 +00:00
window.webContents.session.setSpellCheckerLanguages(safeLanguages);
2020-04-03 00:46:36 +00:00
2021-09-11 20:43:33 +00:00
// Set up ad blocker
BlockerIntegration.factory(baseDir);
2020-04-04 20:22:42 +00:00
// This prevents automatic download prompts on certain webview URLs without
// stopping conversation logs from being downloaded
electron.session.defaultSession.on(
'will-download',
(e: Event, item: DownloadItem) => {
if (!item.getURL().match(/^blob:file:/)) {
2020-10-31 21:12:22 +00:00
log.info('download.prevent', { item, event: e });
2020-04-04 20:22:42 +00:00
e.preventDefault();
}
}
);
2020-04-02 00:27:21 +00:00
// tslint:disable-next-line:no-floating-promises
2020-03-15 15:22:55 +00:00
window.loadFile(
path.join(__dirname, 'window.html'),
{
2020-04-02 00:27:21 +00:00
query: {settings: JSON.stringify(settings), import: shouldImportSettings ? 'true' : ''}
2020-03-15 15:22:55 +00:00
}
);
2020-04-01 22:19:55 +00:00
2020-03-15 15:22:55 +00:00
// window.loadURL(url.format({ //tslint:disable-line:no-floating-promises
// pathname: path.join(__dirname, 'window.html'),
// protocol: 'file:',
// slashes: true,
// query: {settings: JSON.stringify(settings), import: shouldImportSettings ? 'true' : []}
// }));
2017-09-02 01:50:31 +00:00
2018-01-06 16:14:21 +00:00
setUpWebContents(window.webContents);
2017-09-02 01:50:31 +00:00
2018-01-06 16:14:21 +00:00
// Save window state when it is being closed.
window.on('close', () => windowState.setSavedWindowState(window));
window.on('closed', () => windows.splice(windows.indexOf(window), 1));
2018-03-28 13:51:05 +00:00
window.once('ready-to-show', () => {
window.show();
if(lastState.maximized) window.maximize();
});
2018-01-06 16:14:21 +00:00
return window;
}
function showPatchNotes(): void {
2020-06-29 22:01:06 +00:00
//tslint:disable-next-line: no-floating-promises
openURLExternally('https://github.com/hearmeneigh/fchat-rising/blob/master/CHANGELOG.md');
2018-01-06 16:14:21 +00:00
}
function openBrowserSettings(): electron.BrowserWindow | undefined {
let desiredHeight = 520;
if(process.platform === 'darwin') {
desiredHeight = 750;
}
const windowProperties: electron.BrowserWindowConstructorOptions = {
center: true,
show: false,
icon: process.platform === 'win32' ? winIcon : pngIcon,
frame: false,
width: 650,
height: desiredHeight,
minWidth: 650,
minHeight: desiredHeight,
maxWidth: 650,
maxHeight: desiredHeight,
maximizable: false,
webPreferences: {
webviewTag: true, nodeIntegration: true, nodeIntegrationInWorker: true, spellcheck: true,
enableRemoteModule: true, contextIsolation: false, partition: 'persist:fchat'
} as any
};
const browserWindow = new electron.BrowserWindow(windowProperties);
remoteMain.enable(browserWindow.webContents);
browserWindow.loadFile(path.join(__dirname, 'browser_option.html'), {
query: { settings: JSON.stringify(settings), import: shouldImportSettings ? 'true' : '' }
});
browserWindow.once('ready-to-show', () => {
browserWindow.show();
});
return browserWindow;
}
2021-09-07 00:57:01 +00:00
let zoomLevel = 0;
2018-01-06 16:14:21 +00:00
function onReady(): void {
2020-07-05 17:43:27 +00:00
let hasCompletedUpgrades = false;
2020-06-30 16:46:38 +00:00
const logLevel = (process.env.NODE_ENV === 'production') ? 'info' : 'silly';
2020-07-01 14:33:36 +00:00
log.transports.file.level = settings.risingSystemLogLevel || logLevel;
log.transports.console.level = settings.risingSystemLogLevel || logLevel;
2018-08-10 16:59:37 +00:00
log.transports.file.maxSize = 5 * 1024 * 1024;
2020-06-30 16:46:38 +00:00
2018-08-10 16:59:37 +00:00
log.info('Starting application.');
app.setAppUserModelId('com.squirrel.fchat.F-Chat');
2018-01-06 16:14:21 +00:00
app.on('open-file', createWindow);
if(settings.version !== app.getVersion()) {
showPatchNotes();
2019-09-17 17:14:14 +00:00
if(settings.host === 'wss://chat.f-list.net:9799')
settings.host = defaultHost;
2018-01-06 16:14:21 +00:00
settings.version = app.getVersion();
setGeneralSettings(settings);
}
2020-06-23 23:38:16 +00:00
// require('update-electron-app')(
// {
2023-09-02 20:41:44 +00:00
// repo: 'https://github.com/hearmeneigh/fchat-rising.git',
2020-06-23 23:38:16 +00:00
// updateInterval: '3 hours',
// logger: require('electron-log')
// }
// );
2020-06-29 22:01:06 +00:00
//tslint:disable-next-line: no-unsafe-any
2023-09-02 20:41:44 +00:00
const updaterUrl = `https://update.electronjs.org/hearmeneigh/fchat-rising/${process.platform}-${process.arch}/${pck.version}`;
if((process.env.NODE_ENV === 'production') && (process.platform !== 'darwin')) {
2020-06-23 23:38:16 +00:00
electron.autoUpdater.setFeedURL({url: updaterUrl + (settings.beta ? '?channel=beta' : ''), serverType: 'json'});
setTimeout(() => electron.autoUpdater.checkForUpdates(), 10000);
const updateTimer = setInterval(() => electron.autoUpdater.checkForUpdates(), 3600000);
electron.autoUpdater.on('update-downloaded', () => {
clearInterval(updateTimer);
const menu = electron.Menu.getApplicationMenu()!;
const item = menu.getMenuItemById('update') as MenuItem | null;
if(item !== null) item.visible = true;
else
menu.append(new electron.MenuItem({
label: l('action.updateAvailable'),
submenu: electron.Menu.buildFromTemplate([{
label: l('action.update'),
click: () => {
for(const w of windows) w.webContents.send('quit');
electron.autoUpdater.quitAndInstall();
}
}, {
label: l('help.changelog'),
click: showPatchNotes
}]),
id: 'update'
}));
electron.Menu.setApplicationMenu(menu);
for(const w of windows) w.webContents.send('update-available', true);
});
electron.autoUpdater.on('update-not-available', () => {
for(const w of windows) w.webContents.send('update-available', false);
const item = electron.Menu.getApplicationMenu()!.getMenuItemById('update') as MenuItem | null;
if(item !== null) item.visible = false;
});
electron.autoUpdater.on('error', (e) => log.error(e));
}
2018-01-06 16:14:21 +00:00
const viewItem = {
label: `&${l('action.view')}`,
2021-09-11 01:59:05 +00:00
submenu: <electron.MenuItemConstructorOptions[]>[
2021-09-07 00:57:01 +00:00
// {role: 'resetZoom'},
{
label: 'Reset Zoom',
2021-09-11 01:59:05 +00:00
click: (_m: electron.MenuItem, _w: electron.BrowserWindow) => {
2021-09-07 00:57:01 +00:00
// log.info('MENU ZOOM0');
// w.webContents.setZoomLevel(0);
zoomLevel = 0;
for(const win of electron.webContents.getAllWebContents()) win.send('update-zoom', 0);
for(const win of windows) win.webContents.send('update-zoom', 0);
},
accelerator: 'CmdOrCtrl+0'
},
{
// role: 'zoomIn',
label: 'Zoom In',
2021-09-11 01:59:05 +00:00
click: (_m: electron.MenuItem, w: electron.BrowserWindow) => {
2021-09-07 00:57:01 +00:00
// log.info('MENU ZOOM+');
zoomLevel = Math.min(zoomLevel + w.webContents.getZoomFactor()/2, 6);
// w.webContents.setZoomLevel(newZoom);
for(const win of electron.webContents.getAllWebContents()) win.send('update-zoom', zoomLevel);
for(const win of windows) win.webContents.send('update-zoom', zoomLevel);
},
accelerator: 'CmdOrCtrl+Plus'
},
{
// role: 'zoomIn',
label: 'Zoom Out',
2021-09-11 01:59:05 +00:00
click: (_m: electron.MenuItem, w: electron.BrowserWindow) => {
2021-09-07 00:57:01 +00:00
// log.info('MENU ZOOM-');
zoomLevel = Math.max(0, zoomLevel - w.webContents.getZoomFactor()/2);
// w.webContents.setZoomLevel(newZoom);
for(const win of electron.webContents.getAllWebContents()) win.send('update-zoom', zoomLevel);
for(const win of windows) win.webContents.send('update-zoom', zoomLevel);
},
accelerator: 'CmdOrCtrl+-'
},
// {role: 'zoomOut'},
2018-01-06 16:14:21 +00:00
{type: 'separator'},
{role: 'togglefullscreen'}
]
};
if(process.env.NODE_ENV !== 'production')
2020-04-02 00:27:21 +00:00
viewItem.submenu.unshift({role: 'reload'}, {role: 'forceReload'}, {role: 'toggleDevTools'}, {type: 'separator'});
2018-01-06 16:14:21 +00:00
const spellcheckerMenu = new electron.Menu();
2021-12-23 22:59:09 +00:00
2018-01-06 16:14:21 +00:00
//tslint:disable-next-line:no-floating-promises
addSpellcheckerItems(spellcheckerMenu);
const themes = fs.readdirSync(path.join(__dirname, 'themes')).filter((x) => x.substr(-4) === '.css').map((x) => x.slice(0, -4));
const setTheme = (theme: string) => {
settings.theme = theme;
setGeneralSettings(settings);
};
2020-06-30 21:51:06 +00:00
const setSystemLogLevel = (logLevell: log.LevelOption) => {
settings.risingSystemLogLevel = logLevell;
2020-06-30 21:51:06 +00:00
setGeneralSettings(settings);
};
2018-01-06 16:14:21 +00:00
electron.Menu.setApplicationMenu(electron.Menu.buildFromTemplate([
{
label: `&${l('title')}`,
submenu: [
2020-07-05 17:43:27 +00:00
{
label: l('action.newWindow'),
click: () => {
if (hasCompletedUpgrades) createWindow();
},
accelerator: 'CmdOrCtrl+n'
},
2018-01-06 16:14:21 +00:00
{
label: l('action.newTab'),
2021-09-11 01:59:05 +00:00
click: (_m: electron.MenuItem, w: electron.BrowserWindow) => {
2020-07-05 17:43:27 +00:00
if((hasCompletedUpgrades) && (tabCount < 3)) w.webContents.send('open-tab');
2018-01-06 16:14:21 +00:00
},
accelerator: 'CmdOrCtrl+t'
},
{
label: l('settings.logDir'),
2021-09-11 01:59:05 +00:00
click: (_m, window: electron.BrowserWindow) => {
2020-04-02 00:27:21 +00:00
const dir = electron.dialog.showOpenDialogSync(
2019-09-17 17:14:14 +00:00
{defaultPath: settings.logDirectory, properties: ['openDirectory']});
2018-01-06 16:14:21 +00:00
if(dir !== undefined) {
if(dir[0].startsWith(path.dirname(app.getPath('exe'))))
return electron.dialog.showErrorBox(l('settings.logDir'), l('settings.logDir.inAppDir'));
2020-04-02 00:27:21 +00:00
const button = electron.dialog.showMessageBoxSync(window, {
2018-01-06 16:14:21 +00:00
message: l('settings.logDir.confirm', dir[0], settings.logDirectory),
buttons: [l('confirmYes'), l('confirmNo')],
cancelId: 1
});
if(button === 0) {
2018-03-28 13:51:05 +00:00
for(const w of windows) w.webContents.send('quit');
2018-01-06 16:14:21 +00:00
settings.logDirectory = dir[0];
setGeneralSettings(settings);
app.quit();
}
}
}
},
{
label: l('settings.closeToTray'), type: 'checkbox', checked: settings.closeToTray,
2021-09-11 01:59:05 +00:00
click: (item: electron.MenuItem) => {
2018-01-06 16:14:21 +00:00
settings.closeToTray = item.checked;
setGeneralSettings(settings);
}
}, {
label: l('settings.profileViewer'), type: 'checkbox', checked: settings.profileViewer,
2021-09-11 01:59:05 +00:00
click: (item: electron.MenuItem) => {
2018-01-06 16:14:21 +00:00
settings.profileViewer = item.checked;
setGeneralSettings(settings);
}
},
{label: l('settings.spellcheck'), submenu: spellcheckerMenu},
{
label: l('settings.theme'),
submenu: themes.map((x) => ({
checked: settings.theme === x,
click: () => setTheme(x),
label: x,
type: <'radio'>'radio'
}))
2018-09-28 00:08:10 +00:00
}, {
label: l('settings.hwAcceleration'), type: 'checkbox', checked: settings.hwAcceleration,
2021-09-11 01:59:05 +00:00
click: (item: electron.MenuItem) => {
2018-09-28 00:08:10 +00:00
settings.hwAcceleration = item.checked;
setGeneralSettings(settings);
}
2020-06-30 21:51:06 +00:00
},
// {
// label: l('settings.beta'), type: 'checkbox', checked: settings.beta,
2021-09-11 01:59:05 +00:00
// click: async(item: electron.MenuItem) => {
2020-06-30 21:51:06 +00:00
// settings.beta = item.checked;
// setGeneralSettings(settings);
// // electron.autoUpdater.setFeedURL({url: updaterUrl+(item.checked ? '?channel=beta' : ''), serverType: 'json'});
// // return electron.autoUpdater.checkForUpdates();
// }
// },
{
2018-03-28 13:51:05 +00:00
label: l('fixLogs.action'),
2021-09-11 01:59:05 +00:00
click: (_m, window: electron.BrowserWindow) => window.webContents.send('fix-logs')
2018-01-06 16:14:21 +00:00
},
2020-06-30 21:51:06 +00:00
{type: 'separator'},
{
label: 'Rising',
submenu: [
{
label: 'System log level',
submenu: ['error', 'warn', 'info', 'verbose', 'debug', 'silly'].map((level: string) => (
{
checked: settings.risingSystemLogLevel === level,
label: `${level.substr(0, 1).toUpperCase()}${level.substr(1)}`,
click: () => setSystemLogLevel(level as log.LevelOption),
type: <'radio'>'radio'
}
))
},
{
visible: process.platform === 'win32',
label: 'Disable Windows high-contrast mode',
type: 'checkbox',
checked: settings.risingDisableWindowsHighContrast,
click: (item: electron.MenuItem) => {
settings.risingDisableWindowsHighContrast = item.checked;
setGeneralSettings(settings);
}
},
{
label: l('settings.browserOption'),
click: () => {
openBrowserSettings();
}
2020-06-30 21:51:06 +00:00
}
]
},
2020-10-08 02:24:02 +00:00
{
label: 'Show/hide current profile',
2021-09-11 01:59:05 +00:00
click: (_m: electron.MenuItem, w: electron.BrowserWindow) => {
2020-10-08 02:24:02 +00:00
w.webContents.send('reopen-profile');
},
accelerator: 'CmdOrCtrl+p'
},
2020-06-30 21:51:06 +00:00
2018-01-06 16:14:21 +00:00
{type: 'separator'},
{role: 'minimize'},
{
accelerator: process.platform === 'darwin' ? 'Cmd+Q' : undefined,
label: l('action.quit'),
2021-09-11 01:59:05 +00:00
click(_m: electron.MenuItem, window: electron.BrowserWindow): void {
2018-01-06 16:14:21 +00:00
if(characters.length === 0) return app.quit();
2020-04-02 00:27:21 +00:00
const button = electron.dialog.showMessageBoxSync(window, {
2018-01-06 16:14:21 +00:00
message: l('chat.confirmLeave'),
buttons: [l('confirmYes'), l('confirmNo')],
cancelId: 1
});
if(button === 0) {
for(const w of windows) w.webContents.send('quit');
app.quit();
}
2018-01-06 16:14:21 +00:00
}
}
2020-04-02 00:27:21 +00:00
] as MenuItemConstructorOptions[]
2018-01-06 16:14:21 +00:00
}, {
label: `&${l('action.edit')}`,
submenu: [
{role: 'undo'},
{role: 'redo'},
{type: 'separator'},
{role: 'cut'},
{role: 'copy'},
{role: 'paste'},
{role: 'selectall'}
2020-04-02 00:27:21 +00:00
] as MenuItemConstructorOptions[]
2018-01-06 16:14:21 +00:00
}, viewItem, {
label: `&${l('help')}`,
submenu: [
{
label: l('help.fchat'),
click: () => openURLExternally('https://github.com/hearmeneigh/fchat-rising/blob/master/README.md')
2018-01-06 16:14:21 +00:00
},
// {
// label: l('help.feedback'),
// click: () => openURLExternally('https://goo.gl/forms/WnLt3Qm3TPt64jQt2')
// },
2018-01-06 16:14:21 +00:00
{
label: l('help.rules'),
click: () => openURLExternally('https://wiki.f-list.net/Rules')
2018-01-06 16:14:21 +00:00
},
{
label: l('help.faq'),
click: () => openURLExternally('https://wiki.f-list.net/Frequently_Asked_Questions')
2018-01-06 16:14:21 +00:00
},
{
label: l('help.report'),
click: () => openURLExternally('https://wiki.f-list.net/How_to_Report_a_User#In_chat')
2018-01-06 16:14:21 +00:00
},
{label: l('version', app.getVersion()), click: showPatchNotes}
]
}
]));
2021-12-23 22:59:09 +00:00
2020-04-03 00:46:36 +00:00
electron.ipcMain.on('tab-added', (_event: Event, id: number) => {
2018-01-06 16:14:21 +00:00
const webContents = electron.webContents.fromId(id);
2021-12-23 22:59:09 +00:00
2018-01-06 16:14:21 +00:00
setUpWebContents(webContents);
++tabCount;
if(tabCount === 3)
for(const w of windows) w.webContents.send('allow-new-tabs', false);
});
electron.ipcMain.on('tab-closed', () => {
--tabCount;
for(const w of windows) w.webContents.send('allow-new-tabs', true);
});
2020-04-03 00:46:36 +00:00
electron.ipcMain.on('save-login', (_event: Event, account: string, host: string) => {
2018-01-06 16:14:21 +00:00
settings.account = account;
settings.host = host;
setGeneralSettings(settings);
});
2021-09-11 01:59:05 +00:00
electron.ipcMain.on('connect', (e: Event & {sender: electron.WebContents}, character: string) => {
2018-01-06 16:14:21 +00:00
if(characters.indexOf(character) !== -1) return e.returnValue = false;
2019-09-17 17:14:14 +00:00
characters.push(character);
2018-01-06 16:14:21 +00:00
e.returnValue = true;
});
2020-04-03 00:46:36 +00:00
electron.ipcMain.on('dictionary-add', (_event: Event, word: string) => {
// if(settings.customDictionary.indexOf(word) !== -1) return;
// settings.customDictionary.push(word);
// setGeneralSettings(settings);
for(const w of windows) w.webContents.session.addWordToSpellCheckerDictionary(word);
2018-08-10 16:59:37 +00:00
});
2020-04-03 00:46:36 +00:00
electron.ipcMain.on('dictionary-remove', (_event: Event /*, word: string*/) => {
// settings.customDictionary.splice(settings.customDictionary.indexOf(word), 1);
// setGeneralSettings(settings);
2018-08-10 16:59:37 +00:00
});
2020-04-03 00:46:36 +00:00
electron.ipcMain.on('disconnect', (_event: Event, character: string) => {
2019-01-03 17:38:17 +00:00
const index = characters.indexOf(character);
if(index !== -1) characters.splice(index, 1);
});
const adCoordinator = new AdCoordinatorHost();
electron.ipcMain.on('request-send-ad', (event: IpcMainEvent, adId: string) => (adCoordinator.processAdRequest(event, adId)));
2018-01-06 16:14:21 +00:00
const emptyBadge = electron.nativeImage.createEmpty();
2020-06-29 22:01:06 +00:00
2020-10-24 20:47:50 +00:00
const badge = electron.nativeImage.createFromPath(
//tslint:disable-next-line:no-require-imports no-unsafe-any
path.join(__dirname, <string>require('./build/badge.png').default)
);
2020-06-29 22:01:06 +00:00
2021-09-11 01:59:05 +00:00
electron.ipcMain.on('has-new', (e: Event & {sender: electron.WebContents}, hasNew: boolean) => {
2018-01-06 16:14:21 +00:00
if(process.platform === 'darwin') app.dock.setBadge(hasNew ? '!' : '');
2021-09-11 01:59:05 +00:00
const window = electron.BrowserWindow.fromWebContents(e.sender) as electron.BrowserWindow | undefined;
2018-03-28 13:51:05 +00:00
if(window !== undefined) window.setOverlayIcon(hasNew ? badge : emptyBadge, hasNew ? 'New messages' : '');
2018-01-06 16:14:21 +00:00
});
electron.ipcMain.on('rising-upgrade-complete', () => {
2021-01-23 17:45:36 +00:00
// console.log('RISING COMPLETE SHARE');
2020-07-05 17:43:27 +00:00
hasCompletedUpgrades = true;
for(const w of electron.webContents.getAllWebContents()) w.send('rising-upgrade-complete');
});
2021-09-11 01:59:05 +00:00
electron.ipcMain.on('update-zoom', (_e, zl: number) => {
2021-09-07 00:57:01 +00:00
// log.info('MENU ZOOM UPDATE', zoomLevel);
2021-09-11 01:59:05 +00:00
for(const w of electron.webContents.getAllWebContents()) w.send('update-zoom', zl);
2021-09-07 00:57:01 +00:00
});
electron.ipcMain.handle('browser-option-browse', async () => {
log.debug('settings.browserOption.browse');
console.log('settings.browserOption.browse', JSON.stringify(settings));
let filters;
if(process.platform === "win32") {
filters = [{ name: 'Executables', extensions: ['exe'] }];
} else if (process.platform === "darwin") {
filters = [{ name: 'Executables', extensions: ['app'] }];
} else {
// linux and anything else that might be supported
// no specific extension for executables
filters = [{ name: 'Executables', extensions: ['*'] }];
}
const dir = electron.dialog.showOpenDialogSync(
{
defaultPath: settings.browserPath,
properties: ['openFile'],
filters: filters
});
if(dir !== undefined) {
return dir[0];
}
// we keep the current path if the user cancels the dialog
return settings.browserPath;
});
electron.ipcMain.on('browser-option-update', (_e, _path: string, _args: string) => {
log.debug('Browser Path settings update:', _path, _args);
// store the new path and args in our general settings
settings.browserPath = _path;
settings.browserArgs = _args;
setGeneralSettings(settings);
});
electron.ipcMain.on('open-url-externally', (_e, _url: string) => {
openURLExternally(_url);
});
2018-01-06 16:14:21 +00:00
createWindow();
2017-09-02 01:50:31 +00:00
}
2020-12-28 23:06:59 +00:00
// Twitter fix
app.commandLine.appendSwitch('disable-features', 'CrossOriginOpenerPolicy');
2018-08-10 16:59:37 +00:00
const isSquirrelStart = require('electron-squirrel-startup'); //tslint:disable-line:no-require-imports
2018-09-28 00:08:10 +00:00
if(isSquirrelStart || process.env.NODE_ENV === 'production' && !app.requestSingleInstanceLock()) app.quit();
2018-01-06 16:14:21 +00:00
else app.on('ready', onReady);
2018-09-28 00:08:10 +00:00
app.on('second-instance', createWindow);
app.on('window-all-closed', () => app.quit());