aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2022-04-09 15:08:37 -0500
committermat <github@matdoes.dev>2022-04-09 15:08:37 -0500
commit312500edd00c44c0d28c78042ffb08de33ba3c90 (patch)
tree93041005f687f5ff4154ab30a24e7c5302a57abf
parentab3dcb36938c9da584bfcd2162dc02f999b50c8b (diff)
downloadskyblock-stats-312500edd00c44c0d28c78042ffb08de33ba3c90.tar.gz
skyblock-stats-312500edd00c44c0d28c78042ffb08de33ba3c90.tar.bz2
skyblock-stats-312500edd00c44c0d28c78042ffb08de33ba3c90.zip
Add coop section
-rw-r--r--src/lib/APITypes.d.ts7
-rw-r--r--src/lib/minecraft/Username.svelte21
-rw-r--r--src/lib/profile.ts9
-rw-r--r--src/lib/sections/Coop.svelte83
-rw-r--r--src/lib/sections/Infobox.svelte16
-rw-r--r--src/routes/player/[player]/[profile].svelte18
-rw-r--r--src/routes/player/[player]/index.svelte14
7 files changed, 128 insertions, 40 deletions
diff --git a/src/lib/APITypes.d.ts b/src/lib/APITypes.d.ts
index 2547669..bb0cd25 100644
--- a/src/lib/APITypes.d.ts
+++ b/src/lib/APITypes.d.ts
@@ -13,9 +13,7 @@ export interface CleanMemberProfilePlayer extends CleanPlayer {
lastSave: number | null
purse: number
stats: StatItem[]
- rawHypixelStats: {
- [key: string]: number
- }
+ rawHypixelStats: { [key: string]: number }
minions: CleanMinion[]
fairySouls: FairySouls
inventories?: Inventories
@@ -28,6 +26,7 @@ export interface CleanMemberProfilePlayer extends CleanPlayer {
harp: HarpData
coopInvitation: CoopInvitation | null
farmingContests: FarmingContests
+ left: boolean
}
export interface CleanMember extends CleanBasicMember {
@@ -343,7 +342,7 @@ export interface FarmingContests {
export interface CoopInvitation {
invitedTimestamp: number
- invitedByUuid: string
+ invitedBy: CleanPlayer | null
accepted: boolean
acceptedTimestamp: number | null
}
diff --git a/src/lib/minecraft/Username.svelte b/src/lib/minecraft/Username.svelte
index df9e093..6d45857 100644
--- a/src/lib/minecraft/Username.svelte
+++ b/src/lib/minecraft/Username.svelte
@@ -1,29 +1,24 @@
<script lang="ts">
+ import type { CleanPlayer, CleanBasicMember } from '$lib/APITypes'
+
import ConditionalLink from '$lib/ConditionalLink.svelte'
import Head2d from '$lib/minecraft/heads/Head2d.svelte'
import Head3d from '$lib/minecraft/heads/Head3d.svelte'
import { formattingCodeToHtml } from '../utils'
- export let player
+ export let player: CleanPlayer | CleanBasicMember
export let headType: null | '3d' | '2d' = null
- export let hyperlinkToProfile = false
+ export let hyperlinkToProfile: boolean | string = false
export let prefix = false
/** whether the username should be crossed out and the avatar grayscaled */
export let disabled = false
</script>
-<!-- {%- macro username(player, headType=none, hyperlinkToProfile=false, prefix=false) -%}
-{%- if hyperlinkToProfile %}<a href="/player/{{ player.username }}{% if hyperlinkToProfile|isString %}/{{ hyperlinkToProfile }}{% endif %}">{% endif -%}
-{%- if headType === '3d' %}{{ head3d(player, isPartOfUsername=true) -}}
-{%- elif headType === '2d' %}{{ head2d(player, isPartOfUsername=true) -}}
-{%- endif -%}
-{%- if prefix -%}<span class="username-rank-prefix">{{ player.rank.colored|formattingCodeToHtml|safe }} </span>{%- endif -%}
- <span class="username" style="color: {{ player.rank.color }}">{{ player.username }}</span>
-{%- if hyperlinkToProfile %}</a>{% endif -%}
-{%- endmacro -%} -->
-
-<ConditionalLink href="/player/{player.username}" isWrapped={hyperlinkToProfile}>
+<ConditionalLink
+ href="/player/{typeof hyperlinkToProfile === 'string' ? hyperlinkToProfile : player.username}"
+ isWrapped={!!hyperlinkToProfile}
+>
{#if headType == '3d'}
<span class="head" class:grayscale={disabled}><Head3d {player} isPartOfUsername={true} /></span
>{:else if headType == '2d'}
diff --git a/src/lib/profile.ts b/src/lib/profile.ts
index cba7923..ceeac77 100644
--- a/src/lib/profile.ts
+++ b/src/lib/profile.ts
@@ -14,9 +14,14 @@ export function prettyTimestamp(ms: number) {
export function generateInfobox(data: CleanMemberProfile): string[] {
const result: string[] = []
- result.push(`💾 Last save: ${prettyTimestamp(data.member.lastSave)}`)
+ if (data.member.left)
+ result.push(`🚪 Removed from profile`)
- result.push(`🚶 Profile created: ${prettyTimestamp(data.member.firstJoin)}`)
+ if (data.member.lastSave)
+ result.push(`💾 Last save: ${prettyTimestamp(data.member.lastSave)}`)
+
+ if (data.member.firstJoin)
+ result.push(`🚶 Profile created: ${prettyTimestamp(data.member.firstJoin)}`)
result.push(`✨ Fairy souls: ${data.member.fairySouls.total}/${data.member.fairySouls.max}`)
diff --git a/src/lib/sections/Coop.svelte b/src/lib/sections/Coop.svelte
new file mode 100644
index 0000000..867d878
--- /dev/null
+++ b/src/lib/sections/Coop.svelte
@@ -0,0 +1,83 @@
+<script lang="ts">
+ import type { CleanMemberProfile } from '$lib/APITypes'
+ import Username from '$lib/minecraft/Username.svelte'
+ import { millisecondsToTime } from '$lib/utils'
+ export let data: CleanMemberProfile
+
+ $: isProfileCreator = data.member.coopInvitation?.invitedBy?.uuid == data.member.uuid
+</script>
+
+{#if data.member.coopInvitation}
+ <div class="info-text primary-info-text">
+ {#if isProfileCreator}
+ <p><b class="info-text-value">Created co-op</b></p>
+ {:else}
+ <p>
+ Invited by {#if data.member.coopInvitation.invitedBy}
+ <Username player={data.member.coopInvitation.invitedBy} prefix />
+ {:else}
+ <b>Unknown player</b>
+ {/if}
+ </p>
+ {/if}
+ <p>
+ {isProfileCreator ? 'Began creation' : 'Invited'}:
+ <span class="info-text-value coop-invited-timeago">
+ <b>{millisecondsToTime(Date.now() - data.member.coopInvitation.invitedTimestamp)}</b> ago
+ </span>
+ </p>
+ {#if data.member.coopInvitation.acceptedTimestamp}
+ <p>
+ {isProfileCreator ? 'Finished creation' : 'Accepted invite'}:
+ <span class="info-text-value coop-accepted-invite-after">
+ after <b>
+ {millisecondsToTime(
+ data.member.coopInvitation.acceptedTimestamp -
+ data.member.coopInvitation.invitedTimestamp
+ )}
+ </b>
+ </span>
+ </p>
+ {/if}
+ </div>
+ <h3>Members</h3>
+ {#each data.profile.members.filter(m => !m.left) as player}
+ <span class="member">
+ <Username {player} headType="2d" hyperlinkToProfile />
+ </span>
+ {/each}
+ {#if data.profile.members.filter(m => m.left).length > 0}
+ <h3 class="previous-members-title">Previous members</h3>
+ {#each data.profile.members.filter(m => m.left) as player}
+ <span class="member">
+ <Username
+ {player}
+ headType="2d"
+ hyperlinkToProfile="{player.username}/{data.profile.uuid}"
+ />
+ </span>
+ {/each}
+ {/if}
+{/if}
+
+<style>
+ p {
+ margin: 0;
+ }
+ .primary-info-text {
+ margin: 0.5em 0;
+ }
+ .info-text {
+ color: var(--theme-darker-text);
+ }
+ .info-text .info-text-value {
+ color: var(--theme-main-text);
+ }
+
+ .member {
+ display: block;
+ }
+ .previous-members-title {
+ margin-top: 0.5rem;
+ }
+</style>
diff --git a/src/lib/sections/Infobox.svelte b/src/lib/sections/Infobox.svelte
index f454654..c524ca1 100644
--- a/src/lib/sections/Infobox.svelte
+++ b/src/lib/sections/Infobox.svelte
@@ -2,23 +2,17 @@
import { generateInfobox } from '$lib/profile'
import Username from '$lib/minecraft/Username.svelte'
import Emoji from '$lib/Emoji.svelte'
- import { onMount } from 'svelte'
export let data
-
- // onMount(() => {
- // // reload the data every second so the infobox updates
- // const interval = setInterval(() => {
- // data = data
- // }, 1000)
-
- // return () => clearInterval(interval)
- // })
</script>
<div id="infobox-container">
<div id="infobox">
- <h2><Username player={data.member} prefix /> ({data.member.profileName})</h2>
+ <h2>
+ <Username player={data.member} prefix /> ({data.member.left
+ ? 'Removed'
+ : data.member.profileName})
+ </h2>
{#each generateInfobox(data) as item}
<p><Emoji value={item} /></p>
{/each}
diff --git a/src/routes/player/[player]/[profile].svelte b/src/routes/player/[player]/[profile].svelte
index c55732c..1fee37c 100644
--- a/src/routes/player/[player]/[profile].svelte
+++ b/src/routes/player/[player]/[profile].svelte
@@ -52,6 +52,7 @@
import Claimed from '$lib/sections/Claimed.svelte'
import Pets from '$lib/sections/Pets.svelte'
import FarmingContests from '$lib/sections/FarmingContests.svelte'
+ import Coop from '$lib/sections/Coop.svelte'
export let data: CleanMemberProfile
export let pack: MatcherFile
@@ -75,6 +76,7 @@
if (data.member.claimed && data.member.claimed.length > 0) categories.push('claimed')
if (data.member.pets.list.length > 0) categories.push('pets')
if (data.member.farmingContests.list.length > 0) categories.push('farming_contests')
+ if (data.member.coopInvitation) categories.push('co-op')
categories.push('leaderboards')
}
@@ -82,6 +84,8 @@
$: backgroundUrl = data.customization?.backgroundUrl ?? chooseDefaultBackground(data.member.uuid)
$: showingInventories =
data.member.inventories?.inventory || data.member.inventories?.personal_vault
+
+ $: profileName = data.member.left ? 'Removed' : data.member.profileName
</script>
{#if backgroundUrl}
@@ -89,10 +93,10 @@
{/if}
<Head
- title="{data.member.username}'s SkyBlock profile ({data.member.profileName})"
+ title="{data.member.username}'s SkyBlock profile ({profileName})"
description={generateInfobox(data).join('\n')}
metaTitle={(data.member.rank.name ? `[${data.member.rank.name}] ` : '') +
- `${data.member.username}\'s SkyBlock profile (${data.member.profileName})`}
+ `${data.member.username}\'s SkyBlock profile (${profileName})`}
/>
<Header
backArrowHref="/player/{data.member.username}"
@@ -114,7 +118,7 @@
class="profile-emoji"><Emoji value={data.customization.emoji} /></span
>
{/if}
- ({data.member.profileName})
+ ({profileName})
</h1>
<Infobox {data} />
@@ -238,6 +242,14 @@
</Collapsible>
</section>
{/if}
+ {#if categories.includes('co-op')}
+ <section>
+ <Collapsible id="co-op">
+ <h2 slot="title">Co-op</h2>
+ <Coop {data} />
+ </Collapsible>
+ </section>
+ {/if}
<section>
<Collapsible id="leaderboards">
<h2 slot="title">Leaderboards</h2>
diff --git a/src/routes/player/[player]/index.svelte b/src/routes/player/[player]/index.svelte
index eda1998..ad02380 100644
--- a/src/routes/player/[player]/index.svelte
+++ b/src/routes/player/[player]/index.svelte
@@ -30,14 +30,14 @@
</script>
<script lang="ts">
- import type { CleanProfile, CleanUser } from '$lib/APITypes'
+ import type { CleanPlayer, CleanProfile, CleanUser } from '$lib/APITypes'
import BackgroundImage from '$lib/BackgroundImage.svelte'
import Username from '$lib/minecraft/Username.svelte'
import Header from '$lib/Header.svelte'
import Head from '$lib/Head.svelte'
import { chooseDefaultBackground } from '$lib/backgrounds'
- export let data: CleanUser
+ export let data: CleanUser & { player: CleanPlayer }
let activeProfile: CleanProfile | null = null
let activeProfileLastSave: number = 0
@@ -61,9 +61,7 @@
let backgroundUrl: string | null
$: {
- backgroundUrl =
- data.customization?.backgroundUrl ??
- (data.player ? chooseDefaultBackground(data.player.uuid) : null)
+ backgroundUrl = data.customization?.backgroundUrl ?? chooseDefaultBackground(data.player.uuid)
updateActiveProfile()
}
</script>
@@ -76,7 +74,9 @@
<Header />
<main>
- <h1><Username player={data.player} headType="3d" />'s profiles</h1>
+ <h1>
+ <Username player={data.player} headType="3d" />'s profiles
+ </h1>
<ul class="profile-list">
{#each data.profiles ?? [] as profile}
@@ -109,7 +109,7 @@
<Username
{player}
headType="2d"
- hyperlinkToProfile={player.uuid != data.player?.uuid}
+ hyperlinkToProfile="{player.username}/{profile.uuid}"
disabled
/>
</span>