Launcher: BlueMap view with player side panel, map actions, guild invitations

This commit is contained in:
Claude committed 2026-09-30 20:15:32 +00:00
1 parent 878827625a
commit e160ad8da3
10 files changed
+342 -7

No files matched your search

+36
View File
@@ -69,7 +69,24 @@
}
}
type Invite = { id: number; guild_id: string; guild_name: string; guild_tag: string; icon_url: string; inviter: string };
let invites = $state<Invite[]>([]);
async function loadInvites() {
try { invites = await invoke<Invite[]>('my_guild_invites'); } catch { invites = []; }
}
async function answerInvite(inv: Invite, accept: boolean) {
try {
await invoke('respond_guild_invite', { inviteId: inv.id, accept });
toast(accept ? `Welcome to ${inv.guild_name}!` : 'Invitation declined', 'ok');
await Promise.all([loadInvites(), loadInstanceGuildData()]);
} catch (e: any) {
toast(typeof e === 'string' ? e : e?.message ?? 'Could not answer the invitation', 'error');
loadInvites();
}
}
onMount(async () => {
loadInvites();
try { walletServers = (await invoke<{ servers: typeof walletServers }>('get_public_servers')).servers; }
catch { walletServers = []; }
});
@@ -169,6 +186,20 @@
</div>
</div>
{#if invites.length}
<section class="invites glass" aria-label="Guild invitations">
<h3>Guild invitations</h3>
{#each invites as inv (inv.id)}
<div class="invite">
<span class="dot"><Shield size={15} /></span>
<span class="text"><strong>[{inv.guild_tag}] {inv.guild_name}</strong><span class="muted tiny">Invited by {inv.inviter}</span></span>
<button class="sm ghost" onclick={() => answerInvite(inv, false)}>Decline</button>
<button class="sm primary" onclick={() => answerInvite(inv, true)} disabled={!!myGuild} title={myGuild ? 'Leave your guild first' : ''}>Accept</button>
</div>
{/each}
</section>
{/if}
{#if loading && !myGuild && !allGuilds.length}
<div class="center-state"><LoaderCircle class="spin" size={32} /></div>
{:else if myGuild}
@@ -416,6 +447,11 @@
</Modal>
<style>
.invites { display: flex; flex-direction: column; gap: 0.6rem; padding: 0.9rem 1.1rem; border-radius: var(--radius); border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--line)); }
.invites h3 { margin: 0; font-size: 0.95rem; }
.invite { display: flex; align-items: center; gap: 0.7rem; }
.invite .dot { width: 2rem; height: 2rem; display: grid; place-items: center; border-radius: 0.6rem; background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.invite .text { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.guilds-page {
height: 100%;
display: flex;