Move MC mod versions to a different page
This commit is contained in:
parent
82fc180afe
commit
8740bb8979
|
@ -1,9 +1,5 @@
|
|||
# MrMelon54.com Frontend
|
||||
|
||||
[![Build Status](https://ci.mrmelon54.com/api/badges/melon/summer-ui/status.svg)](https://ci.mrmelon54.com/melon/summer-ui)
|
||||
|
||||
UI for [Summer](https://code.mrmelon54.com/melon/summer)
|
||||
|
||||
## Building
|
||||
|
||||
```bash
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
export type ButtonData = {
|
||||
id: string;
|
||||
cfId: string;
|
||||
modrinth: string;
|
||||
curseforge: string;
|
||||
github: string;
|
||||
};
|
|
@ -0,0 +1,25 @@
|
|||
export interface McUploadItem {
|
||||
name: string;
|
||||
modrinth: McUploadItemPlatform;
|
||||
curseforge: McUploadItemPlatform;
|
||||
github: string;
|
||||
}
|
||||
|
||||
export interface McUploadItemPlatform {
|
||||
url: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface McUploadVersion {
|
||||
meta: {
|
||||
version: string;
|
||||
channel: string;
|
||||
game_versions: string[];
|
||||
loaders: string[];
|
||||
environment: string;
|
||||
};
|
||||
filename: string;
|
||||
sha512: string;
|
||||
modrinth_id: string;
|
||||
curseforge_id: string;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
export type Project = {
|
||||
id: number;
|
||||
key: string;
|
||||
title: string;
|
||||
description: string;
|
||||
url: string;
|
||||
group_id: number;
|
||||
activity: Activity;
|
||||
};
|
||||
|
||||
export type Activity = {
|
||||
id: number;
|
||||
key: string;
|
||||
title: string;
|
||||
description: string;
|
||||
value: number;
|
||||
project_id: number;
|
||||
status: string;
|
||||
};
|
|
@ -1,4 +1,8 @@
|
|||
<div class="center-screen-wrapper">
|
||||
<script lang="ts">
|
||||
export let noCenter = true;
|
||||
</script>
|
||||
|
||||
<div class="center-screen-wrapper" class:no-center={noCenter}>
|
||||
<div class="center-screen">
|
||||
<slot />
|
||||
</div>
|
||||
|
@ -13,6 +17,10 @@
|
|||
min-height: calc(100vh - 50px);
|
||||
box-sizing: border-box;
|
||||
|
||||
&.no-center {
|
||||
place-items: start;
|
||||
}
|
||||
|
||||
> .center-screen {
|
||||
max-width: min(100%, 2560px);
|
||||
margin: 0 auto;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<div id="app-router">
|
||||
<Header {isHome} />
|
||||
<main>
|
||||
<CenterScreen>
|
||||
<CenterScreen noCenter={!isHome}>
|
||||
<slot />
|
||||
</CenterScreen>
|
||||
</main>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import {navigate} from "vite-plugin-ssr/client/router";
|
||||
import MetaTags from "~/components/MetaTags.svelte";
|
||||
import Layout from "./__layout.svelte";
|
||||
import Layout from "~/pages/__layout.svelte";
|
||||
|
||||
export let __;
|
||||
export let pageProps;
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
display: flex;
|
||||
flex-direction: row;
|
||||
background: var(--bg-panel);
|
||||
border-radius: 16px;
|
||||
border-radius: 14px;
|
||||
-webkit-box-shadow: 0px 0px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
-moz-box-shadow: 0px 0px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: 0px 0px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
|
@ -77,7 +77,7 @@
|
|||
img {
|
||||
aspect-ratio: 1/1;
|
||||
width: 100%;
|
||||
border-radius: 16px;
|
||||
border-radius: calc(100% / 16);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,31 +1,19 @@
|
|||
<script lang="ts">
|
||||
import type {ModData, VersionData} from "~/api/modrinth";
|
||||
import type {Project} from "~/api/timeline";
|
||||
import type {ButtonData} from "~/api/button";
|
||||
import type {ModData} from "~/api/modrinth";
|
||||
import LazyComponent from "~/lib/LazyComponent.svelte";
|
||||
import ModrinthLogo from "~/icons/ModrinthLogo.svelte";
|
||||
import CurseforgeLogo from "~/icons/CurseforgeLogo.svelte";
|
||||
import GithubLogo from "~/icons/GithubLogo.svelte";
|
||||
import {modStore} from "~/stores/minecraft-cache";
|
||||
import MetaTags from "~/components/MetaTags.svelte";
|
||||
import Layout from "../__layout.svelte";
|
||||
import {onMount} from "svelte";
|
||||
import Layout from "~/pages/__layout.svelte";
|
||||
import type {McUploadItem} from "~/api/mc-upload";
|
||||
|
||||
export const props = ["project"];
|
||||
export let __;
|
||||
|
||||
let modData: ModData;
|
||||
let buttonData: ButtonData;
|
||||
let updateData: Promise<Project> = new Promise((res, rej) => {});
|
||||
let versionData: Promise<VersionData[]> = new Promise((res, rej) => {});
|
||||
|
||||
onMount(() => {
|
||||
updateData = new Promise((res, rej) => {
|
||||
fetch(`https://api.mrmelon54.com/v1/timeline/project/minecraft/${__.routeParams.project}`)
|
||||
.then(resp => res(resp.json()))
|
||||
.catch(err => rej(err));
|
||||
});
|
||||
});
|
||||
let buttonData: McUploadItem | null;
|
||||
|
||||
modStore.subscribe(x => {
|
||||
if (x instanceof Error) {
|
||||
|
@ -33,78 +21,12 @@
|
|||
buttonData = null;
|
||||
} else if (x) {
|
||||
modData = x.projectsSlugMap[__.routeParams.project];
|
||||
buttonData = modData ? x.modAlias[modData.id] : null;
|
||||
versionData = new Promise((res, rej) => {
|
||||
fetch(`https://api.modrinth.com/v2/versions?ids=${JSON.stringify(modData.versions)}`)
|
||||
.then(resp => res(resp.json()))
|
||||
.catch(err => rej(err));
|
||||
});
|
||||
buttonData = x.modAlias[__.routeParams.project];
|
||||
} else {
|
||||
modData = null;
|
||||
buttonData = null;
|
||||
}
|
||||
});
|
||||
|
||||
type Version = {type: "version"; value: number[]};
|
||||
|
||||
type Range = {type: "range"; min: number[]; max: number[]};
|
||||
|
||||
function parseVersion(a: string): Version {
|
||||
let v = a.split(".").map(x => parseInt(x));
|
||||
if (v.length == 2) v.push(0);
|
||||
return {type: "version", value: v};
|
||||
}
|
||||
|
||||
function mergeVersions(a: Version | Range, b: Version): Range {
|
||||
if (a.type === "version") {
|
||||
let z = [...a.value];
|
||||
z[z.length - 1]++;
|
||||
if (arrayEquals(z, b.value)) return {type: "range", min: a.value, max: b.value};
|
||||
} else if (a.type === "range") {
|
||||
let z = [...a.max];
|
||||
z[z.length - 1]++;
|
||||
if (arrayEquals(z, b.value)) return {type: "range", min: a.min, max: b.value};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function squashVersions(a: Version[]): Array<Version | Range> {
|
||||
if (a.length == 0) return [];
|
||||
let out: Array<Version | Range> = [];
|
||||
let z: Version | Range = a[0];
|
||||
for (let i = 1; i < a.length; i++) {
|
||||
let m = mergeVersions(z, a[i]);
|
||||
if (m == null) {
|
||||
out.push(z);
|
||||
z = a[i];
|
||||
} else {
|
||||
z = m;
|
||||
}
|
||||
}
|
||||
out.push(z);
|
||||
return out;
|
||||
}
|
||||
|
||||
function renderGameVersions(a: string[]) {
|
||||
let b = a.map(x => parseVersion(x));
|
||||
if (b.length == 0) return "";
|
||||
let squash = squashVersions(b);
|
||||
return squash.map(x => renderVersion(x)).join(", ");
|
||||
}
|
||||
|
||||
function renderVersion(a: Version | Range): string {
|
||||
if (a.type === "version") {
|
||||
if (a.value[a.value.length - 1] === 0) a.value.splice(a.value.length - 1, 1);
|
||||
return a.value.map(x => x.toString()).join(".");
|
||||
} else if (a.type === "range") {
|
||||
return renderVersion({type: "version", value: a.min}) + " - " + renderVersion({type: "version", value: a.max});
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
function arrayEquals(a, b) {
|
||||
return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((val, index) => val === b[index]);
|
||||
}
|
||||
</script>
|
||||
|
||||
<MetaTags
|
||||
|
@ -119,10 +41,6 @@
|
|||
<div class="mod-meta">
|
||||
<img class="title-img" src={modData.icon_url} alt={modData.title} />
|
||||
<h1 class="title-text">{modData.title}</h1>
|
||||
<div class="platform-text">
|
||||
<div>Modrinth ID: {buttonData.id}</div>
|
||||
<div>CurseForge ID: {buttonData.cfId}</div>
|
||||
</div>
|
||||
{#if buttonData}
|
||||
<div class="link-buttons">
|
||||
<a href={buttonData.github} class="brand-button-wrapper" rel="noreferrer" target="_blank">
|
||||
|
@ -131,52 +49,30 @@
|
|||
<span>Source Code</span>
|
||||
</div>
|
||||
</a>
|
||||
<a href={buttonData.modrinth} class="brand-button-wrapper" rel="noreferrer" target="_blank">
|
||||
<div class="brand-button button-modrinth">
|
||||
<ModrinthLogo />
|
||||
<span>Modrinth</span>
|
||||
</div>
|
||||
</a>
|
||||
<a href={buttonData.curseforge} class="brand-button-wrapper" rel="noreferrer" target="_blank">
|
||||
<div class="brand-button button-curseforge">
|
||||
<CurseforgeLogo />
|
||||
<span>CurseForge</span>
|
||||
</div>
|
||||
</a>
|
||||
{#if buttonData.modrinth}
|
||||
<a href={buttonData.modrinth.url} class="brand-button-wrapper" rel="noreferrer" target="_blank">
|
||||
<div class="brand-button button-modrinth">
|
||||
<ModrinthLogo />
|
||||
<span>Modrinth</span>
|
||||
</div>
|
||||
</a>
|
||||
{/if}
|
||||
{#if buttonData.curseforge}
|
||||
<a href={buttonData.curseforge.url} class="brand-button-wrapper" rel="noreferrer" target="_blank">
|
||||
<div class="brand-button button-curseforge">
|
||||
<CurseforgeLogo />
|
||||
<span>CurseForge</span>
|
||||
</div>
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="buttons-loading" />
|
||||
{/if}
|
||||
<div class="game-versions">
|
||||
{#await versionData then w}
|
||||
{#each w as v, i}
|
||||
<a class="version-pill" rel="noreferrer" target="_blank" href="https://modrinth.com/mod/{modData.slug}/version/{v.id}">
|
||||
<span>{renderGameVersions(v.game_versions)}</span>
|
||||
</a>
|
||||
{/each}
|
||||
{:catch}
|
||||
<div data-text="No version data" />
|
||||
{/await}
|
||||
</div>
|
||||
{#await updateData}
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-infinite" />
|
||||
</div>
|
||||
{:then w}
|
||||
<div class="progress">
|
||||
<div class="progress-title"><h2>Progress: {w.activity.title} (<span class="progress-status">{w.activity.status}</span>)</h2></div>
|
||||
<div class="progress-details">
|
||||
<p class="progress-text">{w.activity.description}</p>
|
||||
</div>
|
||||
<div class="progress-bar">
|
||||
<div class="progress-bar-done" style="width: {w.activity.value}%;">
|
||||
<span class="progress-bar-text">{w.activity.value + "%"}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{:catch}
|
||||
<div data-text="No update data" />
|
||||
{/await}
|
||||
</div>
|
||||
<div class="body-tabs">
|
||||
<a href="/minecraft/{__.routeParams.project}" class="selected">Description</a>
|
||||
<a href="/minecraft/{__.routeParams.project}/versions">Versions</a>
|
||||
</div>
|
||||
<div class="body-text">
|
||||
<LazyComponent component={() => import("~/components/Markdown.svelte")} delayMs={500} source={modData.body}>Loading...</LazyComponent>
|
||||
|
@ -193,7 +89,7 @@
|
|||
.title-img {
|
||||
width: max(25%, 100px);
|
||||
aspect-ratio: 1/1;
|
||||
border-radius: 32px;
|
||||
border-radius: calc(100% / 16);
|
||||
margin-bottom: 32px;
|
||||
-webkit-box-shadow: 0px 0px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
-moz-box-shadow: 0px 0px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
|
@ -209,42 +105,17 @@
|
|||
.platform-text {
|
||||
margin: 0 0 16px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin-bottom: 32px;
|
||||
.body-tabs {
|
||||
display: flex;
|
||||
margin-bottom: 32px;
|
||||
|
||||
> .progress-bar {
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
border-radius: 24px;
|
||||
background-color: var(--bg-panel);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
-webkit-box-shadow: 0px 0px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
-moz-box-shadow: 0px 0px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: 0px 0px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
> a {
|
||||
padding: 16px;
|
||||
|
||||
> .progress-bar-done {
|
||||
transform: translateX(-100%);
|
||||
-webkit-animation: loadBar 1s forwards;
|
||||
animation: loadBar 1s forwards;
|
||||
height: 100%;
|
||||
background-color: var(--primary-main);
|
||||
|
||||
@keyframes loadBar {
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
> .progress-bar-text {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 10px;
|
||||
transform: translateY(-50%);
|
||||
font-family: monospace;
|
||||
}
|
||||
}
|
||||
&.selected {
|
||||
border-bottom: 3px solid var(--primary-main);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -262,18 +133,4 @@
|
|||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.game-versions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
margin-bottom: 32px;
|
||||
|
||||
.version-pill {
|
||||
background: var(--primary-main);
|
||||
padding: 6px 12px;
|
||||
border-radius: 0.5rem;
|
||||
color: var(--primary-text);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,252 @@
|
|||
<script lang="ts">
|
||||
import type {ModData} from "~/api/modrinth";
|
||||
import ModrinthLogo from "~/icons/ModrinthLogo.svelte";
|
||||
import CurseforgeLogo from "~/icons/CurseforgeLogo.svelte";
|
||||
import GithubLogo from "~/icons/GithubLogo.svelte";
|
||||
import {modStore} from "~/stores/minecraft-cache";
|
||||
import MetaTags from "~/components/MetaTags.svelte";
|
||||
import Layout from "~/pages/__layout.svelte";
|
||||
import type {McUploadItem, McUploadVersion} from "~/api/mc-upload";
|
||||
|
||||
export const props = ["project"];
|
||||
export let __;
|
||||
|
||||
let modData: ModData;
|
||||
let buttonData: McUploadItem | null;
|
||||
let versionData: Promise<McUploadVersion[]> = new Promise(() => {});
|
||||
|
||||
modStore.subscribe(x => {
|
||||
if (x instanceof Error) {
|
||||
modData = null;
|
||||
buttonData = null;
|
||||
} else if (x) {
|
||||
modData = x.projectsSlugMap[__.routeParams.project];
|
||||
buttonData = x.modAlias[__.routeParams.project];
|
||||
versionData = new Promise((res, rej) => {
|
||||
fetch(`https://api.mrmelon54.com/v1/mc-upload/mod/${__.routeParams.project}/versions`)
|
||||
.then(resp => res(resp.json()))
|
||||
.catch(err => rej(err));
|
||||
});
|
||||
} else {
|
||||
modData = null;
|
||||
buttonData = null;
|
||||
}
|
||||
});
|
||||
|
||||
type Version = {type: "version"; value: number[]};
|
||||
|
||||
type Range = {type: "range"; min: number[]; max: number[]};
|
||||
|
||||
function parseVersion(a: string): Version {
|
||||
let v = a.split(".").map(x => parseInt(x));
|
||||
if (v.length == 2) v.push(0);
|
||||
return {type: "version", value: v};
|
||||
}
|
||||
|
||||
function mergeVersions(a: Version | Range, b: Version): Range {
|
||||
if (a.type === "version") {
|
||||
let z = [...a.value];
|
||||
z[z.length - 1]++;
|
||||
if (arrayEquals(z, b.value)) return {type: "range", min: a.value, max: b.value};
|
||||
} else if (a.type === "range") {
|
||||
let z = [...a.max];
|
||||
z[z.length - 1]++;
|
||||
if (arrayEquals(z, b.value)) return {type: "range", min: a.min, max: b.value};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function squashVersions(a: Version[]): Array<Version | Range> {
|
||||
if (a.length == 0) return [];
|
||||
let out: Array<Version | Range> = [];
|
||||
let z: Version | Range = a[0];
|
||||
for (let i = 1; i < a.length; i++) {
|
||||
let m = mergeVersions(z, a[i]);
|
||||
if (m == null) {
|
||||
out.push(z);
|
||||
z = a[i];
|
||||
} else {
|
||||
z = m;
|
||||
}
|
||||
}
|
||||
out.push(z);
|
||||
return out;
|
||||
}
|
||||
|
||||
function renderGameVersions(a: string[]) {
|
||||
let b = a.map(x => parseVersion(x));
|
||||
if (b.length == 0) return "";
|
||||
b = b.sort((a, b) => {
|
||||
if (a.value[0] != b.value[0]) return a.value[0] - b.value[0];
|
||||
if (a.value[1] != b.value[1]) return a.value[1] - b.value[1];
|
||||
if (a.value[2] != b.value[2]) return a.value[2] - b.value[2];
|
||||
return 0;
|
||||
});
|
||||
let squash = squashVersions(b);
|
||||
return squash.map(x => renderVersion(x)).join(", ");
|
||||
}
|
||||
|
||||
function renderVersion(a: Version | Range): string {
|
||||
if (a.type === "version") {
|
||||
if (a.value[a.value.length - 1] === 0) a.value.splice(a.value.length - 1, 1);
|
||||
return a.value.map(x => x.toString()).join(".");
|
||||
} else if (a.type === "range") {
|
||||
return renderVersion({type: "version", value: a.min}) + " - " + renderVersion({type: "version", value: a.max});
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
function arrayEquals(a, b) {
|
||||
return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((val, index) => val === b[index]);
|
||||
}
|
||||
</script>
|
||||
|
||||
<MetaTags
|
||||
url={__.urlOriginal}
|
||||
title={(modData ? `${modData.title} Versions | ` : "") + "Minecraft | MrMelon54"}
|
||||
description=""
|
||||
keywords="minecraft,minecraft mod,{__.routeParams.project}"
|
||||
/>
|
||||
|
||||
<Layout>
|
||||
{#if modData}
|
||||
<div class="mod-meta">
|
||||
<img class="title-img" src={modData.icon_url} alt={modData.title} />
|
||||
<h1 class="title-text">{modData.title}</h1>
|
||||
{#if buttonData}
|
||||
<div class="link-buttons">
|
||||
<a href={buttonData.github} class="brand-button-wrapper" rel="noreferrer" target="_blank">
|
||||
<div class="brand-button button-github">
|
||||
<GithubLogo />
|
||||
<span>Source Code</span>
|
||||
</div>
|
||||
</a>
|
||||
{#if buttonData.modrinth}
|
||||
<a href={buttonData.modrinth.url} class="brand-button-wrapper" rel="noreferrer" target="_blank">
|
||||
<div class="brand-button button-modrinth">
|
||||
<ModrinthLogo />
|
||||
<span>Modrinth</span>
|
||||
</div>
|
||||
</a>
|
||||
{/if}
|
||||
{#if buttonData.curseforge}
|
||||
<a href={buttonData.curseforge.url} class="brand-button-wrapper" rel="noreferrer" target="_blank">
|
||||
<div class="brand-button button-curseforge">
|
||||
<CurseforgeLogo />
|
||||
<span>CurseForge</span>
|
||||
</div>
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="buttons-loading" />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="body-tabs">
|
||||
<a href="/minecraft/{__.routeParams.project}">Description</a>
|
||||
<a href="/minecraft/{__.routeParams.project}/versions" class="selected">Versions</a>
|
||||
</div>
|
||||
<div class="game-versions">
|
||||
{#await versionData then w}
|
||||
<table>
|
||||
{#each w.filter(x => x.modrinth_id != "" || x.curseforge_id != "").reverse() as v}
|
||||
<tr>
|
||||
<th>{v.meta.version}</th>
|
||||
<td>{renderGameVersions(v.meta.game_versions)}</td>
|
||||
<td>
|
||||
{#if v.modrinth_id != ""}
|
||||
<a class="version-pill mr-dl" rel="noreferrer" target="_blank" href="{buttonData.modrinth.url}/version/{v.modrinth_id}">
|
||||
<span>Modrinth</span>
|
||||
</a>
|
||||
{/if}
|
||||
</td>
|
||||
<td>
|
||||
{#if v.curseforge_id != ""}
|
||||
<a class="version-pill cf-dl" rel="noreferrer" target="_blank" href="{buttonData.curseforge.url}/files/{v.curseforge_id}">
|
||||
<span>Curseforge</span>
|
||||
</a>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</table>
|
||||
{:catch}
|
||||
<div data-text="No version data" />
|
||||
{/await}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="projects-loading" />
|
||||
{/if}
|
||||
</Layout>
|
||||
|
||||
<style lang="scss">
|
||||
@import "../../../styles/link-buttons.scss";
|
||||
|
||||
.mod-meta {
|
||||
.title-img {
|
||||
width: max(25%, 100px);
|
||||
aspect-ratio: 1/1;
|
||||
border-radius: calc(100% / 16);
|
||||
margin-bottom: 32px;
|
||||
-webkit-box-shadow: 0px 0px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
-moz-box-shadow: 0px 0px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: 0px 0px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.title-text {
|
||||
margin: 0 0 16px 0;
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.platform-text {
|
||||
margin: 0 0 16px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.body-tabs {
|
||||
display: flex;
|
||||
margin-bottom: 32px;
|
||||
|
||||
> a {
|
||||
padding: 16px;
|
||||
|
||||
&.selected {
|
||||
border-bottom: 3px solid var(--primary-main);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.game-versions {
|
||||
display: flex;
|
||||
margin-bottom: 32px;
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
tr:nth-child(2n) {
|
||||
background-color: var(--bg-panel);
|
||||
}
|
||||
}
|
||||
|
||||
.version-pill {
|
||||
padding: 6px 12px;
|
||||
border-radius: 0.5rem;
|
||||
color: var(--primary-text);
|
||||
|
||||
&.mr-dl {
|
||||
background: green;
|
||||
}
|
||||
|
||||
&.cf-dl {
|
||||
background: orangered;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,28 +1,23 @@
|
|||
import {writable} from "svelte/store";
|
||||
import {PromiseAllUnique} from "~/utils/promise-all-unique";
|
||||
import type {ModData} from "~/api/modrinth";
|
||||
import type { McUploadItem } from "~/api/mc-upload";
|
||||
|
||||
export interface ModStore {
|
||||
projects: ModData[];
|
||||
projectsIdMap: Map<string, ModData>;
|
||||
projectsSlugMap: Map<string, ModData>;
|
||||
modAlias: Map<string, ModStoreItem>;
|
||||
modAlias: Map<string, McUploadItem>;
|
||||
}
|
||||
|
||||
export interface ModStoreItem {
|
||||
id: string;
|
||||
github: string;
|
||||
modrinth: string;
|
||||
cfId: string;
|
||||
curseforge: string;
|
||||
}
|
||||
|
||||
|
||||
export const modStore = writable<ModStore | Error | null>(
|
||||
(() => {
|
||||
(() => {
|
||||
PromiseAllUnique([
|
||||
fetch("https://api.modrinth.com/v2/user/mrmelon54/projects").then(resp => resp.json()),
|
||||
fetch("https://cdn.mrmelon54.com/assets/minecraft/mods.json").then(resp => resp.json()),
|
||||
fetch("https://api.mrmelon54.com/v1/mc-upload/summary").then(resp => resp.json()),
|
||||
])
|
||||
.then(([projects, modAlias]) => {
|
||||
let projectsIdMap: Map<string, ModData> = new Map();
|
||||
|
|
Loading…
Reference in New Issue