From bdef14b02922f617de668f585725ac5b237e8b59 Mon Sep 17 00:00:00 2001 From: Martin Fournier Date: Mon, 3 Jan 2022 10:29:56 -0500 Subject: [PATCH 1/3] Add API server information menu item --- electron/gameWindow.js | 6 ++---- electron/menu.js | 26 +++++++++++++++++++++++++- electron/utils.js | 8 +++++++- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/electron/gameWindow.js b/electron/gameWindow.js index 39fdaea0e..f105340f8 100644 --- a/electron/gameWindow.js +++ b/electron/gameWindow.js @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-var-requires */ -const { app, BrowserWindow, shell } = require("electron"); +const { app, BrowserWindow } = require("electron"); const log = require("electron-log"); const utils = require("./utils"); const achievements = require("./achievements"); @@ -31,9 +31,7 @@ async function createWindow(killall) { // and open every other protocols on the browser e.preventDefault(); - shell.openExternal(url); - - global.app_playerOpenedExternalLink = true; + utils.openExternal(url); }); window.webContents.backgroundThrottling = false; diff --git a/electron/menu.js b/electron/menu.js index 9b73b984c..ac00af758 100644 --- a/electron/menu.js +++ b/electron/menu.js @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-var-requires */ -const { Menu, clipboard } = require("electron"); +const { Menu, clipboard, dialog } = require("electron"); const log = require("electron-log"); const api = require("./api-server"); const utils = require("./utils"); @@ -78,6 +78,30 @@ function getMenu(window) { clipboard.writeText(token); }) }, + { + type: 'separator', + }, + { + label: 'Information', + click: () => { + dialog.showMessageBox({ + type: 'info', + title: 'Bitburner > API Server Information', + message: 'The API Server is used to write script files to your in-game home.', + detail: 'There is an official Visual Studio Code extension that makes use of that feature.\n\n' + + 'It allows you to write your script file in an external IDE and have them pushed over to the game automatically.\n' + + 'If you want more information, head over to: https://github.com/bitburner-official/bitburner-vscode.', + buttons: ['Dismiss', 'Open Extension Link (GitHub)'], + defaultId: 0, + cancelId: 0, + noLink: true, + }).then(({response}) => { + if (response === 1) { + utils.openExternal('https://github.com/bitburner-official/bitburner-vscode'); + } + }); + } + } ] }, { diff --git a/electron/utils.js b/electron/utils.js index 8e45eba3e..ed88a01f9 100644 --- a/electron/utils.js +++ b/electron/utils.js @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-var-requires */ -const { app, dialog } = require("electron"); +const { app, dialog, shell } = require("electron"); const log = require("electron-log"); const achievements = require("./achievements"); @@ -93,7 +93,13 @@ async function exportSave(window) { .executeJavaScript(`${exportSaveFromIndexedDb.toString()}; exportSaveFromIndexedDb();`, true); } +function openExternal(url) { + shell.openExternal(url); + global.app_playerOpenedExternalLink = true; +} + module.exports = { reloadAndKill, showErrorBox, exportSave, attachUnresponsiveAppHandler, detachUnresponsiveAppHandler, + openExternal, } From 6d8df6744ef8f0a21c9d06e477b64ee96a19ac66 Mon Sep 17 00:00:00 2001 From: Martin Fournier Date: Mon, 3 Jan 2022 10:32:01 -0500 Subject: [PATCH 2/3] Add toasts & terminal funcs to electron app Attach functions to the window object so that the wrapper can executeJs to display messages to the player --- electron/menu.js | 15 +++++++++++++++ electron/utils.js | 12 +++++++++++- src/Electron.tsx | 28 ++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/electron/menu.js b/electron/menu.js index ac00af758..b497c897b 100644 --- a/electron/menu.js +++ b/electron/menu.js @@ -54,12 +54,21 @@ function getMenu(window) { { label: api.isListening() ? 'Disable Server' : 'Enable Server', click: (async () => { + let success = false; try { await api.toggleServer(); + success = true; } catch (error) { log.error(error); utils.showErrorBox('Error Toggling Server', error); } + if (success && api.isListening()) { + utils.writeToast(window, "Started API Server", "success"); + } else if (success && !api.isListening()) { + utils.writeToast(window, "Stopped API Server", "success"); + } else { + utils.writeToast(window, 'Error Toggling Server', "error"); + } refreshMenu(window); }) }, @@ -67,6 +76,11 @@ function getMenu(window) { label: api.isAutostart() ? 'Disable Autostart' : 'Enable Autostart', click: (async () => { api.toggleAutostart(); + if (api.isAutostart()) { + utils.writeToast(window, "Enabled API Server Autostart", "success"); + } else { + utils.writeToast(window, "Disabled API Server Autostart", "success"); + } refreshMenu(window); }) }, @@ -76,6 +90,7 @@ function getMenu(window) { const token = api.getAuthenticationToken(); log.log('Wrote authentication token to clipboard'); clipboard.writeText(token); + utils.writeToast(window, "Copied Authentication Token to Clipboard", "info"); }) }, { diff --git a/electron/utils.js b/electron/utils.js index ed88a01f9..03175b57b 100644 --- a/electron/utils.js +++ b/electron/utils.js @@ -93,6 +93,16 @@ async function exportSave(window) { .executeJavaScript(`${exportSaveFromIndexedDb.toString()}; exportSaveFromIndexedDb();`, true); } +async function writeTerminal(window, message, type = null) { + await window.webContents + .executeJavaScript(`window.appNotifier.terminal("${message}", "${type}");`, true) +} + +async function writeToast(window, message, type = "info", duration = 2000) { + await window.webContents + .executeJavaScript(`window.appNotifier.toast("${message}", "${type}", ${duration});`, true) +} + function openExternal(url) { shell.openExternal(url); global.app_playerOpenedExternalLink = true; @@ -101,5 +111,5 @@ function openExternal(url) { module.exports = { reloadAndKill, showErrorBox, exportSave, attachUnresponsiveAppHandler, detachUnresponsiveAppHandler, - openExternal, + openExternal, writeTerminal, writeToast, } diff --git a/src/Electron.tsx b/src/Electron.tsx index ba2e9866a..9931d3a5e 100644 --- a/src/Electron.tsx +++ b/src/Electron.tsx @@ -22,6 +22,9 @@ import { Server } from "./Server/Server"; import { Router } from "./ui/GameRoot"; import { Page } from "./ui/Router"; import { removeLeadingSlash } from "./Terminal/DirectoryHelpers"; +import { Terminal } from './Terminal'; +import { SnackbarEvents } from "./ui/React/Snackbar"; +import { IMap } from "./types"; interface Achievement { ID: string; @@ -417,6 +420,7 @@ export function initElectron(): void { setAchievements([]); initWebserver(); setInterval(calculateAchievements, 5000); + initAppNotifier(); } function initWebserver(): void { @@ -451,3 +455,27 @@ function initWebserver(): void { return "not a script file"; }; } + +// Expose certain alert functions to allow the wrapper to sends message to the game +function initAppNotifier(): void { + const funcs = { + terminal: (message: string, type?: string) => { + const typesFn: IMap<(s: string) => void> = { + info: Terminal.info, + warn: Terminal.warn, + error: Terminal.error, + success: Terminal.success + }; + let fn; + if (type) fn = typesFn[type]; + if (!fn) fn = Terminal.print; + fn.bind(Terminal)(message); + }, + toast: (message: string, type: "info" | "success" | "warning" | "error" , duration = 2000) => + SnackbarEvents.emit(message, type, duration), + } + + // Will be consumud by the electron wrapper. + // @ts-ignore + window.appNotifier = funcs; +} From 6c3618cb6506c652a6ca42927127f22e5d189772 Mon Sep 17 00:00:00 2001 From: Martin Fournier Date: Mon, 3 Jan 2022 10:33:58 -0500 Subject: [PATCH 3/3] Check userAgent before running electron init --- src/Electron.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Electron.tsx b/src/Electron.tsx index 9931d3a5e..0b71fa94f 100644 --- a/src/Electron.tsx +++ b/src/Electron.tsx @@ -417,10 +417,14 @@ function calculateAchievements(): void { } export function initElectron(): void { - setAchievements([]); - initWebserver(); - setInterval(calculateAchievements, 5000); - initAppNotifier(); + const userAgent = navigator.userAgent.toLowerCase(); + if (userAgent.indexOf(' electron/') > -1) { + // Electron-specific code + setAchievements([]); + initWebserver(); + setInterval(calculateAchievements, 5000); + initAppNotifier(); + } } function initWebserver(): void {