1
0
mirror of https://github.com/zumbiepig/MineXLauncher.git synced 2025-06-08 08:14:48 +00:00
This commit is contained in:
zumbiepig 2024-09-01 16:11:00 -07:00
parent 0a58472584
commit dd0b28c755
No known key found for this signature in database
GPG Key ID: 17C891BE28B953DE
20 changed files with 75 additions and 96 deletions

View File

@ -1,11 +1,6 @@
# MineXLauncher # MineXLauncher
## Variables to update when changing version number ### Update data in [updates.json](/public/resources/data/updates.json)
- `cacheVersion` in [sw.ts](/src/sw.ts) and [sw-full.ts](/src/sw-full.ts)
- `launcherVersion` in [main.ts](/src/resources/scripts/main.ts)
- Changelog in [main.ts](/src/resources/scripts/main.ts)
- Changelog on [updates page](/public/updates/index.html)
## Client versions ## Client versions

View File

@ -3,7 +3,9 @@ import tseslint from 'typescript-eslint';
export default tseslint.config( export default tseslint.config(
eslint.configs.recommended, eslint.configs.recommended,
tseslint.configs.eslintRecommended,
...tseslint.configs.strict, ...tseslint.configs.strict,
// ...tseslint.configs.strictTypeChecked,
...tseslint.configs.stylisticTypeChecked, ...tseslint.configs.stylisticTypeChecked,
{ {
languageOptions: { languageOptions: {

View File

@ -17,7 +17,7 @@
</div> </div>
<div class="launcher"> <div class="launcher">
<div class="title-bar"> <div class="title-bar">
<span>MineXLauncher 1.5</span> <span id="title-bar-text">MineXLauncher</span>
</div> </div>
<div class="content"> <div class="content">
<div class="main-panel"> <div class="main-panel">

View File

@ -16,7 +16,7 @@
</div> </div>
<div class="launcher"> <div class="launcher">
<div class="title-bar"> <div class="title-bar">
<span>MineXLauncher 1.6.0</span> <span id="title-bar-text">MineXLauncher</span>
</div> </div>
<div class="content"> <div class="content">
<div class="sidebar"> <div class="sidebar">

View File

@ -16,7 +16,7 @@
</div> </div>
<div class="launcher"> <div class="launcher">
<div class="title-bar"> <div class="title-bar">
<span>MineXLauncher 1.6.0</span> <span id="title-bar-text">MineXLauncher</span>
</div> </div>
<div class="content"> <div class="content">
<div class="sidebar"> <div class="sidebar">

View File

@ -16,7 +16,7 @@
</div> </div>
<div class="launcher"> <div class="launcher">
<div class="title-bar"> <div class="title-bar">
<span>MineXLauncher 1.6.0</span> <span id="title-bar-text">MineXLauncher</span>
</div> </div>
<div class="content"> <div class="content">
<div class="sidebar"> <div class="sidebar">

View File

@ -16,7 +16,7 @@
</div> </div>
<div class="launcher"> <div class="launcher">
<div class="title-bar"> <div class="title-bar">
<span>MineXLauncher 1.6.0</span> <span id="title-bar-text">MineXLauncher</span>
</div> </div>
<div class="content"> <div class="content">
<div class="sidebar"> <div class="sidebar">

View File

@ -16,7 +16,7 @@
/> />
<meta property="og:title" content="MineXLauncher" /> <meta property="og:title" content="MineXLauncher" />
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:image" content="/resources/images/icons/favicon.webp" /> <meta property="og:image" content="/resources/images/icons/minexlauncher.webp" />
<meta property="og:url" content="https://launcher.orionzleon.me/" /> <meta property="og:url" content="https://launcher.orionzleon.me/" />
<meta property="og:description" content="MineXLauncher is a custom launcher for Eaglercraft that has many versions and clients." /> <meta property="og:description" content="MineXLauncher is a custom launcher for Eaglercraft that has many versions and clients." />
<meta property="og:locale" content="en-US" /> <meta property="og:locale" content="en-US" />

View File

@ -13,7 +13,7 @@
<body> <body>
<div class="launcher"> <div class="launcher">
<div class="title-bar"> <div class="title-bar">
<span>MineXLauncher 1.6.0</span> <span id="title-bar-text">MineXLauncher</span>
</div> </div>
<div class="content"> <div class="content">
<div class="sidebar"> <div class="sidebar">

View File

@ -16,7 +16,7 @@
</div> </div>
<div class="launcher"> <div class="launcher">
<div class="title-bar"> <div class="title-bar">
<span>MineXLauncher 1.6.0</span> <span id="title-bar-text">MineXLauncher</span>
</div> </div>
<div class="content"> <div class="content">
<div class="sidebar"> <div class="sidebar">

View File

@ -16,7 +16,7 @@
</div> </div>
<div class="launcher"> <div class="launcher">
<div class="title-bar"> <div class="title-bar">
<span>MineXLauncher 1.6.0</span> <span id="title-bar-text">MineXLauncher</span>
</div> </div>
<div class="content"> <div class="content">
<div class="sidebar"> <div class="sidebar">

View File

@ -17,7 +17,7 @@
</div> </div>
<div class="launcher"> <div class="launcher">
<div class="title-bar"> <div class="title-bar">
<span>MineXLauncher 1.6.0</span> <span id="title-bar-text">MineXLauncher</span>
</div> </div>
<div class="content"> <div class="content">
<div class="main-panel"> <div class="main-panel">

View File

@ -1,18 +1,18 @@
[ [
{ {
"version": "1.6.0", "version": "1.6",
"changelog": [ "changelog": [
"You can now install mods directly from the mods list" "You can now install mods directly from the mods list"
] ]
}, },
{ {
"version": "1.5.0", "version": "1.5",
"changelog": [ "changelog": [
"You can now install the launcher as a PWA web app" "You can now install the launcher as a PWA web app"
] ]
}, },
{ {
"version": "1.4.0", "version": "1.4",
"changelog": [ "changelog": [
"Added Starlike Client", "Added Starlike Client",
"Added welcome and setup screen", "Added welcome and setup screen",
@ -24,14 +24,14 @@
] ]
}, },
{ {
"version": "1.3.0", "version": "1.3",
"changelog": [ "changelog": [
"Redesigned archive page", "Redesigned archive page",
"Added offline page" "Added offline page"
] ]
}, },
{ {
"version": "1.2.0", "version": "1.2",
"changelog": [ "changelog": [
"Added Eaglercraft 1.2.5", "Added Eaglercraft 1.2.5",
"Added more mods and resource packs", "Added more mods and resource packs",
@ -39,7 +39,7 @@
] ]
}, },
{ {
"version": "1.1.0", "version": "1.1",
"changelog": [ "changelog": [
"Added a mods and resource packs list", "Added a mods and resource packs list",
"Temporary workaround for keyboard not working in the game", "Temporary workaround for keyboard not working in the game",
@ -51,7 +51,7 @@
] ]
}, },
{ {
"version": "1.0.0", "version": "1.0",
"changelog": [ "changelog": [
"Major rewrite, check it out yourself!" "Major rewrite, check it out yourself!"
] ]

View File

@ -16,7 +16,7 @@
</div> </div>
<div class="launcher"> <div class="launcher">
<div class="title-bar"> <div class="title-bar">
<span>MineXLauncher 1.6.0</span> <span id="title-bar-text">MineXLauncher</span>
</div> </div>
<div class="content"> <div class="content">
<div class="sidebar"> <div class="sidebar">

View File

@ -16,7 +16,7 @@
</div> </div>
<div class="launcher"> <div class="launcher">
<div class="title-bar"> <div class="title-bar">
<span>MineXLauncher 1.6.0</span> <span id="title-bar-text">MineXLauncher</span>
</div> </div>
<div class="content"> <div class="content">
<div class="sidebar"> <div class="sidebar">

View File

@ -16,7 +16,7 @@
</div> </div>
<div class="launcher"> <div class="launcher">
<div class="title-bar"> <div class="title-bar">
<span>MineXLauncher 1.6.0</span> <span id="title-bar-text">MineXLauncher</span>
</div> </div>
<div class="content"> <div class="content">
<div class="sidebar"> <div class="sidebar">

View File

@ -14,7 +14,7 @@
<body> <body>
<div class="launcher"> <div class="launcher">
<div class="title-bar"> <div class="title-bar">
<span>MineXLauncher 1.6.0</span> <span id="title-bar-text">MineXLauncher</span>
</div> </div>
<div class="content"> <div class="content">
<div class="main-panel"> <div class="main-panel">

View File

@ -1,10 +1,6 @@
import { SemVer, gt } from 'semver'; import { gt, coerce } from 'semver';
let selectedVersion: string | undefined; let selectedVersion: string;
// Update `cacheVersion` in sw.js too
const launcherVersion: SemVer = new SemVer('1.6.0-beta.1');
const releaseNotes = ['You can now install mods directly from the mods list'];
const theme = { const theme = {
load: function (themeToLoad?: string) { load: function (themeToLoad?: string) {
@ -14,7 +10,7 @@ const theme = {
themeElement.href = `/resources/styles/themes/${themeToLoad}.css`; themeElement.href = `/resources/styles/themes/${themeToLoad}.css`;
} else { } else {
const savedTheme = storage.local.get('theme'); const savedTheme = storage.local.get('theme');
if (savedTheme !== null) { if (savedTheme) {
themeElement.href = `/resources/styles/themes/${savedTheme}.css`; themeElement.href = `/resources/styles/themes/${savedTheme}.css`;
} }
} }
@ -157,8 +153,8 @@ const navigate = {
}, },
}; };
const cookie = { /*const cookie = {
set: function (key: string, value: string, days: number) { set: function (key: string, value: string | number | object | [] | boolean | null | undefined, days: number) {
let maxAge; let maxAge;
if (days) { if (days) {
maxAge = days * 60 * 60 * 24; maxAge = days * 60 * 60 * 24;
@ -167,20 +163,19 @@ const cookie = {
} }
document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(value)}; Max-Age=${maxAge}; Path=/; SameSite=Lax; Secure`; document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(value)}; Max-Age=${maxAge}; Path=/; SameSite=Lax; Secure`;
}, },
get: function (key: string): string | null { get: function (key: string) {
for (const cookie of document.cookie.split('; ')) { for (const cookie of document.cookie.split('; ')) {
const cookiePair = cookie.split('='); const cookiePair = cookie.split('=');
if (encodeURIComponent(key) === cookiePair[0]) { if (encodeURIComponent(key) === cookiePair[0]) {
// @ts-expect-error
return decodeURIComponent(cookiePair[1]); return decodeURIComponent(cookiePair[1]);
} }
} }
return null; return undefined;
}, },
delete: function (key: string) { delete: function (key: string) {
document.cookie = `${encodeURIComponent(key)}=; Max-Age=0; Path=/`; document.cookie = `${encodeURIComponent(key)}=; Max-Age=0; Path=/`;
}, },
}; };*/
const storage = { const storage = {
local: { local: {
@ -190,14 +185,12 @@ const storage = {
const json = JSON.parse(item); const json = JSON.parse(item);
if (json[key] !== undefined) { if (json[key] !== undefined) {
return json[key]; return json[key];
} else {
return null;
} }
} else { return undefined;
return null;
} }
return undefined;
}, },
set: function (key: string, value: string | number | object | [] | boolean | null) { set: function (key: string, value: string | number | object | boolean | null | undefined) {
let item = localStorage.getItem('minexlauncher'); let item = localStorage.getItem('minexlauncher');
if (item === null) { if (item === null) {
item = '{}'; item = '{}';
@ -206,14 +199,6 @@ const storage = {
json[key] = value; json[key] = value;
localStorage.setItem('minexlauncher', JSON.stringify(json)); localStorage.setItem('minexlauncher', JSON.stringify(json));
}, },
delete: function (key: string) {
const item = localStorage.getItem('minexlauncher');
if (item !== null) {
const json = JSON.parse(item);
json[key] = undefined;
localStorage.setItem('minexlauncher', JSON.stringify(json));
}
},
}, },
session: { session: {
get: function (key: string) { get: function (key: string) {
@ -222,14 +207,12 @@ const storage = {
const json = JSON.parse(item); const json = JSON.parse(item);
if (json[key] !== undefined) { if (json[key] !== undefined) {
return json[key]; return json[key];
} else {
return null;
} }
} else { return undefined;
return null;
} }
return undefined;
}, },
set: function (key: string, value: string | number | object | [] | boolean | null) { set: function (key: string, value: string | number | object | boolean | null | undefined) {
let item = sessionStorage.getItem('minexlauncher'); let item = sessionStorage.getItem('minexlauncher');
if (item === null) { if (item === null) {
item = '{}'; item = '{}';
@ -238,14 +221,6 @@ const storage = {
json[key] = value; json[key] = value;
sessionStorage.setItem('minexlauncher', JSON.stringify(json)); sessionStorage.setItem('minexlauncher', JSON.stringify(json));
}, },
delete: function (key: string) {
const item = sessionStorage.getItem('minexlauncher');
if (item !== null) {
const json = JSON.parse(item);
json[key] = undefined;
sessionStorage.setItem('minexlauncher', JSON.stringify(json));
}
},
}, },
}; };
@ -322,15 +297,24 @@ const serviceworker = {
}, },
}; };
theme.load();
if (detect.mobile()) {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = '/resources/styles/mobile.css';
document.head.appendChild(link);
}
if (window.location.pathname === '/') { if (window.location.pathname === '/') {
const lastPage = storage.session.get('lastPage'); const lastPage = storage.session.get('lastPage');
const isMobile = detect.mobile(); const isMobile = detect.mobile();
const iframe = document.createElement('iframe'); const iframe = document.createElement('iframe');
iframe.id = 'main_frame'; iframe.id = 'main_frame';
if (storage.local.get('lastVersion') === null) { if (!storage.local.get('lastVersion')) {
iframe.src = '/welcome/'; iframe.src = '/welcome/';
} else if (lastPage !== null) { } else if (lastPage && typeof lastPage === 'string') {
iframe.src = lastPage; iframe.src = lastPage;
} else if (isMobile) { } else if (isMobile) {
iframe.src = '/mobile/'; iframe.src = '/mobile/';
@ -349,7 +333,7 @@ if (window.location.pathname === '/') {
} }
}); });
/* if (storage.local.get('offlineCache') === true) { /* if (storage.local.get('offlineCache')) {
serviceworker.register('/sw-full.js'); serviceworker.register('/sw-full.js');
} else { } else {
serviceworker.register('/sw.js'); serviceworker.register('/sw.js');
@ -374,32 +358,30 @@ if (window.location.pathname === '/') {
} }
}); });
} }
document.addEventListener('DOMContentLoaded', async () => {
document.addEventListener('DOMContentLoaded', () => {
const profileName = document.getElementById('profile-name'); const profileName = document.getElementById('profile-name');
if (profileName) { if (profileName) {
profileName.textContent = storage.local.get('username'); profileName.textContent = storage.local.get('username');
} }
const titleBarText = document.getElementById('title-bar-text');
if (titleBarText) {
titleBarText.textContent += ` ${(await (await fetch('/resources/data/updates.json')).json())[0].version}`;
}
}); });
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', async () => {
const lastVersion = storage.local.get('lastVersion'); const lastVersion = storage.local.get('lastVersion');
if (lastVersion !== null && gt(launcherVersion, lastVersion)) { const currentVersion = (await (await fetch('/resources/data/updates.json')).json())[0].version;
alert(`MineXLauncher has been updated to v${launcherVersion}!\n\nChanges in v${launcherVersion}:\n${releaseNotes.map((item) => ` - ${item}`).join('\n')}`); const changelog = (await (await fetch('/resources/data/updates.json')).json())[0].changelog.map((change: string) => ` - ${change}`).join('\n');
storage.local.set('lastVersion', launcherVersion); // @ts-expect-error
if (lastVersion && gt(coerce(currentVersion, { includePrerelease: true }), coerce(lastVersion, { includePrerelease: true }))) {
alert(`MineXLauncher has been updated to v${currentVersion}!\n\nChanges in v${currentVersion}:\n${changelog}`);
storage.local.set('lastVersion', currentVersion);
} }
}); });
} }
if (detect.mobile()) {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = '/resources/styles/mobile.css';
document.head.appendChild(link);
}
theme.load();
if (window.location.pathname === '/settings/') { if (window.location.pathname === '/settings/') {
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
const profileName = document.getElementById('profile-name'); const profileName = document.getElementById('profile-name');
@ -463,7 +445,7 @@ if (window.location.pathname === '/settings/') {
theme.load(themeSelect.value); theme.load(themeSelect.value);
}); });
setupForm.addEventListener('submit', (event) => { setupForm.addEventListener('submit', async (event) => {
event.preventDefault(); event.preventDefault();
let username = usernameInput.value.replace(/[^A-Za-z0-9]/g, '_').substring(0, 16); let username = usernameInput.value.replace(/[^A-Za-z0-9]/g, '_').substring(0, 16);
@ -482,7 +464,7 @@ if (window.location.pathname === '/settings/') {
// storage.local.set('offlineCache', offlineCheckbox.checked); // storage.local.set('offlineCache', offlineCheckbox.checked);
storage.local.set('showAds', true); storage.local.set('showAds', true);
storage.local.set('mods', []); storage.local.set('mods', []);
storage.local.set('lastVersion', launcherVersion); storage.local.set('lastVersion', (await (await fetch('/resources/data/updates.json')).json())[0].version);
/* if (offlineCheckbox.checked) { /* if (offlineCheckbox.checked) {
serviceworker.register('/sw-full.js'); serviceworker.register('/sw-full.js');
@ -519,8 +501,8 @@ if (window.location.pathname === '/settings/') {
break; break;
} }
const mods = await (await fetch('/resources/data/mods.json')).json(); const modData = await (await fetch('/resources/data/mods.json')).json();
mods[modType].forEach((mod: { id: string; name: string; description: string; author: string; authorLink: string; source: string }) => { modData[modType].forEach((mod: { id: string; name: string; description: string; author: string; authorLink: string; source: string }) => {
const modItem = document.createElement('div'); const modItem = document.createElement('div');
modItem.classList.add('mod-item'); modItem.classList.add('mod-item');
modItem.innerHTML = `<div class="mod-icon"><img loading="lazy" src="/resources/mods/icons/${mod.id}.webp" /></div><div class="mod-details"><h3 class="mod-name">${mod.name}</h3><p class="mod-author">By <a href="${mod.authorLink}" target="_blank">${mod.author}</a></p><p class="mod-description">${mod.description}</p><div class="mod-links"><a href="${mod.source}" class="mod-link" target="_blank">Source</a><a href="/resources/mods/downloads/${mod.id}.${modExt}" class="mod-link" download>Download</a></div></div>`; modItem.innerHTML = `<div class="mod-icon"><img loading="lazy" src="/resources/mods/icons/${mod.id}.webp" /></div><div class="mod-details"><h3 class="mod-name">${mod.name}</h3><p class="mod-author">By <a href="${mod.authorLink}" target="_blank">${mod.author}</a></p><p class="mod-description">${mod.description}</p><div class="mod-links"><a href="${mod.source}" class="mod-link" target="_blank">Source</a><a href="/resources/mods/downloads/${mod.id}.${modExt}" class="mod-link" download>Download</a></div></div>`;
@ -532,9 +514,8 @@ if (window.location.pathname === '/settings/') {
} else if (window.location.pathname === '/updates/') { } else if (window.location.pathname === '/updates/') {
document.addEventListener('DOMContentLoaded', async () => { document.addEventListener('DOMContentLoaded', async () => {
const updatesContainer = document.getElementById('updates-container'); const updatesContainer = document.getElementById('updates-container');
const updates = await (await fetch('/resources/data/updates.json')).json(); const updateData: { version: string; changelog: string[] }[] = await (await fetch('/resources/data/updates.json')).json();
updateData.forEach((update) => {
updates.forEach((update: { version: string; changelog: string[] }) => {
const versionHeader = document.createElement('strong'); const versionHeader = document.createElement('strong');
versionHeader.textContent = `MineXLauncher ${update.version}`; versionHeader.textContent = `MineXLauncher ${update.version}`;
updatesContainer?.appendChild(versionHeader); updatesContainer?.appendChild(versionHeader);
@ -553,5 +534,5 @@ if (window.location.pathname === '/settings/') {
if (window.location.hostname === null) { if (window.location.hostname === null) {
// Stop the minifier from removing these functions // Stop the minifier from removing these functions
console.debug([navigate, cookie, query, versionSelector, game, mods]); console.debug([navigate, query, versionSelector, game, mods]);
} }

View File

@ -1,5 +1,5 @@
// @ts-nocheck // @ts-nocheck
const cacheVersion = '1.6.0'; const cacheVersion = '1.6';
const cacheName = `minexlauncher-full-v${cacheVersion}`; const cacheName = `minexlauncher-full-v${cacheVersion}`;
self.addEventListener('install', (event) => { self.addEventListener('install', (event) => {

View File

@ -1,8 +1,8 @@
// @ts-nocheck // @ts-nocheck
const cacheVersion = '1.6.0'; const cacheVersion = '1.6';
const cacheName = `minexlauncher-v${cacheVersion}`; const cacheName = `minexlauncher-v${cacheVersion}`;
const offlineUrl = '/offline.html'; const offlineUrl = '/offline.html';
const cacheAssets = [ const cacheAssets: string[] = [
offlineUrl, offlineUrl,
'/resources/images/icons/favicon.webp', '/resources/images/icons/favicon.webp',
'/resources/scripts/google-tag.js', '/resources/scripts/google-tag.js',
@ -35,7 +35,8 @@ self.addEventListener('install', (event) => {
for (const asset of cacheAssets) { for (const asset of cacheAssets) {
await cache.add(asset); await cache.add(asset);
const progress = `${++cachedAssets}/${totalAssets}`; ++cachedAssets;
const progress = `${cachedAssets.toString()}/${totalAssets.toString()}`;
console.log(`Cached: ${asset} (${progress})`); console.log(`Cached: ${asset} (${progress})`);
} }