statuses
This commit is contained in:
parent
a801609eb9
commit
808207bbeb
46
css/main.css
46
css/main.css
|
|
@ -2093,6 +2093,25 @@ a.fc-name:hover { color: rgb(var(--accent-rgb)); }
|
|||
}
|
||||
.fc-user:empty { display: none; }
|
||||
|
||||
/* custom status (Discord activity type 4) */
|
||||
.fc-custom {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
font-size: 0.72rem;
|
||||
color: var(--subtext-1);
|
||||
margin-top: 0.1rem;
|
||||
min-width: 0;
|
||||
}
|
||||
.fc-custom[hidden] { display: none; }
|
||||
.fc-custom-emoji { width: 14px; height: 14px; display: block; flex: none; }
|
||||
.fc-custom-emoji-uni { font-size: 0.8rem; line-height: 1; flex: none; }
|
||||
.fc-custom-text {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.fc-badges {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
|
@ -2923,6 +2942,33 @@ html[data-theme] body.api-body {
|
|||
}
|
||||
.pc-user:empty { display: none; }
|
||||
|
||||
/* status word (Online / Idle / Do Not Disturb / Offline) */
|
||||
.pc-status-text {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
color: var(--overlay-1);
|
||||
}
|
||||
.pc-status-text:empty { display: none; }
|
||||
.pc-status-text::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
margin-right: 0.3rem;
|
||||
vertical-align: baseline;
|
||||
background: var(--overlay-0);
|
||||
}
|
||||
.presence-card[data-status="online"] .pc-status-text { color: var(--green); }
|
||||
.presence-card[data-status="online"] .pc-status-text::before { background: var(--green); }
|
||||
.presence-card[data-status="idle"] .pc-status-text { color: var(--yellow); }
|
||||
.presence-card[data-status="idle"] .pc-status-text::before { background: var(--yellow); }
|
||||
.presence-card[data-status="dnd"] .pc-status-text { color: var(--red); }
|
||||
.presence-card[data-status="dnd"] .pc-status-text::before { background: var(--red); }
|
||||
.presence-card[data-status="offline"] .pc-status-text { color: var(--overlay-1); }
|
||||
.presence-card[data-status="offline"] .pc-status-text::before { background: var(--overlay-0); }
|
||||
|
||||
/* ---- expandable sections ---- */
|
||||
.pc-sections {
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@
|
|||
</header>
|
||||
|
||||
<!-- ============ GIRLS-NETWORK ============ -->
|
||||
<section class="section">
|
||||
<section class="section" id="girls-network">
|
||||
<h2 class="section-title">Girls-Network</h2>
|
||||
<div class="bot-grid">
|
||||
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
</section>
|
||||
|
||||
<!-- ============ MY BOTS (doughmination) ============ -->
|
||||
<section class="section">
|
||||
<section class="section" id="my-bots">
|
||||
<h2 class="section-title">My Bots</h2>
|
||||
<div class="bot-grid">
|
||||
|
||||
|
|
@ -160,7 +160,7 @@
|
|||
</section>
|
||||
|
||||
<!-- ============ TOOLS ============ -->
|
||||
<section class="section">
|
||||
<section class="section" id="tools">
|
||||
<h2 class="section-title">Tools</h2>
|
||||
<div class="bot-grid">
|
||||
|
||||
|
|
|
|||
|
|
@ -291,4 +291,29 @@
|
|||
} else {
|
||||
init();
|
||||
}
|
||||
|
||||
// ---- anchor links: open the targeted <details> and scroll to it --------
|
||||
// Sections are collapsible (and some are populated/un-hidden async), so a
|
||||
// plain #hash won't reliably reveal them. Open + scroll on load and on
|
||||
// hashchange, retrying briefly while late content settles in.
|
||||
function openFromHash() {
|
||||
var id = (location.hash || "").slice(1);
|
||||
if (!id) return;
|
||||
var attempts = 0;
|
||||
(function tryOpen() {
|
||||
var target = document.getElementById(id);
|
||||
if (target && !target.hidden) {
|
||||
if (target.tagName === "DETAILS") target.open = true;
|
||||
target.scrollIntoView();
|
||||
return;
|
||||
}
|
||||
if (attempts++ < 10) setTimeout(tryOpen, 200);
|
||||
})();
|
||||
}
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", openFromHash);
|
||||
} else {
|
||||
openFromHash();
|
||||
}
|
||||
window.addEventListener("hashchange", openFromHash);
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -97,6 +97,30 @@
|
|||
return proxyImg(url, { w: 480 });
|
||||
}
|
||||
|
||||
// custom-status emoji → CDN url (custom emoji) or null (unicode emoji)
|
||||
function customEmojiUrl(e) {
|
||||
if (!e || !e.id) return null;
|
||||
return proxyImg("https://cdn.discordapp.com/emojis/" + e.id + (e.animated ? ".gif" : ".png") + "?size=32");
|
||||
}
|
||||
// Render the Discord custom status (activity type 4): emoji + text.
|
||||
function renderCustomStatus(refs, activities) {
|
||||
if (!refs.custom) return;
|
||||
var c = (activities || []).find(function (a) { return a && a.type === 4; });
|
||||
var text = c && c.state ? String(c.state) : "";
|
||||
var emoji = c && c.emoji;
|
||||
if (!text && !(emoji && (emoji.id || emoji.name))) {
|
||||
refs.custom.hidden = true;
|
||||
refs.custom.innerHTML = "";
|
||||
return;
|
||||
}
|
||||
var eu = emoji ? customEmojiUrl(emoji) : null;
|
||||
var emojiHtml = eu
|
||||
? '<img class="fc-custom-emoji" src="' + eu + '" alt="" onerror="this.remove()">'
|
||||
: (emoji && emoji.name ? '<span class="fc-custom-emoji-uni">' + esc(emoji.name) + "</span>" : "");
|
||||
refs.custom.innerHTML = emojiHtml + (text ? '<span class="fc-custom-text">' + esc(text) + "</span>" : "");
|
||||
refs.custom.hidden = false;
|
||||
}
|
||||
|
||||
// dstn.to badge list → small icon row (same source the presence card uses)
|
||||
function renderDstnBadges(badges) {
|
||||
if (!Array.isArray(badges)) return "";
|
||||
|
|
@ -150,6 +174,7 @@
|
|||
'<span class="fc-tag" hidden></span>' +
|
||||
'</span>' +
|
||||
'<span class="fc-user"></span>' +
|
||||
'<span class="fc-custom" hidden></span>' +
|
||||
'<span class="fc-badges"></span>' +
|
||||
'</span>' +
|
||||
'</div>';
|
||||
|
|
@ -159,6 +184,7 @@
|
|||
pfp: card.querySelector(".fc-pfp"),
|
||||
statusDot: card.querySelector(".fc-status"),
|
||||
user: card.querySelector(".fc-user"),
|
||||
custom: card.querySelector(".fc-custom"),
|
||||
tag: card.querySelector(".fc-tag"),
|
||||
badges: card.querySelector(".fc-badges"),
|
||||
banner: card.querySelector(".fc-banner")
|
||||
|
|
@ -188,6 +214,7 @@
|
|||
refs.statusDot.title = STATUS_TITLE[status] || "Offline";
|
||||
if (u.avatar) refs.pfp.src = avatarUrl(u);
|
||||
if (u.username) refs.user.textContent = "@" + u.username;
|
||||
renderCustomStatus(refs, d.activities);
|
||||
renderClanTag(refs, u.primary_guild);
|
||||
return true;
|
||||
})
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
'</span>' +
|
||||
'<span class="pc-sub-row">' +
|
||||
'<span class="pc-user"></span>' +
|
||||
'<span class="pc-status-text"></span>' +
|
||||
'<span class="pc-pronouns" hidden></span>' +
|
||||
'<span class="pc-platforms" aria-hidden="true"></span>' +
|
||||
'</span>' +
|
||||
|
|
@ -71,6 +72,8 @@
|
|||
const tagEl = card.querySelector(".pc-tag");
|
||||
const userEl = card.querySelector(".pc-user");
|
||||
const platformsEl = card.querySelector(".pc-platforms");
|
||||
const statusTextEl = card.querySelector(".pc-status-text");
|
||||
const STATUS_TITLE = { online: "Online", idle: "Idle", dnd: "Do Not Disturb", offline: "Offline" };
|
||||
const metaEl = card.querySelector(".pc-meta");
|
||||
const badgesEl = card.querySelector(".pc-badges");
|
||||
const sections = card.querySelector(".pc-sections");
|
||||
|
|
@ -505,6 +508,7 @@
|
|||
const u = d.discord_user || {};
|
||||
const status = d.discord_status || "offline";
|
||||
card.dataset.status = status;
|
||||
if (statusTextEl) statusTextEl.textContent = STATUS_TITLE[status] || "Offline";
|
||||
|
||||
avImg.src = avatarUrl(u);
|
||||
const deco = u.avatar_decoration_data;
|
||||
|
|
|
|||
|
|
@ -62,14 +62,14 @@
|
|||
</a>
|
||||
|
||||
<!-- lyrics -->
|
||||
<div class="sec-row">
|
||||
<div class="sec-row" id="lyrics-section">
|
||||
<h2 class="sec-title">Lyrics</h2>
|
||||
<button class="ly-lock is-locked" id="ly-lock" type="button" aria-pressed="true" hidden><span class="ly-bars" aria-hidden="true"><i></i><i></i><i></i><i></i></span><span class="ly-lock-label">Synced</span></button>
|
||||
</div>
|
||||
<div class="lyrics is-empty" id="lyrics"><p class="ly-note">Waiting for a track…</p></div>
|
||||
|
||||
<!-- recently played -->
|
||||
<h2 class="sec-title">Recently played</h2>
|
||||
<h2 class="sec-title" id="recently-played">Recently played</h2>
|
||||
<ul class="recent" id="recent"></ul>
|
||||
|
||||
<!-- top artists (hidden until Last.fm data arrives) -->
|
||||
|
|
|
|||
Loading…
Reference in New Issue