Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions docs/DEBUGGING-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,6 @@ log("error", "download failed", {
**During Development:**

- Press **F12** or **Ctrl+Shift+I** in the running Vortex window
- Or add to your code: `require('@electron/remote').getCurrentWindow().webContents.openDevTools()`

**From Command Line:**

Expand Down Expand Up @@ -287,9 +286,6 @@ Vortex uses Electron, which provides Chrome DevTools for debugging.
// In main process
import { BrowserWindow } from "electron";
BrowserWindow.getFocusedWindow()?.webContents.openDevTools();

// In renderer process
require("@electron/remote").getCurrentWindow().webContents.openDevTools();
```

### Network Tab
Expand Down
107 changes: 55 additions & 52 deletions extensions/gamebryo-plugin-management/src/util/UserlistPersistor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,12 @@ import { ILOOTList, ILOOTPlugin } from "../types/ILOOTList";

import { gameSupported } from "./gameSupport";

import * as RemoteT from "@electron/remote";
import Promise from "bluebird";
import { dialog as dialogIn } from "electron";
import { dump, load } from "js-yaml";
import * as _ from "lodash";
import * as path from "path";
import { fs, types, util } from "vortex-api";

const remote = util.lazyRequire<typeof RemoteT>(() =>
require("@electron/remote"),
);
import Promise from 'bluebird';
import { dialog as dialogIn } from 'electron';
import { dump, load } from 'js-yaml';
import * as _ from 'lodash';
import * as path from 'path';
import { fs, types, util } from 'vortex-api';

/**
* persistor syncing to and from the loot userlist.yaml file
Expand Down Expand Up @@ -179,32 +174,41 @@ class UserlistPersistor implements types.IPersistor {
});
}

private handleInvalidList() {
const dialog = process.type === "renderer" ? remote.dialog : dialogIn;
private async handleInvalidList() {
const showMessageBox = async (options: Electron.MessageBoxOptions) => {
if (process.type === 'renderer') {
const result = await (window as any).api.dialog.showMessageBox(options);
return result.response;
} else {
const result = await dialogIn.showMessageBox(null, options);
return result.response;
}
};

let res = 0;
if (this.mMode === "masterlist") {
res = dialog.showMessageBoxSync(null, {
title: "Masterlist invalid",
message:
`The masterlist "${this.mUserlistPath}" can\'t be read. ` +
"\n\n" +
"If you continue now, the masterlist will be reset.",

buttons: ["Reset Masterlist", "Quit Vortex"],
if (this.mMode === 'masterlist') {
res = await showMessageBox({
title: 'Masterlist invalid',
message: `The masterlist "${this.mUserlistPath}" can\'t be read. `
+ '\n\n'
+ 'If you continue now, the masterlist will be reset.',

buttons: [
'Reset Masterlist',
'Quit Vortex'
],
});
} else {
res = dialog.showMessageBoxSync(null, {
title: "Userlist invalid",
message:
`The LOOT userlist "${this.mUserlistPath}" can\'t be read. ` +
"\n\n" +
"You should quit Vortex now and repair the file.\n" +
"If (and only if!) you're certain you didn't modify the file yourself, " +
"please send in a bug report with that file attached." +
"\n\n" +
"If you continue now, the userlist will be reset and all your plugin " +
"rules and group assignments will be lost.",
res = await showMessageBox({
title: 'Userlist invalid',
message: `The LOOT userlist "${this.mUserlistPath}" can\'t be read. `
+ '\n\n'
+ 'You should quit Vortex now and repair the file.\n'
+ 'If (and only if!) you\'re certain you didn\'t modify the file yourself, '
+ 'please send in a bug report with that file attached.'
+ '\n\n'
+ 'If you continue now, the userlist will be reset and all your plugin '
+ 'rules and group assignments will be lost.',
noLink: true,
defaultId: 1,
buttons: ["Reset Userlist", "Quit Vortex"],
Expand Down Expand Up @@ -250,26 +254,25 @@ class UserlistPersistor implements types.IPersistor {

let empty: boolean = false;

return fs
.readFileAsync(this.mUserlistPath)
.then((data: Buffer) => {
if (data.byteLength <= 5) {
// the smallest non-empty file is actually around 20 bytes long and
// the smallest useful file probably 30. This is really to catch
// cases where the file is not parseable because it's completely empty
// or contains only "null" or something silly like that
empty = true;
}
return fs.readFileAsync(this.mUserlistPath)
.then(async (data: Buffer) => {
if (data.byteLength <= 5) {
// the smallest non-empty file is actually around 20 bytes long and
// the smallest useful file probably 30. This is really to catch
// cases where the file is not parseable because it's completely empty
// or contains only "null" or something silly like that
empty = true;
}

let newList: Partial<ILOOTList> = {};
try {
newList = load(data.toString(), { json: true }) as any;
} catch (err) {
this.handleInvalidList();
}
if (typeof newList !== "object") {
this.handleInvalidList();
}
let newList: Partial<ILOOTList> = {};
try {
newList = load(data.toString(), { json: true }) as any;
} catch (err) {
await this.handleInvalidList();
}
if (typeof (newList) !== 'object') {
await this.handleInvalidList();
}

["globals", "plugins", "groups"].forEach((key) => {
if ([null, undefined].indexOf(newList[key]) !== -1) {
Expand Down
36 changes: 13 additions & 23 deletions extensions/theme-switcher/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,17 @@ interface IFont {
family: string;
}

const getAvailableFontImpl = () => {
// Get available system fonts - runs directly in renderer process
export function getAvailableFonts(): Promise<string[]> {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const fontScanner = require("font-scanner");
return fontScanner
.getAvailableFonts()
.then((fonts: IFont[]) =>
Array.from(
new Set<string>([
"Inter",
"Roboto",
"Montserrat",
"BebasNeue",
...(fonts || []).map((font) => font.family).sort(),
]),
),
);
};

const getAvailableFonts: () => Promise<string[]> = util.makeRemoteCall(
"get-available-fonts",
getAvailableFontImpl,
);

export { getAvailableFonts };
const fontScanner = require('font-scanner');
return fontScanner.getAvailableFonts()
.then((fonts: IFont[]) => Array.from(new Set<string>(
[
'Inter',
'Roboto',
'Montserrat',
'BebasNeue',
...(fonts || []).map(font => font.family).sort(),
])));
}
11 changes: 3 additions & 8 deletions playwright/src/nexusmods-auth-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,10 @@ export async function blockExternalBrowserLaunch(
/**
* Extracts the OAuth URL from Vortex's Redux store
*/
export async function extractOAuthUrl(
mainWindow: Page,
): Promise<OAuthData | { error: string }> {
return await mainWindow.evaluate(() => {
export async function extractOAuthUrl(mainWindow: Page): Promise<OAuthData | { error: string }> {
return await mainWindow.evaluate(async () => {
try {
const remote = (window as any).require("@electron/remote");
const getReduxState = remote.getGlobal("getReduxState");
const stateJson = getReduxState();
const state = JSON.parse(stateJson);
const state = await (window as any).api.redux.getState() as any;
const oauthUrl = state?.session?.nexus?.oauthPending;

if (oauthUrl) {
Expand Down
17 changes: 7 additions & 10 deletions playwright/tests/manage-fake-stardew-valley.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,9 @@ test("manage fake Stardew Valley", async ({
await mainWindow.waitForTimeout(3000);

// Verify game was discovered
console.log("7. Verifying...");
const isDiscovered = await mainWindow.evaluate(() => {
const remote = (window as any).require("@electron/remote");
const state = JSON.parse(remote.getGlobal("getReduxState")());
console.log('7. Verifying...');
const isDiscovered = await mainWindow.evaluate(async () => {
const state = await (window as any).api.redux.getState() as any;
return !!state?.settings?.gameMode?.discovered?.stardewvalley;
});

Expand All @@ -168,9 +167,8 @@ test("manage fake Stardew Valley", async ({
console.log(` Download Popup URL: ${modUrl}`);

// Check Vortex download state before download
const downloadsBefore = await mainWindow.evaluate(() => {
const remote = (window as any).require("@electron/remote");
const state = JSON.parse(remote.getGlobal("getReduxState")());
const downloadsBefore = await mainWindow.evaluate(async () => {
const state = await (window as any).api.redux.getState() as any;
return {
downloadCount: Object.keys(state?.persistent?.downloads?.files || {})
.length,
Expand Down Expand Up @@ -199,9 +197,8 @@ test("manage fake Stardew Valley", async ({
await mainWindow.waitForTimeout(2000);

// Check Vortex download state after download
const downloadsAfter = await mainWindow.evaluate(() => {
const remote = (window as any).require("@electron/remote");
const state = JSON.parse(remote.getGlobal("getReduxState")());
const downloadsAfter = await mainWindow.evaluate(async () => {
const state = await (window as any).api.redux.getState() as any;
const downloads = state?.persistent?.downloads?.files || {};
return {
downloadCount: Object.keys(downloads).length,
Expand Down
27 changes: 11 additions & 16 deletions src/extensions/dashboard/views/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
translate,
} from "../../../renderer/controls/ComponentEx";
import Debouncer from "../../../util/Debouncer";
import lazyRequire from "../../../util/lazyRequire";
import { getSafe } from "../../../util/storeHelper";
import MainPage from "../../../renderer/views/MainPage";

Expand All @@ -26,15 +25,12 @@ import PackeryGrid from "./PackeryGrid";
import type { IPackeryItemProps } from "./PackeryItem";
import PackeryItem from "./PackeryItem";

import type * as remoteT from "@electron/remote";
import * as _ from "lodash";
import * as React from "react";
import { Button, MenuItem } from "react-bootstrap";
import type * as Redux from "redux";
import type { ThunkDispatch } from "redux-thunk";

const remote: typeof remoteT = lazyRequire(() => require("@electron/remote"));

const UPDATE_FREQUENCY_MS = 1000;

interface IBaseProps {
Expand Down Expand Up @@ -78,6 +74,8 @@ class Dashboard extends ComponentEx<IProps, IComponentState> {
private mUpdateTimer: NodeJS.Timeout;
private mLayoutDebouncer: Debouncer;
private mWindowFocused: boolean = true;
private mUnsubscribeFocus: (() => void) | undefined;
private mUnsubscribeBlur: (() => void) | undefined;

constructor(props: IProps) {
super(props);
Expand All @@ -93,27 +91,24 @@ class Dashboard extends ComponentEx<IProps, IComponentState> {
}
return null;
}, 500);
// assuming this doesn't change?
const window = remote.getCurrentWindow();
this.mWindowFocused = window.isFocused();
}

public componentDidMount() {
this.startUpdateCycle();
const win = remote.getCurrentWindow();
win.on("focus", this.onFocus);
win.on("blur", this.onBlur);
window.addEventListener("beforeunload", () => {
win.removeListener("focus", this.onFocus);
win.removeListener("blur", this.onBlur);
// Check initial focus state
window.api.window.isFocused(window.windowId).then((focused) => {
this.mWindowFocused = focused;
});
// Subscribe to focus/blur events via preload API
this.mUnsubscribeFocus = window.api.window.onFocus(this.onFocus);
this.mUnsubscribeBlur = window.api.window.onBlur(this.onBlur);
}

public componentWillUnmount() {
clearTimeout(this.mUpdateTimer);
const win = remote.getCurrentWindow();
win.removeListener("focus", this.onFocus);
win.removeListener("blur", this.onBlur);
// Unsubscribe from focus/blur events
this.mUnsubscribeFocus?.();
this.mUnsubscribeBlur?.();
}

public UNSAFE_componentWillReceiveProps(nextProps: IProps) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { showError } from "../../../util/message";
import type { ILog, ISession } from "../types/ISession";
import { loadVortexLogs } from "../util/loadVortexLogs";

import type * as RemoteT from "@electron/remote";
import PromiseBB from "bluebird";
import update from "immutability-helper";
import * as os from "os";
Expand All @@ -31,11 +30,8 @@ import {
} from "react-bootstrap";
import type * as Redux from "redux";
import type { ThunkDispatch } from "redux-thunk";
import lazyRequire from "../../../util/lazyRequire";
import { util } from "../../..";

const remote = lazyRequire<typeof RemoteT>(() => require("@electron/remote"));

export interface IBaseProps {
visible: boolean;
onHide: () => void;
Expand Down Expand Up @@ -313,7 +309,7 @@ class DiagnosticsFilesDialog extends ComponentEx<IProps, IComponentState> {
.filter((line) => enabledLevels.has(line.type))
.map((line) => `${line.time} - ${line.type}: ${line.text}`)
.join(os.EOL);
remote.clipboard.writeText(filteredLog);
window.api.clipboard.writeText(filteredLog);
};

private openLogFolder = () => {
Expand Down
Loading