Allow for logos to be used as instance names

This commit is contained in:
SCOPEDD committed 2026-09-29 01:58:53 -04:00
1 parent a1f19e86c6
commit 522e3a5717
10 files changed
+36 -8

No files matched your search

+1
View File
@@ -332,6 +332,7 @@ pub struct InstanceSummary {
pub description: String,
pub icon_url: Option<String>,
pub banner_url: Option<String>,
pub logo_url: Option<String>,
pub mc_version: String,
pub loader: Loader,
pub loader_version: Option<String>,
+3 -3
View File
@@ -63,9 +63,9 @@ const manifest: Manifest = {
custom_css: '',
},
instances: [
{ id: 'survival-smp', name: 'Survival SMP', description: 'Our main survival world — season 4. Claims, shops & weekend events.', icon_url: null, banner_url: null, mc_version: '1.21.1', loader: 'fabric', loader_version: '0.16.9', revision: 3, server: { name: 'SCOPENET SMP', address: 'play.scopenet.gg', port: 25565, auto_join: true, inject: true }, memory: { min_mb: 2048, max_mb: 6144 }, jvm_args: '', featured: true, source_label: 'Modrinth · Fabulously Optimized 6.2', file_count: 48, total_size: 184_000_000 },
{ id: 'creative', name: 'Creative Build', description: 'Plots, WorldEdit and weekly build contests.', icon_url: null, banner_url: null, mc_version: '1.20.1', loader: 'vanilla', loader_version: null, revision: 1, server: { name: 'Creative', address: 'creative.scopenet.gg', port: 25565, auto_join: false, inject: true }, memory: { min_mb: 1024, max_mb: 4096 }, jvm_args: '', featured: false, source_label: 'Minecraft 1.20.1', file_count: 0, total_size: 0 },
{ id: 'modded', name: 'Create: Above & Beyond', description: 'Factory building with Create and friends.', icon_url: null, banner_url: null, mc_version: '1.20.1', loader: 'forge', loader_version: '1.20.1-47.3.0', revision: 2, server: null, memory: { min_mb: 4096, max_mb: 8192 }, jvm_args: '', featured: false, source_label: 'CurseForge · Create: Above & Beyond 1.4', file_count: 212, total_size: 612_000_000 },
{ id: 'survival-smp', name: 'Survival SMP', description: 'Our main survival world — season 4. Claims, shops & weekend events.', icon_url: null, banner_url: null, logo_url: null, mc_version: '1.21.1', loader: 'fabric', loader_version: '0.16.9', revision: 3, server: { name: 'SCOPENET SMP', address: 'play.scopenet.gg', port: 25565, auto_join: true, inject: true }, memory: { min_mb: 2048, max_mb: 6144 }, jvm_args: '', featured: true, source_label: 'Modrinth · Fabulously Optimized 6.2', file_count: 48, total_size: 184_000_000 },
{ id: 'creative', name: 'Creative Build', description: 'Plots, WorldEdit and weekly build contests.', icon_url: null, banner_url: null, logo_url: null, mc_version: '1.20.1', loader: 'vanilla', loader_version: null, revision: 1, server: { name: 'Creative', address: 'creative.scopenet.gg', port: 25565, auto_join: false, inject: true }, memory: { min_mb: 1024, max_mb: 4096 }, jvm_args: '', featured: false, source_label: 'Minecraft 1.20.1', file_count: 0, total_size: 0 },
{ id: 'modded', name: 'Create: Above & Beyond', description: 'Factory building with Create and friends.', icon_url: null, banner_url: null, logo_url: null, mc_version: '1.20.1', loader: 'forge', loader_version: '1.20.1-47.3.0', revision: 2, server: null, memory: { min_mb: 4096, max_mb: 8192 }, jvm_args: '', featured: false, source_label: 'CurseForge · Create: Above & Beyond 1.4', file_count: 212, total_size: 612_000_000 },
],
};
+1
View File
@@ -8,6 +8,7 @@ export interface Instance {
description: string;
icon_url: string | null;
banner_url: string | null;
logo_url: string | null;
mc_version: string;
loader: Loader;
loader_version: string | null;
+9 -1
View File
@@ -4,7 +4,7 @@
import ServerStatus from '../components/ServerStatus.svelte';
import NewsFeed from '../components/NewsFeed.svelte';
import Console from '../components/Console.svelte';
import { activeAccount, app, instances, selectedInstance } from '../lib/store.svelte';
import { abs, activeAccount, app, instances, selectedInstance } from '../lib/store.svelte';
import { loaderName, shortLoaderVersion } from '../lib/format';
import { openUrl } from '../lib/tauri';
@@ -26,7 +26,13 @@
<span class="chip">{loaderName[inst.loader]} {shortLoaderVersion(inst.mc_version, inst.loader_version)}</span>
{#if inst.file_count}<span class="chip"><Package size={12} /> {inst.file_count} mods & files</span>{/if}
</div>
{#if inst.logo_url}
<div class="logo-wrap">
<img class="inst-logo" src={abs(inst.logo_url)} alt={inst.name} />
</div>
{:else}
<h1>{inst.name}</h1>
{/if}
<p class="desc">{inst.description || b.tagline}</p>
</section>
@@ -67,6 +73,8 @@
.greet { font-size: 0.88rem; }
.greet strong { color: var(--text); font-weight: 560; }
.chips { display: flex; gap: 0.45rem; flex-wrap: wrap; }
.logo-wrap { max-width: 100%; display: flex; align-items: flex-end; min-height: 3rem; margin: 0.25rem 0; }
.inst-logo { max-height: clamp(3.8rem, 8vw, 6.2rem); max-width: min(100%, 30rem); object-fit: contain; object-position: left bottom; filter: drop-shadow(0 4px 16px rgba(0, 0, 0, 0.5)); }
h1 { font-size: clamp(2.2rem, 4.4vw, 3.2rem); line-height: 1.05; font-weight: 700; letter-spacing: -0.025em; }
.desc { font-size: 0.95rem; line-height: 1.6; color: var(--muted); max-width: 32rem; }
.actions { grid-column: 1; grid-row: 2; display: flex; flex-direction: column; gap: 0.8rem; animation: fade 0.3s ease both; }
+4
View File
@@ -215,6 +215,10 @@ const MIGRATIONS: &[&str] = &[
WHEN NEW.uuid <> ''
BEGIN INSERT OR IGNORE INTO reserved_usernames VALUES (NEW.username, NEW.uuid); END;
"#,
// 5: instance logo url.
r#"
ALTER TABLE instances ADD COLUMN logo_url TEXT;
"#,
];
pub async fn connect(data_dir: &Path) -> Result<SqlitePool> {
+6 -3
View File
@@ -349,6 +349,7 @@ pub struct InstanceInput {
description: String,
icon_url: Option<String>,
banner_url: Option<String>,
logo_url: Option<String>,
mc_version: String,
loader: Loader,
loader_version: Option<String>,
@@ -403,15 +404,16 @@ pub async fn create_instance(
let now = crate::db::now();
let mem = input.memory.unwrap_or_default();
sqlx::query(
"INSERT INTO instances (id, name, description, icon_url, banner_url, mc_version, loader, loader_version, source_kind, source_label,
"INSERT INTO instances (id, name, description, icon_url, banner_url, logo_url, mc_version, loader, loader_version, source_kind, source_label,
visibility, allowed_groups, memory_min, memory_max, jvm_args, server, featured, enabled, sort, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'vanilla', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'vanilla', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
)
.bind(&id)
.bind(&input.name)
.bind(&input.description)
.bind(&input.icon_url)
.bind(&input.banner_url)
.bind(&input.logo_url)
.bind(&input.mc_version)
.bind(input.loader.as_str())
.bind(&input.loader_version)
@@ -461,7 +463,7 @@ pub async fn update_instance(
// admin explicitly changes them here.
let label = if existing.source_kind == "vanilla" { format!("Minecraft {}", input.mc_version) } else { existing.source_label.clone() };
sqlx::query(
"UPDATE instances SET name = ?, description = ?, icon_url = ?, banner_url = ?, mc_version = ?, loader = ?, loader_version = ?,
"UPDATE instances SET name = ?, description = ?, icon_url = ?, banner_url = ?, logo_url = ?, mc_version = ?, loader = ?, loader_version = ?,
source_label = ?, visibility = ?, allowed_groups = ?, memory_min = ?, memory_max = ?, jvm_args = ?, server = ?, featured = ?,
enabled = ?, sort = ?, revision = revision + 1, updated_at = ? WHERE id = ?",
)
@@ -469,6 +471,7 @@ pub async fn update_instance(
.bind(&input.description)
.bind(input.icon_url.filter(|s| !s.is_empty()))
.bind(input.banner_url.filter(|s| !s.is_empty()))
.bind(input.logo_url.filter(|s| !s.is_empty()))
.bind(&input.mc_version)
.bind(input.loader.as_str())
.bind(&input.loader_version)
+4
View File
@@ -63,6 +63,7 @@ pub struct InstanceRow {
pub description: String,
pub icon_url: Option<String>,
pub banner_url: Option<String>,
pub logo_url: Option<String>,
pub mc_version: String,
pub loader: String,
pub loader_version: Option<String>,
@@ -92,6 +93,7 @@ pub struct AdminInstance {
pub description: String,
pub icon_url: Option<String>,
pub banner_url: Option<String>,
pub logo_url: Option<String>,
pub mc_version: String,
pub loader: Loader,
pub loader_version: Option<String>,
@@ -123,6 +125,7 @@ impl InstanceRow {
description: self.description.clone(),
icon_url: self.icon_url.clone(),
banner_url: self.banner_url.clone(),
logo_url: self.logo_url.clone(),
mc_version: self.mc_version.clone(),
loader: Loader::parse(&self.loader).unwrap_or_default(),
loader_version: self.loader_version.clone(),
@@ -154,6 +157,7 @@ impl InstanceRow {
description: a.description,
icon_url: a.icon_url,
banner_url: a.banner_url,
logo_url: a.logo_url,
mc_version: a.mc_version,
loader: a.loader,
loader_version: a.loader_version,
@@ -4,7 +4,7 @@
import { Play, Settings } from '@lucide/svelte';
import type { Branding } from '../lib/types';
let { b, instanceName = 'Survival SMP' }: { b: Branding; instanceName?: string } = $props();
let { b, instanceName = 'Survival SMP', instanceLogo = null }: { b: Branding; instanceName?: string; instanceLogo?: string | null } = $props();
const fontFamily = $derived(`'${b.font} Variable', '${b.font}', 'Inter Variable', sans-serif`);
const media = $derived(b.background.kind !== 'gradient' && b.background.url ? b.background.url : null);
@@ -53,7 +53,11 @@
<div class="main">
<div class="hero">
<div class="chips"><span>1.21.1</span><span>Fabric</span></div>
{#if instanceLogo}
<img class="hero-logo" src={instanceLogo} alt={instanceName} />
{:else}
<h1>{instanceName}</h1>
{/if}
<p>{b.tagline}</p>
<div class="row">
<span class="play"><Play size={9} fill="currentColor" /> Play</span>
@@ -103,6 +107,7 @@
.avatar { width: 55%; aspect-ratio: 1; border-radius: 25%; background: #3fb97c; }
.main { position: absolute; left: 6.2%; top: 5.6%; right: 0; bottom: 0; padding: 4% 4%; z-index: 1; display: flex; gap: 6%; }
.hero { flex: 1; align-self: flex-end; display: flex; flex-direction: column; gap: 0.6em; }
.hero-logo { max-height: 2.8em; max-width: 80%; object-fit: contain; object-position: left bottom; }
.hero h1 { font-size: 3.1em; line-height: 1.05; margin: 0; letter-spacing: -0.025em; font-weight: 700; }
.hero p { color: var(--mut); font-size: 0.95em; margin: 0; }
.chips { display: flex; gap: 0.4em; }
+1
View File
@@ -7,6 +7,7 @@ export interface Instance {
description: string;
icon_url: string | null;
banner_url: string | null;
logo_url: string | null;
mc_version: string;
loader: string;
loader_version: string | null;
@@ -251,6 +251,7 @@
<label class="field">Name<input bind:value={form.name} /></label>
<label class="field">Description<textarea bind:value={form.description} rows="3" placeholder="What makes this instance special?"></textarea></label>
<ImageInput bind:value={form.icon_url} label="Icon" help="Square image, shown in the launcher sidebar." />
<ImageInput bind:value={form.logo_url} label="Logo (optional)" help="Wide logo or wordmark image used in place of the instance title text." />
<ImageInput bind:value={form.banner_url} label="Banner / background" help="Wide image shown behind this instance. Overrides the launcher background." />
</section>
<section class="card col">