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..b497c897b 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"); @@ -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,8 +90,33 @@ 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"); }) }, + { + 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..03175b57b 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,23 @@ 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; +} + module.exports = { reloadAndKill, showErrorBox, exportSave, attachUnresponsiveAppHandler, detachUnresponsiveAppHandler, + openExternal, writeTerminal, writeToast, } diff --git a/src/Electron.tsx b/src/Electron.tsx index ba2e9866a..0b71fa94f 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; @@ -414,9 +417,14 @@ function calculateAchievements(): void { } export function initElectron(): void { - setAchievements([]); - initWebserver(); - setInterval(calculateAchievements, 5000); + const userAgent = navigator.userAgent.toLowerCase(); + if (userAgent.indexOf(' electron/') > -1) { + // Electron-specific code + setAchievements([]); + initWebserver(); + setInterval(calculateAchievements, 5000); + initAppNotifier(); + } } function initWebserver(): void { @@ -451,3 +459,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; +}