This commit is contained in:
+39
-7
@@ -336,6 +336,39 @@ function versionLine(pkg, status) {
|
||||
return items;
|
||||
}
|
||||
|
||||
function formatSize(bytes) {
|
||||
if (!bytes) return "";
|
||||
if (bytes >= 1048576) return `${(bytes / 1048576).toFixed(1)} MB`;
|
||||
return `${Math.max(1, Math.round(bytes / 1024))} KB`;
|
||||
}
|
||||
|
||||
function renderGet() {
|
||||
const node = $("get");
|
||||
const { app, bundle } = state.manifest;
|
||||
const cards = [];
|
||||
if (app) {
|
||||
cards.push(
|
||||
el("div", { class: "get-card" },
|
||||
el("h2", {}, "Windows app"),
|
||||
el("p", {}, "Finds your game automatically, even inside Program Files, and installs RedLoader and mods with one click."),
|
||||
el("a", { class: "button primary", href: app.url }, `Download the app (${formatSize(app.size)})`),
|
||||
el("p", { class: "get-note" }, `Version ${app.version}. If Windows shows a warning, click More info, then Run anyway.`),
|
||||
),
|
||||
);
|
||||
}
|
||||
if (bundle) {
|
||||
cards.push(
|
||||
el("div", { class: "get-card" },
|
||||
el("h2", {}, "Zip download"),
|
||||
el("p", {}, "RedLoader and every mod in one zip. Extract it into your Sons of the Forest folder, the one that contains SonsOfTheForest.exe."),
|
||||
el("a", { class: "button secondary", href: bundle.url, download: "sotf-mods.zip" }, `Download zip (${formatSize(bundle.size)})`),
|
||||
),
|
||||
);
|
||||
}
|
||||
node.hidden = !cards.length;
|
||||
node.replaceChildren(...cards);
|
||||
}
|
||||
|
||||
function renderFolder() {
|
||||
const node = $("folder");
|
||||
node.replaceChildren();
|
||||
@@ -344,8 +377,8 @@ function renderFolder() {
|
||||
if (!supportsFs) {
|
||||
node.append(
|
||||
el("div", { class: "folder-text" },
|
||||
el("p", { class: "folder-name" }, "This browser can't install mods"),
|
||||
el("p", { class: "folder-help" }, "Open this page in Chrome or Edge on Windows to install mods with one click. You can still download each mod from its release page below."),
|
||||
el("p", { class: "folder-name" }, "Install from this page"),
|
||||
el("p", { class: "folder-help" }, "This browser can't write to your game folder. Use the Windows app or the zip download above."),
|
||||
),
|
||||
);
|
||||
return;
|
||||
@@ -378,15 +411,13 @@ function renderFolder() {
|
||||
|
||||
node.append(
|
||||
el("div", { class: "folder-text" },
|
||||
el("p", { class: "folder-name" }, "Choose your game folder"),
|
||||
el("p", { class: "folder-name" }, "Install from this page"),
|
||||
el("p", { class: "folder-help" },
|
||||
state.folderError ? `${state.folderError} ` : "",
|
||||
"On Steam it's usually ",
|
||||
el("code", {}, "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Sons Of The Forest"),
|
||||
". In Steam you can find it with Manage, Browse local files.",
|
||||
"Chrome and Edge can't open folders inside Program Files, which is where Steam installs games by default. If Chrome says the folder contains system files, use the Windows app instead.",
|
||||
),
|
||||
),
|
||||
el("button", { class: "primary", disabled: state.busy, onclick: chooseFolder }, "Choose game folder"),
|
||||
el("button", { class: "secondary", disabled: state.busy, onclick: chooseFolder }, "Choose game folder"),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -486,6 +517,7 @@ function renderFooter() {
|
||||
|
||||
function render() {
|
||||
if (!state.manifest) return;
|
||||
renderGet();
|
||||
renderFolder();
|
||||
renderRedloader();
|
||||
renderMods();
|
||||
|
||||
+3
-2
@@ -15,9 +15,10 @@
|
||||
<main class="page">
|
||||
<header class="masthead">
|
||||
<h1>Sons of the Forest mod loader</h1>
|
||||
<p class="lede">Pick your game folder once, then install, update and remove mods with one click.</p>
|
||||
<p class="lede">Install, update and remove Sons of the Forest mods with one click.</p>
|
||||
</header>
|
||||
<section id="folder" class="folder" aria-label="Game folder"></section>
|
||||
<section id="get" class="get" aria-label="Ways to install" hidden></section>
|
||||
<section id="folder" class="folder" aria-label="Install from this page"></section>
|
||||
<section id="redloader" class="block" aria-labelledby="redloader-title" hidden></section>
|
||||
<section id="mods" class="block" aria-labelledby="mods-title"></section>
|
||||
<p id="status" class="status" role="status" aria-live="polite"></p>
|
||||
|
||||
+72
-1
@@ -74,13 +74,84 @@ a:hover {
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
.get {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
|
||||
gap: 1rem;
|
||||
margin-top: 2.75rem;
|
||||
}
|
||||
|
||||
.get-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding: 1.35rem 1.5rem 1.4rem;
|
||||
background: var(--bark);
|
||||
border: 1px solid var(--bark-line);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.get-card:first-child {
|
||||
border-top: 5px solid var(--flare);
|
||||
}
|
||||
|
||||
.get-card h2 {
|
||||
margin: 0;
|
||||
font-family: var(--display);
|
||||
font-weight: 700;
|
||||
font-size: 1.75rem;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.get-card p {
|
||||
margin: 0.4rem 0 1.1rem;
|
||||
color: var(--lichen);
|
||||
}
|
||||
|
||||
.get-card .get-note {
|
||||
margin: 0.8rem 0 0;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
a.button {
|
||||
display: inline-block;
|
||||
margin-top: auto;
|
||||
padding: 0.6rem 1.1rem;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.2;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.button.primary {
|
||||
background: var(--flare);
|
||||
color: var(--flare-ink);
|
||||
}
|
||||
|
||||
a.button.primary:hover {
|
||||
background: var(--flare-hover);
|
||||
color: var(--flare-ink);
|
||||
}
|
||||
|
||||
a.button.secondary {
|
||||
color: var(--fog);
|
||||
border-color: var(--bark-line);
|
||||
}
|
||||
|
||||
a.button.secondary:hover {
|
||||
border-color: var(--lichen);
|
||||
color: var(--fog);
|
||||
}
|
||||
|
||||
.folder {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem 1.5rem;
|
||||
margin-top: 2.75rem;
|
||||
margin-top: 1rem;
|
||||
padding: 1.25rem 1.5rem;
|
||||
background: var(--bark);
|
||||
border: 1px solid var(--bark-line);
|
||||
|
||||
Reference in New Issue
Block a user