2019-08-23 17:54:08 +02:00
|
|
|
import { WEBPACK_ELECTRON_PORT } from 'config';
|
2022-01-02 21:33:11 +01:00
|
|
|
import { app, BrowserWindow, dialog, screen, nativeImage } from 'electron';
|
2018-03-08 00:03:45 +01:00
|
|
|
import isDev from 'electron-is-dev';
|
2018-03-21 14:29:51 +01:00
|
|
|
import windowStateKeeper from 'electron-window-state';
|
2019-11-05 19:54:58 +01:00
|
|
|
import SUPPORTED_LANGUAGES from 'constants/supported_languages';
|
2021-04-06 21:14:45 +02:00
|
|
|
import { SUPPORTED_SUB_LANGUAGE_CODES, SUB_LANG_CODE_LEN } from 'constants/supported_sub_languages';
|
|
|
|
import SUPPORTED_BROWSER_LANGUAGES from 'constants/supported_browser_languages';
|
2020-08-13 18:57:00 +02:00
|
|
|
import { TO_TRAY_WHEN_CLOSED } from 'constants/settings';
|
2018-03-21 14:29:51 +01:00
|
|
|
|
2018-01-18 03:13:08 +01:00
|
|
|
import setupBarMenu from './menu/setupBarMenu';
|
2019-11-12 23:03:11 +01:00
|
|
|
import * as PAGES from 'constants/pages';
|
2022-01-02 21:33:11 +01:00
|
|
|
const remote = require('@electron/remote/main');
|
2022-02-16 22:48:09 +01:00
|
|
|
const shell = require('electron').shell;
|
2021-04-06 21:14:45 +02:00
|
|
|
function GetAppLangCode() {
|
|
|
|
// https://www.electronjs.org/docs/api/locales
|
|
|
|
// 1. Gets the user locale.
|
|
|
|
// 2. Converts unsupported sub-languages to its primary (e.g. "en-GB" -> "en").
|
|
|
|
// Note that the primary itself may or may not be a supported language
|
|
|
|
// (up to clients to verify against SUPPORTED_LANGUAGES).
|
|
|
|
const langCode = app.getLocale();
|
|
|
|
if (langCode.length === SUB_LANG_CODE_LEN && !SUPPORTED_SUB_LANGUAGE_CODES.includes(langCode)) {
|
|
|
|
return SUPPORTED_BROWSER_LANGUAGES[langCode.slice(0, 2)];
|
|
|
|
}
|
|
|
|
return SUPPORTED_BROWSER_LANGUAGES[langCode];
|
|
|
|
}
|
|
|
|
|
2018-02-24 00:20:12 +01:00
|
|
|
export default appState => {
|
2018-03-21 14:29:51 +01:00
|
|
|
// Get primary display dimensions from Electron.
|
|
|
|
const { width, height } = screen.getPrimaryDisplay().workAreaSize;
|
|
|
|
|
|
|
|
// Load the previous state with fallback to defaults.
|
|
|
|
const windowState = windowStateKeeper({
|
|
|
|
defaultWidth: width,
|
|
|
|
defaultHeight: height,
|
|
|
|
});
|
|
|
|
|
2019-11-18 19:30:15 +01:00
|
|
|
const startMinimized = (process.argv || []).includes('--hidden');
|
|
|
|
|
2018-07-05 04:49:12 +02:00
|
|
|
const windowConfiguration = {
|
2019-09-26 18:07:11 +02:00
|
|
|
backgroundColor: '#270f34', // Located in src/scss/init/_vars.scss `--color-background--splash`
|
2018-03-26 23:32:43 +02:00
|
|
|
minWidth: 950,
|
2018-01-18 03:13:08 +01:00
|
|
|
minHeight: 600,
|
|
|
|
autoHideMenuBar: true,
|
2019-10-09 18:34:18 +02:00
|
|
|
titleBarStyle: 'hiddenInset',
|
2018-01-18 03:13:08 +01:00
|
|
|
show: false,
|
2018-03-21 14:29:51 +01:00
|
|
|
// Create the window using the state information.
|
|
|
|
x: windowState.x,
|
|
|
|
y: windowState.y,
|
|
|
|
// If state is undefined, create window as maximized.
|
|
|
|
width: windowState.width === undefined ? width : windowState.width,
|
|
|
|
height: windowState.height === undefined ? height : windowState.height,
|
2020-09-07 00:46:30 +02:00
|
|
|
icon: nativeImage.createFromPath('static/img/tray/default/tray.png'),
|
2018-07-05 04:49:12 +02:00
|
|
|
webPreferences: {
|
|
|
|
// Disable renderer process's webSecurity on development to enable CORS.
|
|
|
|
webSecurity: !isDev,
|
|
|
|
plugins: true,
|
2020-09-07 00:46:30 +02:00
|
|
|
nodeIntegration: true,
|
2022-01-02 21:33:11 +01:00
|
|
|
contextIsolation: false,
|
2021-11-11 15:19:09 +01:00
|
|
|
enableRemoteModule: true, // see about removing this
|
2018-07-05 04:49:12 +02:00
|
|
|
},
|
|
|
|
};
|
2019-05-01 16:18:26 +02:00
|
|
|
const lbryProto = 'lbry://';
|
|
|
|
const lbryProtoQ = 'lbry://?';
|
2019-09-03 05:01:04 +02:00
|
|
|
const rendererURL = isDev ? `http://localhost:${WEBPACK_ELECTRON_PORT}` : `file://${__dirname}/index.html`;
|
2018-01-18 03:13:08 +01:00
|
|
|
|
|
|
|
let window = new BrowserWindow(windowConfiguration);
|
2022-01-02 21:33:11 +01:00
|
|
|
remote.enable(window.webContents);
|
2018-01-18 03:13:08 +01:00
|
|
|
|
2018-03-21 14:29:51 +01:00
|
|
|
// Let us register listeners on the window, so we can update the state
|
|
|
|
// automatically (the listeners will be removed when the window is closed)
|
|
|
|
// and restore the maximized or full screen state.
|
|
|
|
windowState.manage(window);
|
2018-01-18 03:13:08 +01:00
|
|
|
|
|
|
|
let deepLinkingURI;
|
2019-05-01 16:18:26 +02:00
|
|
|
|
2019-05-07 23:38:29 +02:00
|
|
|
if ((process.platform === 'win32' || process.platform === 'linux') && String(process.argv[1]).startsWith('lbry')) {
|
2019-05-01 16:18:26 +02:00
|
|
|
[, deepLinkingURI] = process.argv || '';
|
2018-01-18 03:13:08 +01:00
|
|
|
// Keep only command line / deep linked arguments
|
|
|
|
// Windows normalizes URIs when they're passed in from other apps. On Windows, this tries to
|
|
|
|
// restore the original URI that was typed.
|
|
|
|
// - If the URI has no path, Windows adds a trailing slash. LBRY URIs can't have a slash with no
|
|
|
|
// path, so we just strip it off.
|
|
|
|
// - In a URI with a claim ID, like lbry://channel#claimid, Windows interprets the hash mark as
|
|
|
|
// an anchor and converts it to lbry://channel/#claimid. We remove the slash here as well.
|
2018-06-05 17:22:15 +02:00
|
|
|
// - ? also interpreted as an anchor, remove slash also.
|
2018-03-20 00:03:14 +01:00
|
|
|
if (process.platform === 'win32') {
|
2018-06-05 17:22:15 +02:00
|
|
|
deepLinkingURI = deepLinkingURI
|
|
|
|
.replace(/\/$/, '')
|
|
|
|
.replace('/#', '#')
|
|
|
|
.replace('/?', '?');
|
2018-03-20 00:03:14 +01:00
|
|
|
}
|
|
|
|
} else {
|
2019-05-01 16:18:26 +02:00
|
|
|
deepLinkingURI = appState.macDeepLinkingURI || '';
|
|
|
|
}
|
|
|
|
|
|
|
|
// is it a lbry://? pointing to an app page
|
|
|
|
if (deepLinkingURI.includes(lbryProtoQ)) {
|
2019-08-29 01:53:48 +02:00
|
|
|
let path = deepLinkingURI.substr(lbryProtoQ.length);
|
|
|
|
let page = path.indexOf('?') >= 0 ? path.substring(0, path.indexOf('?')) : path;
|
|
|
|
if (Object.values(PAGES).includes(page)) {
|
2019-05-01 16:18:26 +02:00
|
|
|
deepLinkingURI = deepLinkingURI.replace(lbryProtoQ, '#/$/');
|
|
|
|
} else {
|
|
|
|
deepLinkingURI = '';
|
|
|
|
}
|
|
|
|
// else is it a claim
|
|
|
|
} else if (deepLinkingURI.includes(lbryProto)) {
|
|
|
|
deepLinkingURI = deepLinkingURI.replace(lbryProto, '#');
|
|
|
|
} else {
|
|
|
|
deepLinkingURI = '';
|
2018-01-18 03:13:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
setupBarMenu();
|
2019-01-31 14:32:44 +01:00
|
|
|
|
2019-11-05 19:54:58 +01:00
|
|
|
window.loadURL(rendererURL + deepLinkingURI);
|
2019-10-11 16:02:24 +02:00
|
|
|
|
2018-02-24 00:20:12 +01:00
|
|
|
window.on('close', event => {
|
2020-08-13 18:57:00 +02:00
|
|
|
if (appState.isQuitting) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!appState.autoUpdateAccepted) {
|
2018-02-24 00:20:12 +01:00
|
|
|
event.preventDefault();
|
2018-04-02 22:19:47 +02:00
|
|
|
if (window.isFullScreen()) {
|
|
|
|
window.once('leave-full-screen', () => {
|
|
|
|
window.hide();
|
|
|
|
});
|
|
|
|
window.setFullScreen(false);
|
|
|
|
} else {
|
|
|
|
window.hide();
|
|
|
|
}
|
2018-02-24 00:20:12 +01:00
|
|
|
}
|
2020-08-13 18:57:00 +02:00
|
|
|
|
|
|
|
const getToTrayWhenClosedSetting = window.webContents.executeJavaScript(`localStorage.getItem('${TO_TRAY_WHEN_CLOSED}')`);
|
|
|
|
|
|
|
|
getToTrayWhenClosedSetting.then(toTrayWhenClosedSetting => {
|
|
|
|
const closeApp = toTrayWhenClosedSetting === 'false';
|
|
|
|
|
|
|
|
if (closeApp) {
|
|
|
|
app.quit();
|
|
|
|
}
|
|
|
|
});
|
2018-01-18 03:13:08 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
window.on('focus', () => {
|
|
|
|
window.webContents.send('window-is-focused', null);
|
|
|
|
});
|
|
|
|
|
|
|
|
window.on('unresponsive', () => {
|
|
|
|
dialog.showMessageBox(
|
|
|
|
window,
|
|
|
|
{
|
|
|
|
type: 'warning',
|
|
|
|
buttons: ['Wait', 'Quit'],
|
|
|
|
title: 'LBRY Unresponsive',
|
|
|
|
defaultId: 1,
|
|
|
|
message: 'LBRY is not responding. Would you like to quit?',
|
|
|
|
cancelId: 0,
|
|
|
|
},
|
|
|
|
buttonIndex => {
|
|
|
|
if (buttonIndex === 1) app.quit();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2019-11-05 19:54:58 +01:00
|
|
|
|
2018-01-18 03:13:08 +01:00
|
|
|
window.once('ready-to-show', () => {
|
2019-11-18 19:30:15 +01:00
|
|
|
startMinimized ? window.hide() : window.show();
|
2018-01-18 03:13:08 +01:00
|
|
|
});
|
|
|
|
|
2019-11-18 20:42:29 +01:00
|
|
|
// A backup incase https://github.com/electron/electron/issues/7779 happens
|
2019-11-18 19:30:15 +01:00
|
|
|
window.webContents.once('dom-ready', () => {
|
2019-12-20 17:26:55 +01:00
|
|
|
startMinimized && window.hide();
|
|
|
|
});
|
2019-11-18 19:30:15 +01:00
|
|
|
|
2018-01-18 03:13:08 +01:00
|
|
|
window.webContents.on('did-finish-load', () => {
|
|
|
|
window.webContents.session.setUserAgent(`LBRY/${app.getVersion()}`);
|
2019-11-05 19:54:58 +01:00
|
|
|
|
|
|
|
// restore the user's previous language - we have to do this from here because only electron process can access app.getLocale()
|
|
|
|
window.webContents.executeJavaScript("localStorage.getItem('language')").then(storedLanguage => {
|
2021-04-06 21:14:45 +02:00
|
|
|
const language =
|
|
|
|
storedLanguage && storedLanguage !== 'undefined' && storedLanguage !== 'null'
|
|
|
|
? storedLanguage
|
|
|
|
: GetAppLangCode();
|
2019-11-05 19:54:58 +01:00
|
|
|
if (language !== 'en' && SUPPORTED_LANGUAGES[language]) {
|
|
|
|
window.webContents.send('language-set', language);
|
|
|
|
}
|
|
|
|
});
|
2018-01-18 03:13:08 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
window.webContents.on('crashed', () => {
|
|
|
|
window = null;
|
|
|
|
});
|
2018-10-22 03:01:06 +02:00
|
|
|
|
2022-01-02 21:33:11 +01:00
|
|
|
window.webContents.setWindowOpenHandler((details) => {
|
2022-02-16 23:28:21 +01:00
|
|
|
// Only open http and https links to prevent
|
|
|
|
// security issues.
|
|
|
|
if (['https:', 'http:'].includes(new URL(details.url).protocol)) {
|
|
|
|
shell.openExternal(details.url);
|
|
|
|
}
|
2022-01-02 21:33:11 +01:00
|
|
|
return { action: 'deny' };
|
2018-08-01 22:44:01 +02:00
|
|
|
});
|
2018-01-18 03:13:08 +01:00
|
|
|
|
2020-05-28 11:47:18 +02:00
|
|
|
window.webContents.on('update-target-url', (event, url) => {
|
|
|
|
// Change internal links to the lbry protocol. External (https) links should remain unchanged.
|
2020-06-09 06:10:20 +02:00
|
|
|
let hoverUrlBase = `http://localhost:${WEBPACK_ELECTRON_PORT}/`;
|
|
|
|
if (!isDev) {
|
|
|
|
// Return format of 'update-target-url':
|
|
|
|
// Linux: file:///@claim
|
|
|
|
// Windows: file:///C:/@claim
|
|
|
|
// Use '__dirname' in case installation is not in C:
|
|
|
|
const path = require('path');
|
|
|
|
const exeRoot = path.parse(__dirname).root;
|
|
|
|
|
|
|
|
if (process.platform === 'win32') {
|
|
|
|
// Add extra "/" prefix. Convert "C:\" to "C:/"
|
|
|
|
hoverUrlBase = `file:///` + exeRoot.replace(/\\/g, '/');
|
|
|
|
} else {
|
|
|
|
hoverUrlBase = `file://` + exeRoot;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let dispUrl = url.replace(hoverUrlBase, lbryProto);
|
2020-05-28 11:47:18 +02:00
|
|
|
// Non-claims don't need the lbry protocol:
|
2020-06-10 19:03:15 +02:00
|
|
|
if (dispUrl === lbryProto) {
|
2020-05-28 11:47:18 +02:00
|
|
|
dispUrl = 'Home';
|
|
|
|
} else if (dispUrl.startsWith(lbryProto + '$/')) {
|
|
|
|
dispUrl = dispUrl.replace(lbryProto, '/');
|
|
|
|
}
|
|
|
|
window.webContents.send('update-target-url', dispUrl);
|
|
|
|
});
|
|
|
|
|
2018-01-18 03:13:08 +01:00
|
|
|
return window;
|
|
|
|
};
|