Skip to content

Commit

Permalink
Merge pull request #2 from andrewbrey/v2
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewbrey authored Sep 3, 2022
2 parents 78e7247 + 2d013e4 commit d0f7004
Show file tree
Hide file tree
Showing 28 changed files with 2,435 additions and 3,239 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/app-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:

defaults:
run:
shell: 'bash'
shell: "bash"

jobs:
build:
Expand All @@ -15,11 +15,11 @@ jobs:
matrix:
include:
- platform: linux
os: 'ubuntu-latest'
os: "ubuntu-latest"
- platform: windows
os: 'windows-latest'
os: "windows-latest"
- platform: mac
os: 'macos-latest'
os: "macos-latest"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
Expand Down
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"name": "Nextron: Main",
"type": "node",
"request": "attach",
"protocol": "inspector",
// "protocol": "inspector",
"port": 9292,
"skipFiles": ["<node_internals>/**"],
"sourceMapPathOverrides": {
Expand All @@ -19,7 +19,7 @@
},
{
"name": "Nextron: Renderer",
"type": "pwa-chrome",
"type": "chrome",
"request": "attach",
"port": 5858,
"timeout": 10000,
Expand Down
120 changes: 73 additions & 47 deletions main/background.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,59 @@
import { app, BrowserWindow, globalShortcut, webFrameMain } from 'electron';
import { ipcMain as ipc } from 'electron-better-ipc';
import serve from 'electron-serve';
import { readFile } from 'fs/promises';
import fetch from 'node-fetch';
import { join } from 'path';
import { createWindow } from './helpers';
import { omitSecurityHeadersAndBlockAds } from './helpers/web-requests';

const isProd: boolean = process.env.NODE_ENV === 'production';
const isLinux = process.platform === 'linux';
import { app, BrowserWindow, globalShortcut, webFrameMain } from "electron";
import { ipcMain as ipc } from "electron-better-ipc";
import serve from "electron-serve";
import { readFile } from "fs/promises";
import fetch from "cross-fetch";
import { join } from "path";
import { createWindow } from "./helpers";
import { omitSecurityHeadersAndBlockAds } from "./helpers/web-requests";

const isProd: boolean = process.env.NODE_ENV === "production";
const isLinux = process.platform === "linux";

const port = process.argv[2];
const devURL = `http://localhost:${port}`;

let mainWindow: BrowserWindow | undefined;
let experimentalVideoCSS = false;
let forceDetachKeybindActive = false;
const videoCSSOnScript = 'document.documentElement.classList.add("flot-video");';
const videoCSSOffScript = 'document.documentElement.classList.remove("flot-video");';
const videoCSSOnScript =
'document.documentElement.classList.add("flot-video");';
const videoCSSOffScript =
'document.documentElement.classList.remove("flot-video");';

if (isLinux) {
// https://github.com/electron/electron/issues/25153#issuecomment-843688494
app.commandLine.appendSwitch('use-gl', 'desktop');
app.commandLine.appendSwitch("use-gl", "desktop");
}

if (isProd) {
serve({ directory: 'app' });
serve({ directory: "app" });
} else {
app.setPath('userData', `${app.getPath('userData')} (development)`);
app.setPath("userData", `${app.getPath("userData")} (development)`);
}

(async () => {
await app.whenReady();

globalShortcut.register('CmdOrCtrl+Alt+I', () => {
globalShortcut.register("CmdOrCtrl+Alt+I", () => {
mainWindow?.setIgnoreMouseEvents(!forceDetachKeybindActive);
forceDetachKeybindActive = !forceDetachKeybindActive;
});

const embedCssFilePromise = isProd
? readFile(join(__dirname, 'css', 'embed.css'), { encoding: 'utf8' })
? readFile(join(__dirname, "css", "embed.css"), { encoding: "utf8" })
: fetch(`${devURL}/css/embed.css`).then((r) => r.text());

const embedCss = embedCssFilePromise.catch((e) => {
console.error(e);
return '';
return "";
});

await new Promise((r) => setTimeout(r, isLinux ? 750 : 350)); // required otherwise transparency won't work consistently cross-platform...

mainWindow = createWindow('main', {
mainWindow = createWindow("main", {
transparent: true,
title: 'Flōt',
title: "Flōt",
titleBarStyle: undefined,
trafficLightPosition: undefined,
skipTaskbar: false,
Expand All @@ -66,7 +68,7 @@ if (isProd) {
minWidth: 300,
maxHeight: 1000,
maxWidth: 1000,
icon: join(__dirname, 'images', 'logo', '256x256.png'),
icon: join(__dirname, "images", "logo", "256x256.png"),
alwaysOnTop: true,
hasShadow: false,
webPreferences: {
Expand All @@ -79,17 +81,34 @@ if (isProd) {
mainWindow.setVisibleOnAllWorkspaces(true);

mainWindow.webContents.on(
'did-fail-provisional-load',
(event, code, desc, validatedUrl, isMainFrame, frameProcessId, frameRoutingId) => {
if (mainWindow) ipc.callRenderer(mainWindow, 'iframe-load-failure', validatedUrl);
"did-fail-provisional-load",
(
event,
code,
desc,
validatedUrl,
isMainFrame,
frameProcessId,
frameRoutingId
) => {
if (mainWindow)
ipc.callRenderer(mainWindow, "iframe-load-failure", validatedUrl);
}
);

mainWindow.webContents.on(
'did-frame-navigate',
async (event, url, status, statusText, isMainFrame, frameProcessId, frameRoutingId) => {
"did-frame-navigate",
async (
event,
url,
status,
statusText,
isMainFrame,
frameProcessId,
frameRoutingId
) => {
if (isMainFrame) return;
if (url === 'about:blank') return;
if (url === "about:blank") return;

const frame = webFrameMain.fromId(frameProcessId, frameRoutingId);

Expand Down Expand Up @@ -121,55 +140,62 @@ if (isProd) {
}
);

mainWindow.webContents.on('did-navigate-in-page', async (event, url, isMainFrame, frameProcessId, frameRoutingId) => {
if (isMainFrame) return;
if (url === 'about:blank') return;
mainWindow.webContents.on(
"did-navigate-in-page",
async (event, url, isMainFrame, frameProcessId, frameRoutingId) => {
if (isMainFrame) return;
if (url === "about:blank") return;

const frame = webFrameMain.fromId(frameProcessId, frameRoutingId);
const frame = webFrameMain.fromId(frameProcessId, frameRoutingId);

if (frame) {
frame.executeJavaScript(`parent.postMessage({key: 'location', msg: location.href}, "*")`);
if (frame) {
frame.executeJavaScript(
`parent.postMessage({key: 'location', msg: location.href}, "*")`
);
}
}
});
);

mainWindow.webContents.setWindowOpenHandler(() => ({ action: 'deny' }));
mainWindow.webContents.setWindowOpenHandler(() => ({ action: "deny" }));

if (isProd) {
await mainWindow.loadURL('app://./index.html');
await mainWindow.loadURL("app://./index.html");

app
.whenReady()
.then(() => import('electron-updater'))
.then(() => import("electron-updater"))
.then(({ autoUpdater }) => autoUpdater.checkForUpdatesAndNotify())
.catch((e) => console.error('Failed check updates:', e));
.catch((e) => console.error("Failed check updates:", e));
} else {
await mainWindow.loadURL(`${devURL}/`);
// mainWindow.webContents.openDevTools({ mode: 'detach', activate: false });
}
})();

ipc.answerRenderer('please-enable-video-css', () => {
ipc.answerRenderer("please-enable-video-css", () => {
getFlotEmbed()?.executeJavaScript(videoCSSOnScript);
experimentalVideoCSS = true;
});
ipc.answerRenderer('please-disable-video-css', () => {
ipc.answerRenderer("please-disable-video-css", () => {
getFlotEmbed()?.executeJavaScript(videoCSSOffScript);
experimentalVideoCSS = false;
});
ipc.answerRenderer('please-detach', () => mainWindow?.setIgnoreMouseEvents(true));
ipc.answerRenderer('please-attach', () => {
ipc.answerRenderer("please-detach", () =>
mainWindow?.setIgnoreMouseEvents(true)
);
ipc.answerRenderer("please-attach", () => {
if (!forceDetachKeybindActive) mainWindow?.setIgnoreMouseEvents(false);
});
ipc.answerRenderer('please-quit', () => app.quit());
ipc.answerRenderer("please-quit", () => app.quit());

app.on('window-all-closed', () => app.quit());
app.on('will-quit', () => globalShortcut.unregisterAll());
app.on("window-all-closed", () => app.quit());
app.on("will-quit", () => globalShortcut.unregisterAll());

function getFlotEmbed() {
const frames = mainWindow?.webContents.mainFrame.frames ?? [];

// Some websites seem to cause the embed frame to be renamed...not sure how, it's
// supposed to be a readonly property, but ah well, if this happens, just try the
// using the first frame
return frames.find((f) => f.name === 'flot-embed') ?? frames[0];
return frames.find((f) => f.name === "flot-embed") ?? frames[0];
}
26 changes: 19 additions & 7 deletions main/helpers/create-window.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { BrowserWindow, BrowserWindowConstructorOptions, Rectangle, screen } from 'electron';
import Store from 'electron-store';
import {
BrowserWindow,
BrowserWindowConstructorOptions,
Rectangle,
screen,
} from "electron";
import Store from "electron-store";

interface WindowState {
x: number;
Expand All @@ -8,10 +13,18 @@ interface WindowState {
height: any;
}

export default (windowName: string, options: BrowserWindowConstructorOptions): BrowserWindow => {
const key = 'window-state';
export default (
windowName: string,
options: BrowserWindowConstructorOptions
): BrowserWindow => {
const key = "window-state";
const name = `window-state-${windowName}`;
const defaultState: WindowState = { x: 0, y: 0, width: options.width ?? 600, height: options.height ?? 400 };
const defaultState: WindowState = {
x: 0,
y: 0,
width: options.width ?? 600,
height: options.height ?? 400,
};
const store = new Store<WindowState>({
name,
defaults: { ...defaultState },
Expand Down Expand Up @@ -76,14 +89,13 @@ export default (windowName: string, options: BrowserWindowConstructorOptions): B
...state,
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false,
...options.webPreferences,
},
};
win = new BrowserWindow(browserOptions);

win.on('close', saveState);
win.on("close", saveState);

return win;
};
Loading

1 comment on commit d0f7004

@vercel
Copy link

@vercel vercel bot commented on d0f7004 Sep 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.