Redesign petition SVG share image; remove flag/report button

SVG: clean two-zone layout — dark header with RADICAL wordmark + PETITION
badge, full-width text area with left accent bar and large quote mark,
footer band with signature count, author, date and CTA. Proper word-wrap
centred in the card. Looks like a real share card now.

Remove flag button and handleFlag from proposal cards entirely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
King Omar 2026-06-27 03:13:53 +10:00
parent a07d3f6887
commit b726dc1e24
2 changed files with 64 additions and 74 deletions

View file

@ -1131,7 +1131,6 @@ function initializeShareButtons() {
<img src="https://theradicalparty.com/memes/share-arrow-icon-md.png" alt="Share" style="width: 20px; height: 14px; filter: brightness(0) invert(1); pointer-events: none;"> <img src="https://theradicalparty.com/memes/share-arrow-icon-md.png" alt="Share" style="width: 20px; height: 14px; filter: brightness(0) invert(1); pointer-events: none;">
</div> </div>
<button class="share-img-btn" onclick="event.stopPropagation();event.preventDefault();window.open('${API_BASE_URL}/petition-svg?id=${proposal.id}','_blank')" title="Share as image">🖼</button> <button class="share-img-btn" onclick="event.stopPropagation();event.preventDefault();window.open('${API_BASE_URL}/petition-svg?id=${proposal.id}','_blank')" title="Share as image">🖼</button>
<button class="flag-btn" data-proposal-id="${proposal.id}" onclick="event.stopPropagation();event.preventDefault();handleFlag('${proposal.id}',this)" title="Report this proposal"></button>
</div> </div>
<div class="proposal-time">${formatDate(proposal.timestamp)}</div> <div class="proposal-time">${formatDate(proposal.timestamp)}</div>
</div> </div>

137
worker.js
View file

@ -2024,82 +2024,73 @@ async function servePetitionSVG(request, env) {
* @returns {string} - SVG markup as a string * @returns {string} - SVG markup as a string
*/ */
function generatePetitionSVG(proposal) { function generatePetitionSVG(proposal) {
// Get data with fallbacks const text = escapeHTML(proposal.text || 'Untitled petition');
const petitionText = proposal.text || "Unknown petition";
const upvotes = proposal.upvotes || 0; const upvotes = proposal.upvotes || 0;
const downvotes = proposal.downvotes || 0; const author = escapeHTML(proposal.author_name || 'Anonymous');
const netVotes = upvotes - downvotes; const date = new Date(proposal.timestamp || Date.now()).toLocaleDateString('en-AU', {
const netVotesDisplay = netVotes > 0 ? `+${netVotes}` : netVotes; day: 'numeric', month: 'short', year: 'numeric'
const netVotesColor = netVotes > 0 ? "#11cc77" : (netVotes < 0 ? "#ff0099" : "#ffffff");
const proposalId = proposal.id || "unknown";
// Format timestamp
const timestamp = new Date(proposal.timestamp || Date.now()).toLocaleDateString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric'
}); });
// Base SVG template
const svgTemplate = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 630" width="1200" height="630">
<!-- Background -->
<rect width="1200" height="630" fill="#000000" />
<!-- Border frame with glowing effect -->
<rect x="10" y="10" width="1180" height="610" fill="none" stroke="#ff0099" stroke-width="4" rx="0" />
<rect x="20" y="20" width="1160" height="590" fill="rgba(0, 0, 0, 0.8)" stroke="#ff0099" stroke-width="1" rx="0"
style="filter: drop-shadow(0 0 10px #ff0099)" />
<!-- RADICAL Header -->
<text x="600" y="90" font-family="'Roboto Mono', monospace" font-size="72" font-weight="700" text-anchor="middle"
fill="#ff0099" style="text-transform: uppercase;">RADICAL</text>
<!-- Tagline -->
<rect x="450" y="110" width="300" height="36" fill="#ff0099" />
<text x="600" y="135" font-family="'Roboto Mono', monospace" font-size="20" font-weight="600" text-anchor="middle"
fill="#000000" style="text-transform: uppercase;">VIBE, VOTE, VETO</text>
<!-- Petition text container -->
<rect x="100" y="180" width="1000" height="280" fill="rgba(17, 17, 17, 0.7)" stroke="#333333" stroke-width="1" />
<!-- Petition text (dynamically generated) -->
${generateSVGTextLines(petitionText, 120, 220, 960)}
<!-- Vote statistics -->
<g transform="translate(200, 510)">
<!-- Upvotes -->
<text x="0" y="0" font-family="'Roboto Mono', monospace" font-size="24" fill="#ff0099"></text>
<text x="30" y="0" font-family="'Roboto Mono', monospace" font-size="24" fill="#ffffff">${upvotes}</text>
<!-- Downvotes -->
<text x="120" y="0" font-family="'Roboto Mono', monospace" font-size="24" fill="#ff0099"></text>
<text x="150" y="0" font-family="'Roboto Mono', monospace" font-size="24" fill="#ffffff">${downvotes}</text>
<!-- Net votes -->
<text x="240" y="0" font-family="'Roboto Mono', monospace" font-size="24" fill="#ff0099">NET:</text>
<text x="300" y="0" font-family="'Roboto Mono', monospace" font-size="24" fill="${netVotesColor}">${netVotesDisplay}</text>
</g>
<!-- Timestamp and ID -->
<text x="600" y="560" font-family="'Roboto Mono', monospace" font-size="18" fill="#aaaaaa" text-anchor="middle">
Petition ID: ${proposalId} Created: ${timestamp}
</text>
<!-- Radical Logo / Brand (right corner) -->
<g transform="translate(940, 460)">
<!-- Pink square for the logo -->
<rect x="0" y="0" width="120" height="120" fill="#111111" stroke="#ff0099" stroke-width="2" />
<text x="60" y="50" font-family="'Roboto Mono', monospace" font-size="16" fill="#ffffff" text-anchor="middle">RADICAL</text>
<text x="60" y="75" font-family="'Roboto Mono', monospace" font-size="14" fill="#ff0099" text-anchor="middle">PETITION</text>
<text x="60" y="100" font-family="'Roboto Mono', monospace" font-size="12" fill="#aaaaaa" text-anchor="middle">#${proposalId.slice(-6)}</text>
</g>
<!-- URL -->
<text x="600" y="600" font-family="'Roboto Mono', monospace" font-size="20" fill="#ff0099" text-anchor="middle"
style="text-transform: uppercase;">theradicalparty.com</text>
</svg>`;
return svgTemplate; // Word-wrap the petition text into lines (max ~52 chars per line at font-size 28)
const words = text.split(' ');
const lines = [];
let line = '';
for (const word of words) {
if ((line + ' ' + word).trim().length > 52) { lines.push(line.trim()); line = word; }
else line = (line + ' ' + word).trim();
}
if (line) lines.push(line);
const displayLines = lines.slice(0, 7);
if (lines.length > 7) displayLines[6] = displayLines[6].replace(/.{3}$/, '...');
const textY = 310 - (displayLines.length * 38) / 2;
const textEls = displayLines.map((l, i) =>
`<text x="600" y="${textY + i * 38}" font-family="monospace" font-size="28" font-weight="500" fill="#ffffff" text-anchor="middle">${l}</text>`
).join('\n ');
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 630" width="1200" height="630">
<!-- bg -->
<rect width="1200" height="630" fill="#000"/>
<!-- left accent bar -->
<rect x="0" y="0" width="8" height="630" fill="#ff0099"/>
<!-- header band -->
<rect x="0" y="0" width="1200" height="80" fill="#0a0a0a"/>
<!-- RADICAL wordmark -->
<text x="60" y="54" font-family="monospace" font-size="48" font-weight="700" fill="#ff0099" letter-spacing="8">RADICAL</text>
<!-- tagline -->
<text x="60" y="74" font-family="monospace" font-size="13" fill="#555" letter-spacing="3">VIBE · VOTE · VETO theradicalparty.com</text>
<!-- PETITION label top right -->
<rect x="980" y="18" width="180" height="44" fill="#ff0099"/>
<text x="1070" y="46" font-family="monospace" font-size="18" font-weight="700" fill="#000" text-anchor="middle" letter-spacing="2">PETITION</text>
<!-- petition text area -->
<rect x="60" y="108" width="1080" height="380" fill="#0a0a0a" rx="0"/>
<rect x="60" y="108" width="4" height="380" fill="#ff0099"/>
<!-- quote mark -->
<text x="100" y="185" font-family="monospace" font-size="80" fill="#1a1a1a" font-weight="700">"</text>
<!-- wrapped petition text -->
${textEls}
<!-- footer band -->
<rect x="0" y="508" width="1200" height="122" fill="#0a0a0a"/>
<line x1="0" y1="508" x2="1200" y2="508" stroke="#222" stroke-width="1"/>
<!-- upvote count -->
<text x="68" y="560" font-family="monospace" font-size="15" fill="#666" letter-spacing="1">SIGNATURES</text>
<text x="68" y="598" font-family="monospace" font-size="40" font-weight="700" fill="#ff0099">${upvotes.toLocaleString()}</text>
<!-- divider -->
<line x1="300" y1="524" x2="300" y2="618" stroke="#222" stroke-width="1"/>
<!-- author + date -->
<text x="330" y="556" font-family="monospace" font-size="13" fill="#555" letter-spacing="1">PROPOSED BY</text>
<text x="330" y="585" font-family="monospace" font-size="20" fill="#aaa">${author}</text>
<text x="330" y="612" font-family="monospace" font-size="14" fill="#444">${date}</text>
<!-- CTA -->
<text x="1140" y="570" font-family="monospace" font-size="13" fill="#666" text-anchor="end">Sign this petition at</text>
<text x="1140" y="592" font-family="monospace" font-size="16" fill="#ff0099" text-anchor="end" font-weight="700">theradicalparty.com</text>
</svg>`;
} }
/** /**