feat(live-state): use Steam avatarfull (184x184), downscale in CSS
64x64 avatarmedium looked soft on high-DPI screens. Switching the GetPlayerSummaries field to avatarfull (184x184) and constraining display size to 64px via .live-state .avatar gives sharp rendering on retina/4k panels at the cost of a slightly larger CDN fetch (still hot-linked, so no proxying cost). Also adds the previously-missing CSS for the live-state player grid: avatar+name+meta arranged in a tight 2-column grid per card, link spans the avatar+name so the meta stays non-interactive. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6cbe7dc9f2
commit
096d18ac64
3 changed files with 63 additions and 5 deletions
|
|
@ -44,7 +44,7 @@ def _session_get(url: str, params: dict, timeout: float = REQUEST_TIMEOUT_SECOND
|
||||||
class SteamProfile:
|
class SteamProfile:
|
||||||
steam_id_64: str
|
steam_id_64: str
|
||||||
persona_name: str
|
persona_name: str
|
||||||
avatar_url: str
|
avatar_url: str # avatarfull (184x184); CSS downscales so high-DPI stays crisp
|
||||||
|
|
||||||
|
|
||||||
def fetch_profiles_batch(
|
def fetch_profiles_batch(
|
||||||
|
|
@ -70,7 +70,7 @@ def fetch_profiles_batch(
|
||||||
SteamProfile(
|
SteamProfile(
|
||||||
steam_id_64=str(p["steamid"]),
|
steam_id_64=str(p["steamid"]),
|
||||||
persona_name=str(p.get("personaname", "")),
|
persona_name=str(p.get("personaname", "")),
|
||||||
avatar_url=str(p.get("avatarmedium", "")),
|
avatar_url=str(p.get("avatarfull", "")),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return out
|
return out
|
||||||
|
|
|
||||||
|
|
@ -854,3 +854,61 @@ dialog.modal.modal-wide {
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
color: var(--color-muted);
|
color: var(--color-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Live-state panel — current + recent players on the server detail page.
|
||||||
|
Avatars are fetched as the 184x184 Steam "full" size and downscaled in
|
||||||
|
CSS so high-DPI screens render crisply. */
|
||||||
|
|
||||||
|
.live-state .player-grid {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: var(--space-m) 0 0;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: var(--space-m);
|
||||||
|
}
|
||||||
|
|
||||||
|
.live-state .player-card {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
column-gap: var(--space-s);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.live-state .player-link {
|
||||||
|
display: contents;
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.live-state .player-link:hover .name {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.live-state .avatar {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
border-radius: var(--radius-s);
|
||||||
|
object-fit: cover;
|
||||||
|
grid-row: 1 / span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.live-state .avatar.placeholder {
|
||||||
|
display: inline-block;
|
||||||
|
background: color-mix(in srgb, var(--color-muted) 30%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.live-state .name {
|
||||||
|
grid-column: 2;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.live-state .meta {
|
||||||
|
grid-column: 2;
|
||||||
|
color: var(--color-muted);
|
||||||
|
font-size: 0.85em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.live-state .server-live-summary {
|
||||||
|
font-size: 1.05em;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ def test_fetch_profiles_batch_builds_correct_request(monkeypatch: pytest.MonkeyP
|
||||||
captured: list = []
|
captured: list = []
|
||||||
body = {"response": {"players": [
|
body = {"response": {"players": [
|
||||||
{"steamid": "76561197960828710", "personaname": "Alice",
|
{"steamid": "76561197960828710", "personaname": "Alice",
|
||||||
"avatarmedium": "https://avatars.../alice_medium.jpg"},
|
"avatarfull": "https://avatars.../alice_full.jpg"},
|
||||||
]}}
|
]}}
|
||||||
_patched_get(monkeypatch, body, captured)
|
_patched_get(monkeypatch, body, captured)
|
||||||
|
|
||||||
|
|
@ -47,7 +47,7 @@ def test_fetch_profiles_batch_builds_correct_request(monkeypatch: pytest.MonkeyP
|
||||||
p = profiles[0]
|
p = profiles[0]
|
||||||
assert p.steam_id_64 == "76561197960828710"
|
assert p.steam_id_64 == "76561197960828710"
|
||||||
assert p.persona_name == "Alice"
|
assert p.persona_name == "Alice"
|
||||||
assert p.avatar_url.endswith("alice_medium.jpg")
|
assert p.avatar_url.endswith("alice_full.jpg")
|
||||||
|
|
||||||
|
|
||||||
def test_fetch_profiles_batch_skips_private_or_missing(monkeypatch: pytest.MonkeyPatch) -> None:
|
def test_fetch_profiles_batch_skips_private_or_missing(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
|
|
@ -55,7 +55,7 @@ def test_fetch_profiles_batch_skips_private_or_missing(monkeypatch: pytest.Monke
|
||||||
# should accept that and return only what's there.
|
# should accept that and return only what's there.
|
||||||
body = {"response": {"players": [
|
body = {"response": {"players": [
|
||||||
{"steamid": "76561197960828710", "personaname": "Alice",
|
{"steamid": "76561197960828710", "personaname": "Alice",
|
||||||
"avatarmedium": "https://avatars.../alice_medium.jpg"},
|
"avatarfull": "https://avatars.../alice_full.jpg"},
|
||||||
]}}
|
]}}
|
||||||
_patched_get(monkeypatch, body, [])
|
_patched_get(monkeypatch, body, [])
|
||||||
profiles = steam_users.fetch_profiles_batch(
|
profiles = steam_users.fetch_profiles_batch(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue