From 74c330565d6eebd3cd7eb749629d1e9308e9124f Mon Sep 17 00:00:00 2001 From: Chintanpatel24 <216989679+Chintanpatel24@users.noreply.github.com> Date: Tue, 21 Jul 2026 13:35:59 +0000 Subject: [PATCH] Fix overlaps, music styles, and streak logic - Fix language card text overlaps in standard and compact layouts (Issue #29) - Fix style clashing and equalizer animations in music players (Issue #27) - Fix text overlaps in PR card header (Issue #11) - Fix layout overlaps in Mastercard/Dashboard progress bars (Issues #10, #20) - Fix current streak calculation logic (Streak Card "not working") --- api/streak.js | 21 ++++++++- src/svg-language.js | 27 ++++++++--- src/svg-master.js | 16 ++++--- src/svg-music.js | 108 ++++++++++++++++++++++++++++---------------- src/svg-pr.js | 4 +- 5 files changed, 119 insertions(+), 57 deletions(-) diff --git a/api/streak.js b/api/streak.js index cd1cef0..0cf4817 100644 --- a/api/streak.js +++ b/api/streak.js @@ -49,10 +49,27 @@ module.exports = async (req, res) => { let longestStreak = 0; let tempStreak = 0; + // Corrected streak logic: find last day with activity and check if it's today/yesterday + const today = new Date().toISOString().split('T')[0]; + const yesterday = new Date(Date.now() - 86400000).toISOString().split('T')[0]; + + let lastActiveIndex = -1; for (let i = sortedDays.length - 1; i >= 0; i--) { - if (sortedDays[i].count > 0) currentStreak++; - else break; + if (sortedDays[i].count > 0) { + if (sortedDays[i].date === today || sortedDays[i].date === yesterday) { + lastActiveIndex = i; + } + break; + } + } + + if (lastActiveIndex !== -1) { + for (let i = lastActiveIndex; i >= 0; i--) { + if (sortedDays[i].count > 0) currentStreak++; + else break; + } } + for (const day of sortedDays) { if (day.count > 0) { tempStreak++; longestStreak = Math.max(longestStreak, tempStreak); } else tempStreak = 0; diff --git a/src/svg-language.js b/src/svg-language.js index 10f5bc7..0172b0c 100644 --- a/src/svg-language.js +++ b/src/svg-language.js @@ -20,7 +20,7 @@ function generateLanguageSVG(options) { const barY = headerHeight + 8; const listStartY = barY + barHeight + 20; const listItemHeight = 24; - const cols = Math.min(topLangs.length, 6); + const cols = Math.min(topLangs.length, 3); const rows = Math.ceil(topLangs.length / cols); const listHeight = rows * listItemHeight; const cardWidth = 460; @@ -48,10 +48,13 @@ function generateLanguageSVG(options) { const color = getLanguageColor(lang.name); const pct = lang.percentage >= 10 ? Math.round(lang.percentage) : lang.percentage.toFixed(1); + const maxLabelLen = 18; + const displayName = lang.name.length > maxLabelLen ? lang.name.substring(0, maxLabelLen - 3) + "..." : lang.name; + langList += ` - ${escapeXml(lang.name)} + ${escapeXml(displayName)} ${pct}% `; }); @@ -96,13 +99,23 @@ function generateLanguageCompactSVG(options) { }); let labels = ""; - let labelX = padX; - topLangs.forEach((lang) => { + const cols = 3; + const colWidth = (cardWidth - padX * 2) / cols; + + topLangs.forEach((lang, index) => { const color = getLanguageColor(lang.name); const pct = lang.percentage >= 10 ? Math.round(lang.percentage) : lang.percentage.toFixed(1); - labels += ``; - labels += `${escapeXml(lang.name)} ${pct}%`; - labelX += 84; + + const col = index % cols; + const row = Math.floor(index / cols); + const labelX = padX + col * colWidth; + const labelY = 84 + row * 18; + + const maxLabelLen = 16; + const displayName = lang.name.length > maxLabelLen ? lang.name.substring(0, maxLabelLen - 3) + "..." : lang.name; + + labels += ``; + labels += `${escapeXml(displayName)} ${pct}%`; }); return ` diff --git a/src/svg-master.js b/src/svg-master.js index bdf4b98..b65b743 100644 --- a/src/svg-master.js +++ b/src/svg-master.js @@ -98,14 +98,16 @@ function generateMasterCardSVG(options) { const topLangs = languages.slice(0, 8); topLangs.forEach((lang, i) => { const ly = i * 35; - const barMax = gridW - 150; + const barMax = 240; const barW = (lang.percentage / 100) * barMax; + const maxLabelLen = 15; + const displayName = lang.name.length > maxLabelLen ? lang.name.substring(0, maxLabelLen - 3) + "..." : lang.name; content += ` - ${escapeXml(lang.name)} - - + ${escapeXml(displayName)} + + ${lang.percentage.toFixed(1)}% `; }); @@ -120,12 +122,12 @@ function generateMasterCardSVG(options) { daysOfWeek.forEach((day, i) => { const ly = i * 35; const count = weekMap[i] || 0; - const barW = (count / maxWeekly) * (gridW - 120); + const barW = (count / maxWeekly) * 300; content += ` ${day} - - + + ${count.toLocaleString()} `; }); diff --git a/src/svg-music.js b/src/svg-music.js index 4cfc2a0..a42c7fa 100644 --- a/src/svg-music.js +++ b/src/svg-music.js @@ -51,19 +51,53 @@ function generateMusicSVG(options) { let playerContent = ""; let styleTags = ` - .title { font: 700 14px -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; fill: #${titleColor}; } - .artist { font: 400 12px -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; fill: #${textColor}; } - @keyframes bar { - 0%, 100% { height: 4px; } - 50% { height: 20px; } - } - .bar { fill: #${accentColor}; animation: bar 1s infinite ease-in-out; } - .bar1 { animation-delay: 0s; } - .bar2 { animation-delay: 0.15s; } - .bar3 { animation-delay: 0.3s; } - .bar4 { animation-delay: 0.45s; } - .bar5 { animation-delay: 0.6s; } + /* General Styles */ .glow { filter: drop-shadow(0 0 3px #${accentColor}); } + + /* Winamp (90s) Styles */ + .winamp-title { font: 700 14px monospace; fill: #00ff00; } + .winamp-artist { font: 400 12px monospace; fill: #00ff00; opacity: 0.8; } + @keyframes winamp-scale { + 0%, 100% { transform: scale(1, -0.15); } + 50% { transform: scale(1, -1.0); } + } + .winamp-bar { fill: #00ff00; transform-origin: 0 0; } + .wbar1 { animation: winamp-scale 0.8s infinite ease-in-out; animation-delay: 0.1s; } + .wbar2 { animation: winamp-scale 1.1s infinite ease-in-out; animation-delay: 0.4s; } + .wbar3 { animation: winamp-scale 0.9s infinite ease-in-out; animation-delay: 0.2s; } + .wbar4 { animation: winamp-scale 1.3s infinite ease-in-out; animation-delay: 0.6s; } + .wbar5 { animation: winamp-scale 1.0s infinite ease-in-out; animation-delay: 0.3s; } + + /* iPod Styles */ + .ipod-title { font: 700 14px -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; fill: #111111; } + .ipod-artist { font: 400 12px -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; fill: #555555; } + @keyframes ipod-scale { + 0%, 100% { transform: scale(1, -0.2); } + 50% { transform: scale(1, -1.0); } + } + .ipod-bar { fill: #${accentColor}; transform-origin: 0 0; } + .ibar1 { animation: ipod-scale 0.9s infinite ease-in-out; animation-delay: 0.1s; } + .ibar2 { animation: ipod-scale 1.2s infinite ease-in-out; animation-delay: 0.4s; } + .ibar3 { animation: ipod-scale 0.8s infinite ease-in-out; animation-delay: 0.2s; } + .ibar4 { animation: ipod-scale 1.1s infinite ease-in-out; animation-delay: 0.5s; } + + /* Cassette Styles */ + .cassette-title { font: 700 12px monospace; fill: #ffffff; } + .cassette-artist { font: 400 10px monospace; fill: #d4af37; } + @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } + .reel { transform-origin: center; animation: spin 4s linear infinite; } + + /* Boombox Styles */ + .boombox-title { font: 700 13px monospace; fill: #00ff00; filter: drop-shadow(0 0 2px #00ff00); } + .boombox-artist { font: 400 11px monospace; fill: #00ff00; opacity: 0.7; } + @keyframes boombox-scale { + 0%, 100% { transform: scale(1, -0.15); } + 50% { transform: scale(1, -1.0); } + } + .boombox-bar { fill: #00ff00; transform-origin: 0 0; } + .bbar1 { animation: boombox-scale 0.7s infinite ease-in-out; animation-delay: 0s; } + .bbar2 { animation: boombox-scale 1.0s infinite ease-in-out; animation-delay: 0.3s; } + .bbar3 { animation: boombox-scale 0.8s infinite ease-in-out; animation-delay: 0.15s; } `; if (player === "ipod") { @@ -78,15 +112,15 @@ function generateMusicSVG(options) { ${gif_url ? `` : ` - - - - + + + + `} - ${escapeXml(title)} - ${escapeXml(artist)} + ${escapeXml(title)} + ${escapeXml(artist)} @@ -99,10 +133,6 @@ function generateMusicSVG(options) { `; } else if (player === "cassette") { - styleTags += ` - @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } - .reel { transform-origin: center; animation: spin 4s linear infinite; } - `; playerContent = ` @@ -125,10 +155,10 @@ function generateMusicSVG(options) { - ${escapeXml(title)} + ${escapeXml(title)} - ${escapeXml(artist)} + ${escapeXml(artist)} ${gif_url ? `` : ""} @@ -156,16 +186,16 @@ function generateMusicSVG(options) { - - ${escapeXml(title)} - ${escapeXml(artist)} + + ${escapeXml(title)} + ${escapeXml(artist)} - - - + + + @@ -173,7 +203,7 @@ function generateMusicSVG(options) { `; } else { - // Default 90s Winamp style - Enhanced + // Default 90s Winamp style playerContent = ` @@ -191,18 +221,18 @@ function generateMusicSVG(options) { ${gif_url ? `` : ` - - - - - + + + + + `} - - ${escapeXml(title)} - ${escapeXml(artist)} + + ${escapeXml(title)} + ${escapeXml(artist)} diff --git a/src/svg-pr.js b/src/svg-pr.js index 78824ab..6d84757 100644 --- a/src/svg-pr.js +++ b/src/svg-pr.js @@ -58,8 +58,8 @@ function generatePRCardSVG(options) { Merged: ${mergedPRs} - Closed: ${closedPRs} - Open: ${openPRs} + Closed: ${closedPRs} + Open: ${openPRs} ${rows}