Skip to content

Commit 596e724

Browse files
committed
Refill pill (recycle icon + "Refill") first on grid cards, thumbnails, the detail panel and the catalogue product card; TigerSquad member card/row (badge, level, head count) in the requests panel and support menu, swapped live; print-setting tiles with the icon on the title line
1 parent f8682c6 commit 596e724

18 files changed

Lines changed: 222 additions & 82 deletions

‎WORKLOG.md‎

Lines changed: 4 additions & 2 deletions
Large diffs are not rendered by default.

‎renderer/CODEMAP.md‎

Lines changed: 64 additions & 64 deletions
Large diffs are not rendered by default.

‎renderer/css/10-settings.css‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,3 +974,12 @@
974974
15% { opacity: 1; transform: translateX(5px); background: var(--tsq-orange); }
975975
}
976976
@media (prefers-reduced-motion: reduce) { .tsq-rank-arrow .icon { animation: none; opacity: .8; } }
977+
/* Already in the TigerSquad — the member's badge, level and the squad's head count. */
978+
.support-squad--in.support-squad--in { border-color: color-mix(in srgb, var(--sq-a) 55%, var(--border)); background: color-mix(in srgb, var(--sq-a) 8%, transparent); }
979+
.support-squad--in:hover { background: color-mix(in srgb, var(--sq-a) 14%, transparent); }
980+
.support-squad--in b { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
981+
.support-squad-tier {
982+
padding: 1px 7px; border-radius: 999px; font-size: 10px; font-weight: 800; letter-spacing: .3px;
983+
background: linear-gradient(135deg, var(--sq-a), var(--sq-b)); color: var(--sq-ink);
984+
}
985+
.support-squad-n[hidden] { display: none; }

‎renderer/css/70-detail-misc.css‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,13 @@
700700
.card-tl-badge .icon { background-color: var(--on-accent); }
701701
.card-tl-badge--twin { background: linear-gradient(135deg,var(--info),var(--info)); }
702702
.card-tl-badge--backup { background: linear-gradient(135deg,var(--success-hover),var(--success)); }
703+
/* Refill (a coil that goes into a reusable MasterSpool) — green. */
704+
.card-tl-badge--refill, .panel-img-refill-badge { background: linear-gradient(135deg,var(--success-hover),var(--success)); }
705+
/* "Refill" pill — recycle icon + the word; a plain round icon on the small thumbnails. */
706+
.card-tl-badge.card-tl-badge--refill { width: auto; min-width: 22px; padding: 0 7px 0 5px; gap: 3px; border-radius: 999px; }
707+
.card-badges-tl--sm .card-tl-badge--refill { width: 15px; min-width: 0; padding: 0; border-radius: 50%; }
708+
.panel-img-icon-badge.panel-img-refill-badge { width: auto; padding: 0 8px 0 6px; gap: 4px; border-radius: 999px; }
709+
.refill-txt { font-size: 10.5px; font-weight: 800; letter-spacing: .02em; line-height: 1; color: var(--on-accent); }
703710
/* Compact variant for the tiny table thumbnails. */
704711
.card-badges-tl--sm { top: 3px; left: 3px; gap: 3px; }
705712
.card-badges-tl--sm .card-tl-badge { width: 15px; height: 15px; border-width: 1px; }
@@ -3799,8 +3806,12 @@
37993806
.ro-card { border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; background: color-mix(in srgb, var(--surface-2) 45%, transparent); }
38003807
.ro-card-title { font-size: 14px; font-weight: 700; color: var(--text); margin-bottom: 10px; }
38013808
.ro-ptiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; } /* 2 rows of 3 */
3802-
.ro-ptile { display: flex; align-items: center; gap: 10px; padding: 10px 11px; border-radius: 10px; background: var(--surface-2); min-width: 0; }
3803-
.ro-ptile .icon { background: var(--muted); flex-shrink: 0; }
3809+
/* Icon + label share the title line; the value takes the full width below it. */
3810+
.ro-ptile { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; column-gap: 6px; row-gap: 3px; padding: 9px 11px; border-radius: 10px; background: var(--surface-2); min-width: 0; }
3811+
.ro-ptile > div { display: contents; }
3812+
.ro-ptile .icon { background: var(--muted); flex-shrink: 0; width: 15px; height: 15px; }
3813+
.ro-ptile-k { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
3814+
.ro-ptile-v { grid-column: 1 / -1; }
38043815
.ro-ptile-k { font-size: 11px; color: var(--muted); }
38053816
.ro-ptile-v { font-size: 14px; font-weight: 700; color: var(--text); }
38063817
.ro-cards2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

‎renderer/inventory.js‎

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ import { renderElegooCamBanner } from './printers/elegoo/widget_camera.js';
127127
import { sdcpWireLive } from './printers/elegoo/sdcp.js';
128128
import { elgFanStep } from './printers/elegoo/widget_control.js';
129129
import { jobBar, jobBarFill } from './printers/job-bar.js';
130-
import { initReport, toggleReport, openReport, isReportOpen, reportDropFiles, reportDragState, syncReports } from './report/index.js';
130+
import { initReport, toggleReport, openReport, isReportOpen, reportDropFiles, reportDragState, syncReports, refreshSquadCard } from './report/index.js';
131131

132132
const API_BASE = "https://cdn.tigertag.io";
133133

@@ -4700,11 +4700,21 @@ import { initReport, toggleReport, openReport, isReportOpen, reportDropFiles, re
47004700
renderSupporterBadge(); renderFriendBanner();
47014701
}, () => {});
47024702
}
4703+
let _lastSquadTier; // what the TigerSquad card last showed (undefined = never rendered)
4704+
let _squadCountCache = null; // { n, at } — the TigerSquad head count (_squadMemberCount)
47034705
function renderSupporterBadge() {
47044706
const host = document.querySelector("#sbUser .sb-avatar-wrap"); if (!host) return;
47054707
// TigerSquad member (any level) → heart and ring in the level's colour on the
47064708
// avatar (the level pill lives on the banner, not here). Not a member → nothing.
47074709
const tier = _ownSquadTier();
4710+
// Joined, left or changed level → the head count is stale, and the requests
4711+
// panel's card flips between "join" and "you're in".
4712+
if (tier !== _lastSquadTier) {
4713+
_lastSquadTier = tier; _squadCountCache = null;
4714+
try { refreshSquadCard(); } catch (_) {}
4715+
const row = _supportMenu?.querySelector(".support-squad");
4716+
if (row) { const tmp = document.createElement("div"); tmp.innerHTML = _supportSquadRowHTML(); tmp.firstElementChild ? row.replaceWith(tmp.firstElementChild) : row.remove(); }
4717+
}
47084718
const av = $("sbAvatar");
47094719
av?.classList.toggle("av-squad", !!tier);
47104720
SQUAD_TIERS.forEach(x => av?.classList.toggle(`sq-${x}`, tier === x));
@@ -4956,7 +4966,6 @@ import { initReport, toggleReport, openReport, isReportOpen, reportDropFiles, re
49564966
// How many accounts are in the TigerSquad — a COUNT aggregation over
49574967
// userProfiles (public read) through Firestore REST: ordering on
49584968
// tigerSquad.since also filters to the profiles that have it. Cached 10 min.
4959-
let _squadCountCache = null;
49604969
async function _squadMemberCount() {
49614970
if (_squadCountCache && Date.now() - _squadCountCache.at < 600000) return _squadCountCache.n;
49624971
try {
@@ -5004,6 +5013,30 @@ import { initReport, toggleReport, openReport, isReportOpen, reportDropFiles, re
50045013
// The badge itself arrives with the user doc (server-set); show it right away.
50055014
if (status === "granted") { state.supporter = true; renderSupporterBadge(); }
50065015
}
5016+
// The TigerSquad row of the support menu: "join" (opens the invite) for an
5017+
// account outside, "you're in" (badge, level, head count → the wall) for a member.
5018+
function _supportSquadRowHTML() {
5019+
if (!state.activeAccountId || state.friendView) return "";
5020+
const tier = _ownSquadTier();
5021+
if (!tier) return `
5022+
<button type="button" class="support-squad" data-squad-open>
5023+
<img class="support-squad-badge" src="../assets/img/tigersquad/tigersquad-gold.webp" alt="" aria-hidden="true">
5024+
<span class="support-squad-txt"><b>${esc(t("squadJoin"))}</b><small>${esc(t(state.supporter ? "squadJoinSubMember" : "squadJoinSubFree"))}</small></span>
5025+
<span class="icon icon-arrow-r icon-12 support-squad-go" aria-hidden="true"></span>
5026+
</button>`;
5027+
const n = _squadCountCache?.n;
5028+
if (!(n >= 1)) _squadMemberCount().then(c => {
5029+
const el = _supportMenu?.querySelector(".support-squad-n");
5030+
if (el && c >= 1) { el.textContent = t("squadMembers", { n: c }); el.hidden = false; }
5031+
});
5032+
return `
5033+
<button type="button" class="support-squad support-squad--in sq-${tier}" data-squad-wall>
5034+
<img class="support-squad-badge" src="${esc(SQUAD_ASSETS[tier])}" alt="" aria-hidden="true">
5035+
<span class="support-squad-txt"><b>${esc(t("squadInTitle"))}<span class="support-squad-tier">${esc(squadTierLabel(tier))}</span></b>
5036+
<small class="support-squad-n"${n >= 1 ? "" : " hidden"}>${n >= 1 ? esc(t("squadMembers", { n })) : ""}</small></span>
5037+
<span class="icon icon-arrow-up-right icon-12 support-squad-go" aria-hidden="true"></span>
5038+
</button>`;
5039+
}
50075040
function _openCoffee(e) {
50085041
const anchor = e?.currentTarget || (e instanceof Element ? e : null);
50095042
if (_supportMenu) { _closeSupportMenu(); return; }
@@ -5028,12 +5061,7 @@ import { initReport, toggleReport, openReport, isReportOpen, reportDropFiles, re
50285061
<span>${esc(t("supportCodeHint"))}</span>
50295062
<button type="button" class="support-code-chip${_supporterCodeCached() ? "" : " is-loading"}" data-support-copy="${esc(_supporterCodeCached() || "")}"><span>${esc(_supporterCodeCached() || "TS-····-····")}</span><span class="icon icon-copy icon-12" aria-hidden="true"></span></button>
50305063
</div>` : ""}
5031-
${state.activeAccountId && !state.supportPublicly && !anchor?.closest?.(".squad-invite") ? `
5032-
<button type="button" class="support-squad" data-squad-open>
5033-
<img class="support-squad-badge" src="../assets/img/tigersquad/tigersquad-gold.webp" alt="" aria-hidden="true">
5034-
<span class="support-squad-txt"><b>${esc(t("squadJoin"))}</b><small>${esc(t(state.supporter ? "squadJoinSubMember" : "squadJoinSubFree"))}</small></span>
5035-
<span class="icon icon-arrow-r icon-12 support-squad-go" aria-hidden="true"></span>
5036-
</button>` : ""}
5064+
${!anchor?.closest?.(".squad-invite") ? _supportSquadRowHTML() : ""}
50375065
${!state.supporter && state.activeAccountId ? `
50385066
<details class="support-claim">
50395067
<summary>${esc(t("supportClaimToggle"))}</summary>
@@ -5092,6 +5120,11 @@ import { initReport, toggleReport, openReport, isReportOpen, reportDropFiles, re
50925120
return;
50935121
}
50945122
// TigerSquad → the full invite (perks, levels, the free join), never a silent join.
5123+
if (ev.target.closest("[data-squad-wall]")) {
5124+
_closeSupportMenu();
5125+
window.electronAPI?.openExternal(`https://tigersystem.io/${state.lang || "en"}/tigersquad`);
5126+
return;
5127+
}
50955128
if (ev.target.closest("[data-squad-open]")) {
50965129
_closeSupportMenu();
50975130
if (!document.querySelector(".squad-invite")) setTimeout(_openSquadInvite, 130);
@@ -8442,7 +8475,10 @@ import { initReport, toggleReport, openReport, isReportOpen, reportDropFiles, re
84428475
? `<span class="card-tl-badge card-tl-badge--twin" title="${t('twinBadge')} — ${t('twinTitle')}"><span class="icon icon-link ${iconSize}"></span></span>` : "";
84438476
const backup = (withBackup && r.isPlus && r.rfidBackup)
84448477
? `<span class="card-tl-badge card-tl-badge--backup" title="${esc(t('backupBadge'))}"><span class="icon icon-backup ${iconSize}"></span></span>` : "";
8445-
return (twin || backup) ? `<div class="card-badges-tl${compact ? " card-badges-tl--sm" : ""}">${twin}${backup}</div>` : "";
8478+
// Refill (info1) — a coil with no spool of its own; the same flag as the "Refill" chip. First in the stack.
8479+
const refill = r.isRefill
8480+
? `<span class="card-tl-badge card-tl-badge--refill"><span class="icon icon-recycle ${iconSize}" aria-hidden="true"></span>${compact ? "" : "<span class=\"refill-txt\">Refill</span>"}</span>` : "";
8481+
return (twin || backup || refill) ? `<div class="card-badges-tl${compact ? " card-badges-tl--sm" : ""}">${refill}${twin}${backup}</div>` : "";
84468482
}
84478483

84488484
// Tier badge shown next to a row everywhere we display its origin:
@@ -9790,6 +9826,7 @@ import { initReport, toggleReport, openReport, isReportOpen, reportDropFiles, re
97909826
r.isPlus ? 1 : 0,
97919827
r.isCloud ? 1 : 0,
97929828
r.rfidBackup ? 1 : 0,
9829+
r.isRefill ? 1 : 0,
97939830
r.colorHex || "",
97949831
r.colorHex2 || "",
97959832
r.colorHex3 || "",
@@ -18966,9 +19003,14 @@ import { initReport, toggleReport, openReport, isReportOpen, reportDropFiles, re
1896619003
const imgUrl = r.imgUrl || p.label?.imgUrl || "";
1896719004
const _img = imgUrl ? resolvedImg(imgUrl) : null;
1896819005
const onerr = `this.outerHTML='<div class=\\'panel-img-color-placeholder\\'style=\\'background:${colorBg(r)}\\'><img src=\\'${logoSrc(colorBg(r))}\\'class=\\'panel-img-logo\\'></div>'`;
19006+
// Refill pictogram top-right, as on the spool's detail panel — known once the
19007+
// product detail (`product/get` → filament.refill → info1) has arrived.
19008+
const refill = r.isRefill
19009+
? `<div class="panel-img-badge panel-img-badge--tr panel-img-badge-tr-group"><span class="panel-img-badge-tr-item panel-img-icon-badge panel-img-refill-badge"><span class="icon icon-recycle icon-11" aria-hidden="true"></span><span class="refill-txt">Refill</span></span></div>`
19010+
: "";
1896919011
const imgSection = _img
18970-
? `<div class="panel-img-wrap" style="background:${colorBg(r)}"><img class="panel-img" src="${esc(_img)}" onerror="${esc(onerr)}" /></div>`
18971-
: `<div class="panel-img-wrap"><div class="panel-img-color-placeholder" style="background:${colorBg(r)}"><img src="${logoSrc(colorBg(r))}" class="panel-img-logo" /></div></div>`;
19012+
? `<div class="panel-img-wrap" style="background:${colorBg(r)}"><img class="panel-img" src="${esc(_img)}" onerror="${esc(onerr)}" />${refill}</div>`
19013+
: `<div class="panel-img-wrap"><div class="panel-img-color-placeholder" style="background:${colorBg(r)}"><img src="${logoSrc(colorBg(r))}" class="panel-img-logo" /></div>${refill}</div>`;
1897219014
// Identity — Brand · Series · Material on line 1, colour name on line 2.
1897319015
const brand = (r.brand && r.brand !== "-") ? r.brand : "";
1897419016
const series = (r.series && r.series !== "-") ? r.series : "";
@@ -20242,8 +20284,11 @@ import { initReport, toggleReport, openReport, isReportOpen, reportDropFiles, re
2024220284
const badgeBackup = (r.isPlus && r.rfidBackup)
2024320285
? `<span class="panel-img-badge-tr-item panel-img-icon-badge panel-img-backup-badge" title="${esc(t("backupBadge"))}"><span class="icon icon-backup icon-11"></span></span>`
2024420286
: "";
20245-
const badgeTrGroup = (badgeBackup || badgeTwin || badgeChip)
20246-
? `<div class="panel-img-badge panel-img-badge--tr panel-img-badge-tr-group">${badgeTwin}${badgeBackup}${badgeChip}</div>`
20287+
const badgeRefill = r.isRefill
20288+
? `<span class="panel-img-badge-tr-item panel-img-icon-badge panel-img-refill-badge"><span class="icon icon-recycle icon-11" aria-hidden="true"></span><span class="refill-txt">Refill</span></span>`
20289+
: "";
20290+
const badgeTrGroup = (badgeBackup || badgeTwin || badgeChip || badgeRefill)
20291+
? `<div class="panel-img-badge panel-img-badge--tr panel-img-badge-tr-group">${badgeRefill}${badgeTwin}${badgeBackup}${badgeChip}</div>`
2024720292
: "";
2024820293
// Bottom-right ❤/★/🛍 status cluster, same as the grid/table illustrations.
2024920294
const overlays = badgeLeft + badgeTrGroup + badgeTd + _productBadgesHTML(r);
@@ -22157,6 +22202,12 @@ import { initReport, toggleReport, openReport, isReportOpen, reportDropFiles, re
2215722202
openExternal: url => window.electronAPI?.openExternal(url),
2215822203
openCoffee: anchor => _openCoffee(anchor),
2215922204
canJoinSquad: () => !!state.activeAccountId && !state.supportPublicly && !state.friendView,
22205+
// Already in → the card shows the member's badge instead, with the squad's head count.
22206+
squadMember: () => {
22207+
const tier = state.activeAccountId && !state.friendView ? _ownSquadTier() : null;
22208+
return tier ? { tier, label: squadTierLabel(tier), src: SQUAD_ASSETS[tier], wall: `https://tigersystem.io/${state.lang || "en"}/tigersquad` } : null;
22209+
},
22210+
squadMemberCount: () => _squadMemberCount(),
2216022211
openSquad: () => { if (!document.querySelector(".squad-invite")) _openSquadInvite(); },
2216122212
timeAgo: ms => timeAgo(ms),
2216222213
getUid: () => state.activeAccountId || null,

‎renderer/locales/de.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
"squadJoinSubFree": "Gratis. Du erscheinst an der TigerSquad-Wand — dein Abzeichen folgt deinem Level (Bronze → Platinum), und deine Freunde sehen es.",
3535
"squadJoinSubMember": "Du erscheinst an der TigerSquad-Wand — dein Abzeichen folgt deinem Level (Bronze → Platinum), und deine Freunde sehen es.",
3636
"squadReqCta": "Mal reinschauen",
37+
"squadInTitle": "Du bist in der TigerSquad",
38+
"squadInBody": "Dein Abzeichen hängt an der Wand und deine Freunde sehen es. Danke, dass du dabei bist — dein Level steigt ganz von selbst.",
3739
"squadXpLine": "{{xp}} XP · {{n}} zertifizierte TigerTag+",
3840
"supportThanks": "Du hast das Projekt unterstützt — danke! Ein weiterer Kaffee ist immer willkommen.",
3941
"supportCodeHint": "Schreib deinen Code in die Zahlungsnachricht: So wird deine Spende mit deinem Konto verknüpft (Gold in der TigerSquad)",

‎renderer/locales/en.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
"squadJoinSubFree": "Free. You show up on the TigerSquad wall — your badge follows your level (Bronze → Platinum), and your friends see it.",
3535
"squadJoinSubMember": "You show up on the TigerSquad wall — your badge follows your level (Bronze → Platinum), and your friends see it.",
3636
"squadReqCta": "See what's in it",
37+
"squadInTitle": "You're in the TigerSquad",
38+
"squadInBody": "Your badge is on the wall and your friends see it. Thanks for being part of it — your level climbs on its own as you go.",
3739
"squadXpLine": "{{xp}} XP · {{n}} certified TigerTag+",
3840
"supportThanks": "You backed the project — thank you! Another coffee is always welcome.",
3941
"supportCodeHint": "Add your code to your payment message: it links your gift to your account (Gold in the TigerSquad)",

‎renderer/locales/es.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
"squadJoinSubFree": "Gratis. Apareces en el muro de la TigerSquad — tu insignia sigue tu nivel (Bronze → Platinum) y tus amigos la ven.",
3535
"squadJoinSubMember": "Apareces en el muro de la TigerSquad — tu insignia sigue tu nivel (Bronze → Platinum) y tus amigos la ven.",
3636
"squadReqCta": "Ver qué incluye",
37+
"squadInTitle": "Formas parte de la TigerSquad",
38+
"squadInBody": "Tu insignia está en el muro y tus amigos la ven. Gracias por estar — tu nivel sube solo con el tiempo.",
3739
"squadXpLine": "{{xp}} XP · {{n}} TigerTag+ certificados",
3840
"supportThanks": "Apoyaste el proyecto, ¡gracias! Otro café siempre es bienvenido.",
3941
"supportCodeHint": "Añade tu código al mensaje del pago: vincula tu donación a tu cuenta (Gold en la TigerSquad)",

‎renderer/locales/fr.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
"squadJoinSubFree": "Gratuit. Tu apparais sur le mur de la TigerSquad — ton badge suit ton niveau (Bronze → Platinum), et tes amis le voient.",
3535
"squadJoinSubMember": "Tu apparais sur le mur de la TigerSquad — ton badge suit ton niveau (Bronze → Platinum), et tes amis le voient.",
3636
"squadReqCta": "Voir ce qu'il y a dedans",
37+
"squadInTitle": "Tu fais partie de la TigerSquad",
38+
"squadInBody": "Ton badge est sur le mur et tes amis le voient. Merci d'en être — ton niveau grimpe tout seul au fil du temps.",
3739
"squadXpLine": "{{xp}} XP · {{n}} TigerTag+ certifiés",
3840
"supportThanks": "Tu as soutenu le projet — merci ! Un autre café est toujours le bienvenu.",
3941
"supportCodeHint": "Ajoute ton code dans le message de ton paiement : il relie ton don à ton compte (Gold dans la TigerSquad)",

‎renderer/locales/it.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
"squadJoinSubFree": "Gratis. Compari sul muro della TigerSquad — il tuo badge segue il tuo livello (Bronze → Platinum) e i tuoi amici lo vedono.",
3535
"squadJoinSubMember": "Compari sul muro della TigerSquad — il tuo badge segue il tuo livello (Bronze → Platinum) e i tuoi amici lo vedono.",
3636
"squadReqCta": "Scopri cosa c'è dentro",
37+
"squadInTitle": "Fai parte della TigerSquad",
38+
"squadInBody": "Il tuo badge è sul muro e i tuoi amici lo vedono. Grazie di esserci — il tuo livello sale da solo col tempo.",
3739
"squadXpLine": "{{xp}} XP · {{n}} TigerTag+ certificati",
3840
"supportThanks": "Hai sostenuto il progetto, grazie! Un altro caffè è sempre benvenuto.",
3941
"supportCodeHint": "Aggiungi il tuo codice al messaggio del pagamento: collega la donazione al tuo account (Gold nella TigerSquad)",

0 commit comments

Comments
 (0)