|
10 | 10 | let suffixInput = $state(data.profile.postSuffix || ''); |
11 | 11 | let bskyBudget = $derived(BSKY_LIMIT - BSKY_OVERHEAD - prefixInput.length - suffixInput.length); |
12 | 12 |
|
| 13 | + // Live preview using a real diff |
| 14 | + const preview = data.previewData; |
| 15 | + let previewText = $derived(() => { |
| 16 | + if (!preview) return ''; |
| 17 | + const changes = [ |
| 18 | + preview.titleChanged ? 'Headline changed' : '', |
| 19 | + preview.contentChanged ? 'Content changed' : '' |
| 20 | + ].filter(Boolean).join(' & ') || 'Article updated'; |
| 21 | + const stats = `+${preview.charsAdded} / -${preview.charsRemoved} chars`; |
| 22 | + const prefix = prefixInput ? `${prefixInput} ` : ''; |
| 23 | + const suffix = suffixInput ? `\n\n${suffixInput}` : ''; |
| 24 | + return `${prefix}${changes} in "${preview.title}" (${preview.feedName})\n${stats}\n\nhttps://diff.example.com/diff/${preview.diffId}\nhttps://example.com/article${suffix}`; |
| 25 | + }); |
| 26 | + let previewCharCount = $derived(previewText().length); |
| 27 | +
|
13 | 28 | let fields = $derived((() => { |
14 | 29 | const f = [...(profile.fields || [])]; |
15 | 30 | while (f.length < 4) f.push({ name: '', value: '' }); |
|
120 | 135 | — title may be truncated |
121 | 136 | {/if} |
122 | 137 | </div> |
| 138 | + |
| 139 | + {#if preview} |
| 140 | + <div class="preview-cards"> |
| 141 | + <div class="preview-card preview-mastodon"> |
| 142 | + <div class="preview-header"> |
| 143 | + <span class="preview-icon">🐘</span> |
| 144 | + <span class="preview-label">ActivityPub preview</span> |
| 145 | + </div> |
| 146 | + <div class="preview-body">{previewText()}</div> |
| 147 | + <div class="preview-meta">{previewCharCount} chars (no limit)</div> |
| 148 | + </div> |
| 149 | + <div class="preview-card preview-bluesky"> |
| 150 | + <div class="preview-header"> |
| 151 | + <span class="preview-icon">🦋</span> |
| 152 | + <span class="preview-label">Bluesky preview</span> |
| 153 | + </div> |
| 154 | + <div class="preview-body" class:preview-truncated={previewCharCount > 300}>{previewText().slice(0, 300)}{#if previewCharCount > 300}...{/if}</div> |
| 155 | + <div class="preview-meta" class:budget-over={previewCharCount > 300}>{Math.min(previewCharCount, 300)}/300 chars</div> |
| 156 | + </div> |
| 157 | + </div> |
| 158 | + {/if} |
123 | 159 | </section> |
124 | 160 |
|
125 | 161 | <div class="actions"> |
|
190 | 226 | .budget-warn { color: #92400e; background: #fef3c7; } |
191 | 227 | .budget-over { color: var(--color-del-text); background: var(--color-del-bg); } |
192 | 228 |
|
| 229 | + .preview-cards { display: flex; gap: 1rem; margin-top: 1rem; flex-wrap: wrap; } |
| 230 | + .preview-card { flex: 1; min-width: 260px; border: 1px solid var(--color-border); border-radius: 0.5rem; overflow: hidden; background: white; } |
| 231 | + .preview-header { display: flex; align-items: center; gap: 0.4rem; padding: 0.5rem 0.75rem; background: #f8f8f8; border-bottom: 1px solid var(--color-border); font-size: 0.8rem; font-weight: 600; color: var(--color-muted); } |
| 232 | + .preview-icon { font-size: 1rem; } |
| 233 | + .preview-body { padding: 0.75rem; font-size: 0.85rem; line-height: 1.5; white-space: pre-wrap; word-break: break-word; color: var(--color-text); } |
| 234 | + .preview-truncated { color: var(--color-del-text); } |
| 235 | + .preview-meta { padding: 0.4rem 0.75rem; border-top: 1px solid var(--color-border); font-size: 0.75rem; color: var(--color-muted); background: #fafafa; } |
| 236 | + .preview-mastodon { border-left: 3px solid #6364ff; } |
| 237 | + .preview-bluesky { border-left: 3px solid #0085ff; } |
| 238 | +
|
193 | 239 | .danger-zone { margin-top: 3rem; padding-top: 1.5rem; border-top: 2px solid var(--color-del-bg); } |
194 | 240 | .danger-zone h2 { color: var(--color-del-text); border-bottom-color: var(--color-del-bg); } |
195 | 241 | .danger-zone p { font-size: 0.85rem; color: var(--color-muted); margin-bottom: 1rem; } |
|
0 commit comments