Upload via GUI (202 Dateien)
This commit is contained in:
@@ -75,6 +75,8 @@ const DEFAULT_SETTINGS = {
|
|||||||
sortBy: 'lastPlayed', // lastPlayed | name
|
sortBy: 'lastPlayed', // lastPlayed | name
|
||||||
iso3dIcons: true, // Block-Symbole räumlich darstellen
|
iso3dIcons: true, // Block-Symbole räumlich darstellen
|
||||||
bedrockEnabled: true, // Bedrock-Bereich anzeigen (nur wenn auch installiert)
|
bedrockEnabled: true, // Bedrock-Bereich anzeigen (nur wenn auch installiert)
|
||||||
|
betaTeilnahme: false, // Vorabfassungen (Beta, RC) als Update bekommen
|
||||||
|
letzteVersionVorab: false, // lief zuletzt eine Vorabfassung? (siehe main.js: Beta-Teilnahme)
|
||||||
desktopNotifications: true, // Windows-Meldung bei fertigem Hintergrund-Download/-Backup
|
desktopNotifications: true, // Windows-Meldung bei fertigem Hintergrund-Download/-Backup
|
||||||
friendsEnabled: true,
|
friendsEnabled: true,
|
||||||
friendsShareServer: true, // Freunde sehen, auf welchem Server man spielt (für "Beitreten")
|
friendsShareServer: true, // Freunde sehen, auf welchem Server man spielt (für "Beitreten")
|
||||||
|
|||||||
+19
-17
@@ -82,6 +82,8 @@ body{display:grid;grid-template-rows:auto auto 1fr auto;grid-template-columns:mi
|
|||||||
.titelleiste{display:flex;align-items:center;gap:8px;height:32px;padding:0 150px 0 10px;background:var(--titel-bg);color:var(--titel-fg);-webkit-app-region:drag;user-select:none;font-size:12px}
|
.titelleiste{display:flex;align-items:center;gap:8px;height:32px;padding:0 150px 0 10px;background:var(--titel-bg);color:var(--titel-fg);-webkit-app-region:drag;user-select:none;font-size:12px}
|
||||||
.titel-logo{width:16px;height:16px;flex:none}
|
.titel-logo{width:16px;height:16px;flex:none}
|
||||||
.titel-text{white-space:nowrap}
|
.titel-text{white-space:nowrap}
|
||||||
|
/* Kennzeichnung einer Vorabfassung ("Beta 1", "RC 2") neben dem Namen */
|
||||||
|
.titel-beta{padding:1px 8px;border-radius:99px;background:#e9a800;color:#1b1400;font-size:10.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;line-height:16px;white-space:nowrap}
|
||||||
body.fenster-inaktiv .titelleiste>*{opacity:.55}
|
body.fenster-inaktiv .titelleiste>*{opacity:.55}
|
||||||
body.is-popout>.titelleiste{display:none}
|
body.is-popout>.titelleiste{display:none}
|
||||||
|
|
||||||
@@ -941,20 +943,20 @@ select.s-wert,input.s-wert{padding:6px 8px;border:1px solid var(--border);border
|
|||||||
.se-u2d[data-werkzeug="pipette"] canvas{cursor:copy}
|
.se-u2d[data-werkzeug="pipette"] canvas{cursor:copy}
|
||||||
.se-fuss{align-items:center}
|
.se-fuss{align-items:center}
|
||||||
.se-status{flex:1;min-width:0;margin-left:6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
.se-status{flex:1;min-width:0;margin-left:6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||||
|
|
||||||
/* Manipulationsschutz: gesperrte Instanz (Verbotszeichen, siehe integritaet.js) */
|
/* Manipulationsschutz: gesperrte Instanz (Verbotszeichen, siehe integritaet.js) */
|
||||||
.card.gesperrt .card-icon,.card.gesperrt .card-icon-img{filter:grayscale(1) brightness(.55)}
|
.card.gesperrt .card-icon,.card.gesperrt .card-icon-img{filter:grayscale(1) brightness(.55)}
|
||||||
.card-verbot{position:absolute;left:50%;top:6px;width:60px;height:60px;margin-left:-30px;opacity:.95;pointer-events:none;z-index:2;filter:drop-shadow(0 1px 2px rgba(0,0,0,.45))}
|
.card-verbot{position:absolute;left:50%;top:6px;width:60px;height:60px;margin-left:-30px;opacity:.95;pointer-events:none;z-index:2;filter:drop-shadow(0 1px 2px rgba(0,0,0,.45))}
|
||||||
.card.gesperrt .card-name{color:#e05555}
|
.card.gesperrt .card-name{color:#e05555}
|
||||||
.card.gesperrt.sel .card-name{color:#fff;background:#b02020}
|
.card.gesperrt.sel .card-name{color:#fff;background:#b02020}
|
||||||
.side-ico{position:relative}
|
.side-ico{position:relative}
|
||||||
.side-ico.gesperrt > :not(.side-verbot){filter:grayscale(1) brightness(.55)}
|
.side-ico.gesperrt > :not(.side-verbot){filter:grayscale(1) brightness(.55)}
|
||||||
.side-ico img.side-verbot{position:absolute;left:-4px;top:-4px;width:60px;height:60px;object-fit:contain;border-radius:0;pointer-events:none}
|
.side-ico img.side-verbot{position:absolute;left:-4px;top:-4px;width:60px;height:60px;object-fit:contain;border-radius:0;pointer-events:none}
|
||||||
.side-gesperrt{margin:8px 6px 2px;padding:9px 10px;border:1px solid rgba(200,0,0,.55);background:rgba(200,0,0,.10);border-radius:6px;font-size:12px}
|
.side-gesperrt{margin:8px 6px 2px;padding:9px 10px;border:1px solid rgba(200,0,0,.55);background:rgba(200,0,0,.10);border-radius:6px;font-size:12px}
|
||||||
.side-gesperrt-titel{display:flex;align-items:center;gap:6px;font-weight:700;color:#e04848;font-size:13px;margin-bottom:4px}
|
.side-gesperrt-titel{display:flex;align-items:center;gap:6px;font-weight:700;color:#e04848;font-size:13px;margin-bottom:4px}
|
||||||
.side-gesperrt-titel img{width:18px;height:18px}
|
.side-gesperrt-titel img{width:18px;height:18px}
|
||||||
.side-gesperrt-text{line-height:1.35;margin:4px 0}
|
.side-gesperrt-text{line-height:1.35;margin:4px 0}
|
||||||
.side-gesperrt-text.dim{opacity:.7;font-size:11px}
|
.side-gesperrt-text.dim{opacity:.7;font-size:11px}
|
||||||
.side-gesperrt-gruende{margin:4px 0 8px;padding-left:16px;max-height:110px;overflow:auto;word-break:break-word;line-height:1.35}
|
.side-gesperrt-gruende{margin:4px 0 8px;padding-left:16px;max-height:110px;overflow:auto;word-break:break-word;line-height:1.35}
|
||||||
.side-gesperrt-gruende .dim{opacity:.7;list-style:none;margin-left:-16px}
|
.side-gesperrt-gruende .dim{opacity:.7;list-style:none;margin-left:-16px}
|
||||||
#p-wiederherstellen{width:100%;margin:4px 0}
|
#p-wiederherstellen{width:100%;margin:4px 0}
|
||||||
|
|||||||
+60
-14
@@ -15,6 +15,32 @@ const crypto = require('crypto');
|
|||||||
const { spawn } = require('child_process');
|
const { spawn } = require('child_process');
|
||||||
|
|
||||||
const API = 'https://git.viper.ipv64.net/api/v1/repos/M_Viper/AeroMc-Launcher/releases';
|
const API = 'https://git.viper.ipv64.net/api/v1/repos/M_Viper/AeroMc-Launcher/releases';
|
||||||
|
/*
|
||||||
|
* Beta-Kanal: Vorabfassungen (Beta, RC) liegen im selben Repository wie die
|
||||||
|
* fertigen Versionen, in Gitea als "Pre-Release" markiert – und mit einem Tag,
|
||||||
|
* dem "0.0.0-" vorangestellt ist:
|
||||||
|
*
|
||||||
|
* App-Version 1.2.4-beta.1 -> Tag 0.0.0-1.2.4-beta.1
|
||||||
|
*
|
||||||
|
* Der Vorsatz ist nötig, weil Launcher bis 1.2.3 das Pre-Release-Feld nicht
|
||||||
|
* kennen und nur die Zahlen am Anfang des Tags lesen: "1.2.4-beta.1" wäre für
|
||||||
|
* sie ein normales Update auf 1.2.4, das ALLE Nutzer bekämen. "0.0.0-…" lesen
|
||||||
|
* sie als uralte Version 0.0.0 und ignorieren sie; fertige Versionen finden sie
|
||||||
|
* weiterhin. (Ein Tag ohne Zahl vorn, etwa "beta-…", taugt nicht: Er bringt bei
|
||||||
|
* alten Launchern die Sortierung durcheinander, sie fänden dann gar kein Update
|
||||||
|
* mehr – mit dem echten 1.2.3 geprüft.)
|
||||||
|
*/
|
||||||
|
const BETA_VORSATZ = /^0\.0\.0-(?=\d)/;
|
||||||
|
|
||||||
|
// Version, die ein Release wirklich enthält: Tag ohne "v" und ohne Beta-Vorsatz
|
||||||
|
function tagVersion(tag) {
|
||||||
|
return normVersion(tag).replace(BETA_VORSATZ, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vorabfassung? In Gitea so markiert, mit Beta-Vorsatz oder mit Kennung im Tag
|
||||||
|
function istVorab(release) {
|
||||||
|
return !!release.prerelease || BETA_VORSATZ.test(normVersion(release.tag_name)) || !!parsePreRelease(tagVersion(release.tag_name));
|
||||||
|
}
|
||||||
const UA = 'AeroMC-Launcher';
|
const UA = 'AeroMC-Launcher';
|
||||||
// Downloads nur von hier – eine Release-Datei mit fremder Adresse wird abgelehnt
|
// Downloads nur von hier – eine Release-Datei mit fremder Adresse wird abgelehnt
|
||||||
const ERLAUBTER_HOST = 'git.viper.ipv64.net';
|
const ERLAUBTER_HOST = 'git.viper.ipv64.net';
|
||||||
@@ -188,16 +214,23 @@ function parsePreRelease(v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Vergleicht die Vorabkennungen zweier gleicher Versionsnummern.
|
* Vergleicht die Vorabkennungen zweier gleicher Versionsnummern – wie SemVer:
|
||||||
|
* Die fertige Fassung ist neuer als jede Vorabfassung derselben Nummer
|
||||||
|
* ("1.3.0" > "1.3.0-beta.2"), sonst könnten Beta-Nutzer nie auf die fertige
|
||||||
|
* Version wechseln.
|
||||||
*
|
*
|
||||||
* Bewusst nicht streng nach SemVer: trägt ein Release-Tag die Vorabkennung
|
* Früher zählte eine Vorabkennung nur, wenn beide Seiten eine hatten – als
|
||||||
* nicht, die die App selbst meldet (Tag "1.0.1" gegen App "1.0.1-beta"),
|
* Schutz vor einer Endlosschleife, falls ein Release unter dem Tag "1.0.1"
|
||||||
* würde "1.0.1" als neuer gelten – der Launcher böte dasselbe Update nach
|
* steht, die App darin sich aber weiter als "1.0.1-beta" meldet. Das kann nicht
|
||||||
* jeder Installation erneut an, eine Endlosschleife. Deshalb zählt eine
|
* mehr passieren: Die Signatur bindet die Version (siehe pruefeSignatur), und
|
||||||
* Vorabkennung nur, wenn sie auf beiden Seiten vorhanden ist (beta.1 -> beta.2).
|
* sign-release.js nimmt sie aus derselben package.json wie die App. Ein Release,
|
||||||
|
* bei dem Tag und App-Version nicht übereinstimmen, lässt sich gar nicht
|
||||||
|
* installieren.
|
||||||
*/
|
*/
|
||||||
function comparePreRelease(a, b) {
|
function comparePreRelease(a, b) {
|
||||||
if (!a || !b) return 0;
|
if (!a && !b) return 0;
|
||||||
|
if (!a) return 1; // a ist die fertige Fassung, b eine Vorabfassung
|
||||||
|
if (!b) return -1;
|
||||||
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
||||||
const x = a[i]; const y = b[i];
|
const x = a[i]; const y = b[i];
|
||||||
if (x === undefined) return -1;
|
if (x === undefined) return -1;
|
||||||
@@ -250,20 +283,31 @@ function pickAsset(release, installKind) {
|
|||||||
* Prüft auf Updates.
|
* Prüft auf Updates.
|
||||||
* -> { available, currentVersion, latestVersion, notes, asset, url, noReleases }
|
* -> { available, currentVersion, latestVersion, notes, asset, url, noReleases }
|
||||||
*/
|
*/
|
||||||
async function checkForUpdate(currentVersion) {
|
async function checkForUpdate(currentVersion, opts) {
|
||||||
const installKind = detectInstallKind();
|
const installKind = detectInstallKind();
|
||||||
const res = await fetch(API + '?limit=10', { headers: { 'User-Agent': UA, Accept: 'application/json' } });
|
const kopf = { headers: { 'User-Agent': UA, Accept: 'application/json' } };
|
||||||
|
const res = await fetch(API + '?limit=30', kopf);
|
||||||
if (!res.ok) throw new Error('Update-Server antwortet mit HTTP ' + res.status);
|
if (!res.ok) throw new Error('Update-Server antwortet mit HTTP ' + res.status);
|
||||||
const list = await res.json();
|
const list = await res.json();
|
||||||
const releases = (Array.isArray(list) ? list : []).filter((r) => !r.draft);
|
const alle = (Array.isArray(list) ? list : []).filter((r) => !r.draft);
|
||||||
if (!releases.length) {
|
|
||||||
|
if (!alle.length) {
|
||||||
return { available: false, noReleases: true, currentVersion };
|
return { available: false, noReleases: true, currentVersion };
|
||||||
}
|
}
|
||||||
|
// Vorabfassungen (Beta, RC …) bekommt nur, wer selbst eine Vorabfassung nutzt.
|
||||||
|
// Wer die fertige Fassung installiert hat, bleibt auf fertigen Versionen.
|
||||||
|
// Ob jemand teilnimmt, entscheidet der Schalter "An der Beta teilnehmen"
|
||||||
|
// (opts.beta). Ohne Angabe zählt die installierte Version.
|
||||||
|
const nutztVorab = opts && typeof opts.beta === 'boolean' ? opts.beta : !!parsePreRelease(currentVersion);
|
||||||
|
const releases = nutztVorab ? alle : alle.filter((r) => !istVorab(r));
|
||||||
|
if (!releases.length) {
|
||||||
|
return { available: false, currentVersion, installKind };
|
||||||
|
}
|
||||||
// neueste anhand der Versionsnummer (nicht nach Datum, damit Nachträge nicht stören)
|
// neueste anhand der Versionsnummer (nicht nach Datum, damit Nachträge nicht stören)
|
||||||
releases.sort((a, b) => compareVersions(b.tag_name, a.tag_name));
|
releases.sort((a, b) => compareVersions(tagVersion(b.tag_name), tagVersion(a.tag_name)));
|
||||||
const latest = releases[0];
|
const latest = releases[0];
|
||||||
const available = compareVersions(latest.tag_name, currentVersion) > 0;
|
const latestVersion = tagVersion(latest.tag_name);
|
||||||
const latestVersion = normVersion(latest.tag_name);
|
const available = compareVersions(latestVersion, currentVersion) > 0;
|
||||||
let asset = pickAsset(latest, installKind);
|
let asset = pickAsset(latest, installKind);
|
||||||
// ohne Signatur oder von fremder Adresse wird nichts automatisch installiert
|
// ohne Signatur oder von fremder Adresse wird nichts automatisch installiert
|
||||||
let unsigniert = false;
|
let unsigniert = false;
|
||||||
@@ -485,6 +529,8 @@ module.exports = {
|
|||||||
pruefeSignatur,
|
pruefeSignatur,
|
||||||
signaturText,
|
signaturText,
|
||||||
holeSignatur,
|
holeSignatur,
|
||||||
|
tagVersion,
|
||||||
|
istVorabVersion: (v) => !!parsePreRelease(v),
|
||||||
SIGNATUR_API,
|
SIGNATUR_API,
|
||||||
cleanupUpdateCache,
|
cleanupUpdateCache,
|
||||||
compareVersions,
|
compareVersions,
|
||||||
|
|||||||
Reference in New Issue
Block a user