Skip to content

Commit

Permalink
Installed Versions
Browse files Browse the repository at this point in the history
- Installed versions
- Removing previous files when installing
- Fix decompressing (see kevva/decompress#46)
- Remove potential remote code execution (see https://benjamin-altpeter.de/shell-openexternal-dangers/)
- No version image
- Minor UI changes (disable selecting)
  • Loading branch information
Nadwey committed Jun 7, 2022
1 parent 38d3c21 commit cf4480f
Show file tree
Hide file tree
Showing 12 changed files with 151 additions and 29 deletions.
14 changes: 8 additions & 6 deletions main/RendererBridge.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { ipcMain } = require("electron");
const SE3Api = require("./SE3Api");
const { VersionInstaller, IsVersionInstalled } = require("./VersionInstaller");
const { VersionInstaller, IsVersionInstalled, GetInstalledVersions } = require("./VersionInstaller");

/**
* @type {Object.<string, VersionInstaller>}
Expand All @@ -20,9 +20,7 @@ const ExportAsync = (name, fun) => {
};

const RendererBridge = () => {
ExportAsync("get_versions", SE3Api.GetVersions);
ExportAsync("get_launcher_info", SE3Api.GetLauncherInfo);

// Installer
ipcMain.handle("install_version", (e, id, tag) => {
const deleteInstaller = (id) => {
installers[id] = null;
Expand Down Expand Up @@ -57,11 +55,15 @@ const RendererBridge = () => {
deleteInstaller(id);
}
});

Export("is_version_installed", IsVersionInstalled);
Export("installer_cancel", (id) => {
installers[id].Stop();
});

Export("is_version_installed", IsVersionInstalled);
ExportAsync("get_versions", SE3Api.GetVersions);
ExportAsync("get_installed_versions", GetInstalledVersions);

ExportAsync("get_launcher_info", SE3Api.GetLauncherInfo);
};

module.exports = RendererBridge;
1 change: 0 additions & 1 deletion main/SE3Api.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ const GetVersions = async () => {
* @returns {String} markdown launcher info
*/
const GetLauncherInfo = async () => {
console.log(se3ApiSettings.GetLauncherInfo());
return (
await axios.get(se3ApiSettings.GetLauncherInfo(), {
transformResponse: [],
Expand Down
24 changes: 20 additions & 4 deletions main/VersionInstaller.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const axios = require("axios").default;
const { GetVersionZipFile } = require("./SE3Api");
const { GetVersionZipFile, GetVersions } = require("./SE3Api");
const fs = require("fs");
const path = require("path");
const EventEmitter = require("events");
Expand Down Expand Up @@ -28,6 +28,7 @@ class VersionInstaller extends EventEmitter {
}
const savePath = path.join(GetLauncherDirectory(), file.version.file);

if (fs.existsSync(savePath)) fs.rmSync(savePath);
const res = await axios.get(file.url, {
responseType: "stream",
});
Expand All @@ -41,9 +42,12 @@ class VersionInstaller extends EventEmitter {
this.writer.on("close", async () => {
this.emit("unpacking");
const dir = path.join(GetVersionsDirectory(), file.version.tag);
if (fs.existsSync(dir)) fs.rmSync(dir, { recursive: true, force: true });

try {
await decompress(savePath, dir);
await decompress(savePath, dir, {
filter: file => !file.path.endsWith("/")
});
} catch (ex) {
this.emit("error", ex);
return;
Expand Down Expand Up @@ -91,11 +95,23 @@ class VersionInstaller extends EventEmitter {
*
* @param {String} versionTag
*/
const IsVersionInstalled = (versionTag) => {
const IsVersionInstalled = (versionTag) => {
return fs.existsSync(path.join(GetVersionsDirectory(), versionTag));
}

/**
* Returns installed versions
*
* @returns {import("./SE3Api").FetchedVersion[]}
*/
const GetInstalledVersions = async() => {
let versions = (await GetVersions()).Versions;

return versions.filter(version => IsVersionInstalled(version.tag));
}

module.exports = {
VersionInstaller,
IsVersionInstalled
IsVersionInstalled,
GetInstalledVersions
};
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"devDependencies": {
"concurrently": "^7.2.1",
"cross-env": "^7.0.3",
"electron": "^19.0.1",
"electron": "^19.0.3",
"electron-builder": "^23.0.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
Expand Down Expand Up @@ -48,11 +48,11 @@
"dependencies": {
"@6c65726f79/custom-titlebar": "^0.9.1",
"@electron/remote": "^2.0.8",
"@mantine/core": "^4.2.6",
"@mantine/hooks": "^4.2.6",
"@mantine/modals": "^4.2.6",
"@mantine/next": "^4.2.6",
"@mantine/notifications": "^4.2.6",
"@mantine/core": "^4.2.8",
"@mantine/hooks": "^4.2.8",
"@mantine/modals": "^4.2.8",
"@mantine/next": "^4.2.8",
"@mantine/notifications": "^4.2.8",
"appdata-path": "^1.0.0",
"axios": "^0.27.2",
"decompress": "^4.2.1",
Expand Down
7 changes: 5 additions & 2 deletions preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ window.addEventListener("DOMContentLoaded", () => {
// Open external links in browser
document.querySelector("body").addEventListener("click", (event) => {
if (event.target.tagName.toLowerCase() === "a") {
if (!['https:', 'http:'].includes(new URL(event.target.href).protocol)) return;
const absoluteUrl = new RegExp("^(?:[a-z]+:)?//", "i");
if (!absoluteUrl.test(event.target.href)) return;
event.preventDefault();
if (!absoluteUrl.test(event.target.href)) return;
electron.shell.openExternal(event.target.href);
}
});
Expand Down Expand Up @@ -109,7 +110,9 @@ const IsVersionInstalled = (versionTag) => {
ipcRenderer.invoke("is_version_installed", versionTag);
};

const GetInstalledVersions = async () => {};
const GetInstalledVersions = async() => {
return await ipcRenderer.invoke("get_installed_versions");
};

contextBridge.exposeInMainWorld("se3Api", {
GetVersions,
Expand Down
Binary file added public/no-version-image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 17 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import styles from "./styles/App.module.css";
import "github-markdown-css/github-markdown-dark.css";
import { useEffect, useState } from "react";
import VersionSelector from "./VersionSelector";
import { GetVersions, InstallVersion } from "./SE3Api/versionsApi";
import { GetInstalledVersions, GetVersions, InstallVersion } from "./SE3Api/versionsApi";
import { GetLauncherInfo } from "./SE3Api/launcherApi";
import HomePage from "./HomePage";
import { showNotification, updateNotification } from "@mantine/notifications";
Expand All @@ -12,20 +12,27 @@ import remarkGfm from "remark-gfm";
import ReactMarkdown from "react-markdown";
import { humanFileSize } from "./utils";
import { throttle } from "lodash";
import InstalledVersion from "./InstalledVersion";

export default function App() {
const [activeTab, setActiveTab] = useState(0);
const [versionsSelectorVersions, setVersionsSelectorVersions] = useState([]);
const [versionSelectorShown, setVersionSelectorShown] = useState(false);
const [launcherText, setLauncherText] = useState("Failed to load launcher info");
const [installedVersions, setInstalledVersions] = useState([]);
const modals = useModals();

useEffect(() => {
(async () => {
setLauncherText(await GetLauncherInfo());
setInstalledVersions(await GetInstalledVersions());
})();
}, []);

const updateInstalledVersions = async() => {
setInstalledVersions(await GetInstalledVersions());
}

const VersionSelectorVersions = async () => {
const versions = await GetVersions();
let outVersions = [];
Expand Down Expand Up @@ -114,6 +121,7 @@ export default function App() {
disallowClose: false,
loading: false,
});
updateInstalledVersions();
},
onCancel: () => {
throttled.flush();
Expand All @@ -124,17 +132,19 @@ export default function App() {
disallowClose: false,
loading: false,
});
updateInstalledVersions();
},
onError: (err) => {
throttled.flush();
updateNotification({
id: notificationID,
title: `Error installing ${version.name}`,
message: err,
message: `${err}\nTODO: RETRY`,
autoClose: true,
disallowClose: false,
loading: false,
});
updateInstalledVersions();
}
});
};
Expand All @@ -157,6 +167,11 @@ export default function App() {
<HomePage />
</Tabs.Tab>
<Tabs.Tab label="Versions">
<div className={styles.versionsContainer}>
{
installedVersions.map(version => <InstalledVersion key={version.tag} version={version} />).reverse()
}
</div>
<VersionSelector
onCancel={() => {
setVersionSelectorShown(false);
Expand Down
31 changes: 28 additions & 3 deletions src/InstalledVersion.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
export default function InstalledVersion() {

}
import { Button } from "@mantine/core";
import styles from "./styles/InstalledVersion.module.css";

export default function InstalledVersion({ version }) {
return (
<div
style={{
backgroundImage: `url("${version.image ? new URL("./" + version.image, window.versionsApiSettings.GetImagesDir()).toString() : "no-version-image.png"}")`,
}}
className={styles.installedVersionContainer}
>
<div className={styles.installedVersion}>
<span
style={{
color: version.hidden ? "red" : "white",
}}
className={styles.title}
>
{version.name}
</span>
<div className={styles.buttons}>
<Button color="red">Uninstall</Button>
<Button>Play</Button>
</div>
</div>
</div>
);
}
10 changes: 5 additions & 5 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,18 @@

::-webkit-scrollbar-track
{
background-color: #555;
background-color: #333;
}

::-webkit-scrollbar
{
width: 12px;
background-color: #555;
width: 10px;
background-color: #333;
}

::-webkit-scrollbar-thumb
{
border-radius: 10px;
background-color: #F5F5F5;
background-color: #888;
}

body {
Expand All @@ -42,6 +41,7 @@ body {
.mantine-Tabs-tabsList {
background-color: #00000050;
backdrop-filter: blur(2px);
user-select: none;
}

.mantine-Tabs-body {
Expand Down
4 changes: 4 additions & 0 deletions src/se3Api/versionsApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,7 @@ export function InstallVersion(settings) {
export function IsVersionInstalled(versionTag) {
return window.se3Api.IsVersionInstalled(versionTag);
}

export async function GetInstalledVersions() {
return await window.se3Api.GetInstalledVersions();
}
7 changes: 7 additions & 0 deletions src/styles/App.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,11 @@
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
padding: 2px 10px;
cursor: pointer;
}

.versionsContainer {
height: calc(100% - 30px);
text-align: center;
margin: 30px 0 0;
overflow-y: scroll;
}
51 changes: 51 additions & 0 deletions src/styles/InstalledVersion.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
.installedVersionContainer {
position: relative;
padding: 10px;
margin: 25px;
background-size: cover;
background-position: center;
width: 350px;
height: 210px;
display: inline-block;
}

.installedVersion {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #00000020;
user-select: none;
}

.title {
position: absolute;
top: 0;
left: 0;
right: 0;
display: inline-block;
background-color: #00000090;
color: white;
font-size: 25px;
padding: 5px 0;
font-family: "Quicksand";
}

.buttons {
position: absolute;
left: 0;
right: 0;
bottom: 0;
display: inline-block;
background-color: #00000090;
color: white;
font-size: 25px;
padding: 5px 0;
font-family: "Quicksand";
}

.buttons > button {
margin: 0 5px;
width: 100px;
}

0 comments on commit cf4480f

Please sign in to comment.