Skip to content
This repository was archived by the owner on Mar 5, 2021. It is now read-only.
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
17 changes: 15 additions & 2 deletions scripts/package.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use strict";

const yargs = require("yargs");
const fs = require("fs");
const execSync = require("child_process").execSync;
const path = require("path");
Expand All @@ -9,6 +10,17 @@ const publicPackage = JSON.parse(fs.readFileSync(`${__dirname}/../public/package
publicPackage.version = rootPackage.version;
publicPackage.dependencies = rootPackage.dependencies;

const argv = yargs.argv;
let platform = argv._[0];
let arch = argv._[1];

if (arch == null) {
arch = "all";
}
if (platform == null) {
platform = "all";
}

fs.writeFileSync(`${__dirname}/../public/package.json`, JSON.stringify(publicPackage, null, 2) + "\n");

execSync("npm install --production", { cwd: `${__dirname}/../public`, stdio: "inherit" });
Expand All @@ -19,15 +31,16 @@ execSync("npm install --production", { cwd: `${__dirname}/../public`, stdio: "in
// See https://github.com/electron-userland/electron-packager/issues/413
execSync("npm install rcedit@0.5.0 electron-packager@7.1.0", { stdio: "inherit" });

console.log("Running electron-packager...");
console.log(`Running electron-packager for platform '${platform}' and arch '${arch}'...`);

const packager = require("electron-packager");
const year = new Date().getFullYear();

packager({
dir: "public",
name: "Superpowers",
all: true,
platform: platform,
arch: arch,
version: publicPackage.superpowers.electron,
out: "packages",
icon: "icons/superpowers",
Expand Down
43 changes: 30 additions & 13 deletions src/getPaths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,45 @@ import { LocalizedError } from "./shared/i18n";
const argv = yargs
.usage("Usage: $0 [options]")
.describe("core-path", "Path to Superpowers core")
.describe("ro-data-path", "Path to Superpowers readonly data (used only when core-path is passed too, use '<default>' to get the default electron app appData directory. Falls back to core-path.")
.describe("rw-data-path", "Path to Superpowers writable data (used only when core-path is passed too, use '<default>' to get the default electron app appData directory. Falls back to core-path.")
.argv;

export default function getPaths(callback: (err: LocalizedError, corePath?: string, dataPath?: string) => void) {
let dataPath: string;
export default function getPaths(callback: (err: LocalizedError, corePath?: string, roDataPath?: string, rwDataPath?: string) => void) {
let roDataPath: string;
let rwDataPath: string;

let corePath = argv["core-path"] != null ? path.resolve(argv["core-path"]) : null;
if (corePath != null) {
dataPath = corePath;
process.nextTick(() => { callback(null, corePath, dataPath); });
roDataPath = argv["ro-data-path"] != null ? argv["ro-data-path"] : corePath;
if (roDataPath === "<default>") {
roDataPath = path.join(electron.app.getPath("appData"), "Superpowers");
} else {
roDataPath = path.resolve(roDataPath);
}

rwDataPath = argv["rw-data-path"] != null ? argv["rw-data-path"] : corePath;
if (rwDataPath === "<default>") {
rwDataPath = path.join(electron.app.getPath("appData"), "Superpowers");
} else {
rwDataPath = path.resolve(rwDataPath);
}

process.nextTick(() => { callback(null, corePath, roDataPath, rwDataPath); });
return;
}

try {
dataPath = path.join(electron.app.getPath("appData"), "Superpowers");
roDataPath = rwDataPath = path.join(electron.app.getPath("appData"), "Superpowers");
} catch (err) {
process.nextTick(() => { callback(new LocalizedError("startup:errors.couldNotGetDataPath", { details: err.message })); });
return;
}

console.log(dataPath);
console.log(roDataPath);
console.log(rwDataPath);

if (!fs.existsSync(dataPath)) {
if (!fs.existsSync(rwDataPath)) {
// This is the old custom logic we used to determine the appData folder
// so if the new data folder doesn't exist, we'll try to migrate from the old one
let oldDataPath: string;
Expand All @@ -46,19 +63,19 @@ export default function getPaths(callback: (err: LocalizedError, corePath?: stri
}

if (oldDataPath != null && fs.existsSync(oldDataPath)) {
console.log(`Migrating data from ${oldDataPath} to ${dataPath}...`);
fs.renameSync(oldDataPath, dataPath);
console.log(`Migrating data from ${oldDataPath} to ${rwDataPath}...`);
fs.renameSync(oldDataPath, rwDataPath);
}
}

corePath = path.join(dataPath, "core");
corePath = path.join(roDataPath, "core");

fs.mkdir(dataPath, (err) => {
fs.mkdir(rwDataPath, (err) => {
if (err != null && err.code !== "EEXIST") {
callback(new LocalizedError("startup:errors.couldNotCreateUserDataFolder", { dataPath, reason: err.message }));
callback(new LocalizedError("startup:errors.couldNotCreateUserDataFolder", { rwDataPath, reason: err.message }));
return;
}

callback(null, corePath, dataPath);
callback(null, corePath, roDataPath, rwDataPath);
});
}
16 changes: 9 additions & 7 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import getLanguageCode from "./getLanguageCode";
import * as SupAppIPC from "./ipc";

let corePath: string;
let userDataPath: string;
let roUserDataPath: string;
let rwUserDataPath: string;

let mainWindow: Electron.BrowserWindow;
let trayIcon: Electron.Tray;
Expand Down Expand Up @@ -48,7 +49,7 @@ function startCleanExit() {
electron.ipcMain.on("ready-to-quit", (event) => {
if (event.sender !== mainWindow.webContents) return;

SupAppIPC.saveAuthorizations(userDataPath);
SupAppIPC.saveAuthorizations(rwUserDataPath);

console.log("Exited cleanly.");
isReadyToQuit = true;
Expand All @@ -60,13 +61,14 @@ electron.ipcMain.on("show-main-window", () => { restoreMainWindow(); });
function onAppReady() {
menu.setup(electron.app);

getPaths((dataPathErr, pathToCore, pathToUserData) => {
userDataPath = pathToUserData;
getPaths((dataPathErr, pathToCore, pathToRoUserData, pathToRwUserData) => {
roUserDataPath = pathToRoUserData;
rwUserDataPath = pathToRwUserData;
corePath = pathToCore;

SupAppIPC.loadAuthorizations(userDataPath);
SupAppIPC.loadAuthorizations(rwUserDataPath);

getLanguageCode(userDataPath, (languageCode) => {
getLanguageCode(rwUserDataPath, (languageCode) => {
i18n.setLanguageCode(languageCode);
i18n.load([ "startup", "tray" ], () => {
if (dataPathErr != null) {
Expand Down Expand Up @@ -135,7 +137,7 @@ function setupMainWindow() {
mainWindow.loadURL(`file://${__dirname}/renderer/${i18n.getLocalizedFilename("index.html")}`);

mainWindow.webContents.on("did-finish-load", () => {
mainWindow.webContents.send("init", corePath, userDataPath, i18n.languageCode);
mainWindow.webContents.send("init", corePath, roUserDataPath, rwUserDataPath, i18n.languageCode);
mainWindow.show();
});

Expand Down
11 changes: 11 additions & 0 deletions src/renderer/flatpak.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as path from "path";
import * as fs from "fs";

export function underFlatpak() {
if (process.env.XDG_RUNTIME_DIR == null) {
return false;
}

const flatpakInfo = path.join(process.env.XDG_RUNTIME_DIR, "flatpak-info");
return fs.existsSync(flatpakInfo) && fs.statSync(flatpakInfo).isFile();
}
4 changes: 2 additions & 2 deletions src/renderer/forkServerProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ export default function forkSererProcess(extraArgs: string[] = []) {
// for (const key in nodeProcess.env) serverEnv[key] = nodeProcess.env[key];

// So instead, we'll just copy the environment variables we definitely need
for (const varName of [ "NODE_ENV", "APPDATA", "HOME", "XDG_DATA_HOME" ]) {
for (const varName of [ "NODE_ENV", "APPDATA", "HOME", "XDG_DATA_HOME", "XDG_CONFIG_HOME", "XDG_CACHE_HOME", "LD_LIBRARY_PATH", "GST_PLUGIN_SYSTEM_PATH", "XDG_CONFIG_DIRS", "PATH", "GI_TYPELIB_PATH" ]) {
if (process.env[varName] != null) serverEnv[varName] = process.env[varName];
}

const serverProcess = fork(
serverPath,
[ `--data-path=${settings.userDataPath}` ].concat(extraArgs),
[ `--data-path=${settings.roUserDataPath}`, `--rw-data-path=${settings.rwUserDataPath}` ].concat(extraArgs),
{ silent: true, env: serverEnv }
);
return serverProcess;
Expand Down
22 changes: 16 additions & 6 deletions src/renderer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import openServerSettings from "./tabs/openServerSettings";
import * as localServer from "./localServer";
import * as chat from "./chat";
import WelcomeDialog from "./WelcomeDialog";
import * as flatpak from "./flatpak";

electron.ipcRenderer.on("init", onInitialize);
electron.ipcRenderer.on("quit", onQuit);
Expand All @@ -26,8 +27,8 @@ const namespaces = [
"welcome", "home"
];

function onInitialize(sender: any, corePath: string, userDataPath: string, languageCode: string) {
settings.setPaths(corePath, userDataPath);
function onInitialize(sender: any, corePath: string, roUserDataPath: string, rwUserDataPath: string, languageCode: string) {
settings.setPaths(corePath, roUserDataPath, rwUserDataPath);
i18n.setLanguageCode(languageCode);
i18n.load(namespaces, () => { settings.load(onSettingsLoaded); });
}
Expand All @@ -42,7 +43,7 @@ function onQuit() {
function onSettingsLoaded(err: Error) {
if (err != null) {
const label = i18n.t("startup:errors.couldNotLoadSettings", {
settingsPath: `${settings.userDataPath}/settings.json`,
settingsPath: `${settings.rwUserDataPath}/settings.json`,
reason: err.message
});
const options = {
Expand Down Expand Up @@ -71,7 +72,10 @@ function start() {

splashScreen.fadeOut(() => {
if (settings.nickname == null) {
async.series([ showWelcomeDialog, installFirstSystem ]);
let actions = [ showWelcomeDialog, installFirstSystem ];
if (flatpak.underFlatpak())
actions = [ showWelcomeDialog, startLocalServer ];
async.series(actions);
} else {
me.start();
chat.start();
Expand Down Expand Up @@ -105,6 +109,11 @@ function showWelcomeDialog(callback: Function) {
});
}

function startLocalServer(callback: Function) {
localServer.start();
callback();
}

function installFirstSystem(callback: Function) {
const label = i18n.t("welcome:askGameInstall.prompt");
const options = {
Expand All @@ -115,8 +124,7 @@ function installFirstSystem(callback: Function) {

new dialogs.ConfirmDialog(label, options, (installGame) => {
if (!installGame) {
localServer.start();
callback();
startLocalServer(callback);
return;
}

Expand Down Expand Up @@ -160,6 +168,8 @@ function installFirstSystem(callback: Function) {
}

function updateSystemsAndPlugins() {
if (flatpak.underFlatpak()) { localServer.start(); return; }

serverSettingsSystems.getRegistry((registry) => {
if (registry == null) { localServer.start(); return; }

Expand Down
6 changes: 3 additions & 3 deletions src/renderer/serverSettings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ function getServerConfig() {

let localConfig: ServerConfig;
try {
localConfig = JSON.parse(fs.readFileSync(`${settings.userDataPath}/config.json`, { encoding: "utf8" }));
localConfig = JSON.parse(fs.readFileSync(`${settings.rwUserDataPath}/config.json`, { encoding: "utf8" }));
} catch (err) { /* Ignore */ }
if (localConfig == null) localConfig = {} as any;

Expand All @@ -93,7 +93,7 @@ function getServerConfig() {
}

function onOpenProjectsFolderClick() {
electron.shell.openExternal(`${settings.userDataPath}/projects/`);
electron.shell.openExternal(`${settings.rwUserDataPath}/projects/`);
}

function onChangeAutoStartServer() {
Expand Down Expand Up @@ -149,7 +149,7 @@ export function applyScheduledSave() {
maxRecentBuilds: parseInt(maxRecentBuildsElt.value, 10)
};

fs.writeFileSync(`${settings.userDataPath}/config.json`, JSON.stringify(config, null, 2) + "\n", { encoding: "utf8" });
fs.writeFileSync(`${settings.rwUserDataPath}/config.json`, JSON.stringify(config, null, 2) + "\n", { encoding: "utf8" });

clearTimeout(scheduleSaveTimeoutId);
scheduleSaveTimeoutId = null;
Expand Down
12 changes: 7 additions & 5 deletions src/renderer/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import * as fs from "fs";
import * as i18n from "../shared/i18n";

export let corePath: string;
export let userDataPath: string;
export let roUserDataPath: string;
export let rwUserDataPath: string;

export let favoriteServers: ServerEntry[];
export let favoriteServersById: { [id: string]: ServerEntry };
Expand All @@ -14,9 +15,10 @@ export let nickname: string;
export let presence: "online"|"away"|"offline";
export let savedChatrooms: string[];

export function setPaths(newCorePath: string, newUserDataPath: string) {
export function setPaths(newCorePath: string, newRoUserDataPath: string, newRwUserDataPath: string) {
corePath = newCorePath;
userDataPath = newUserDataPath;
roUserDataPath = newRoUserDataPath;
rwUserDataPath = newRwUserDataPath;
}

export function setNickname(newNickname: string) {
Expand All @@ -36,7 +38,7 @@ export function setAutoStartServer(enabled: boolean) {
}

export function load(callback: (err: Error) => void) {
const settingsPath = `${userDataPath}/settings.json`;
const settingsPath = `${rwUserDataPath}/settings.json`;
console.log(`Loading settings from ${settingsPath}.`);

fs.readFile(settingsPath, { encoding: "utf8" }, (err, dataJSON) => {
Expand Down Expand Up @@ -97,7 +99,7 @@ export function applyScheduledSave() {
savedChatrooms
};

fs.writeFileSync(`${userDataPath}/settings.json`, JSON.stringify(data, null, 2) + "\n", { encoding: "utf8" });
fs.writeFileSync(`${rwUserDataPath}/settings.json`, JSON.stringify(data, null, 2) + "\n", { encoding: "utf8" });

clearTimeout(scheduleSaveTimeoutId);
scheduleSaveTimeoutId = null;
Expand Down
10 changes: 9 additions & 1 deletion src/renderer/updateManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import * as systemServerSettings from "./serverSettings/systems";
import * as i18n from "../shared/i18n";
import * as splashScreen from "./splashScreen";
import fetch from "../shared/fetch";
import * as flatpak from "./flatpak";

/* tslint:disable */
const https: typeof dummy_https = require("follow-redirects").https;
Expand All @@ -24,7 +25,14 @@ if (appVersion === "0.0.0-dev") {
} else appVersion = `v${appVersion}`;

export function checkForUpdates(callback: (err: Error) => void) {
async.series([ checkAppUpdate, checkCoreUpdate ], callback);
let updateRoutines = [ checkAppUpdate, checkCoreUpdate ];
if (flatpak.underFlatpak())
updateRoutines = [ checkNoUpdates ];
async.series(updateRoutines, callback);
}

function checkNoUpdates(callback: (err: Error) => void) {
callback(null);
}

function checkAppUpdate(callback: (err: Error) => void) {
Expand Down