diff --git a/script/render-preview.mjs b/script/render-preview.mjs index 1e88abc..c74d6ea 100644 --- a/script/render-preview.mjs +++ b/script/render-preview.mjs @@ -39,6 +39,7 @@ const sample = { }, ], unsubscribeUrl: 'https://app.flotilla.social/unsubscribe?token=abc123', + settingsUrl: 'https://app.flotilla.social/settings/alerts', } const source = readFileSync(templatePath, 'utf8') diff --git a/src/digest.ts b/src/digest.ts index d18c515..334a2c8 100644 --- a/src/digest.ts +++ b/src/digest.ts @@ -104,6 +104,7 @@ export class Digest { for (const pk of pubkeys) { try { await loadProfile(pk) + await waitForProfile(pk) } catch { // pass } @@ -175,4 +176,18 @@ const getFormatter = () => { timeStyle: 'short', timeZone: 'UTC', }) +} + +// Poll until the profile lands in the repository or hits a timeout. The load +// promise can resolve before sharedLoad writes the event to the store, so only +// the profile's presence here guarantees its avatar/name. +const waitForProfile = async (pubkey: string, timeoutMs = 5000) => { + const deadline = Date.now() + timeoutMs + + while (Date.now() < deadline) { + if (profilesByPubkey.get().get(pubkey)) { + return + } + await new Promise(r => setTimeout(r, 200)) + } } \ No newline at end of file diff --git a/src/emails/digest.mjml b/src/emails/digest.mjml index 53f08cc..5d6525d 100644 --- a/src/emails/digest.mjml +++ b/src/emails/digest.mjml @@ -19,6 +19,7 @@ .event-stats { margin-top: 8px; color: #64748b; font-size: 13px; } .stat-item { display: inline-flex; align-items: center; margin-right: 12px; } .footer { font-family: Inter, Helvetica, Arial, sans-serif; color: #94a3b8; font-size: 12px; line-height: 1.5; } + .footer a { color: #7161FF; text-decoration: underline; } .logo { max-width: 48px; max-height: 48px; } a { text-decoration: none; } @@ -57,7 +58,7 @@