aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-09-10 11:25:36 -0700
committerAdam Soltys <[email protected]>2026-09-10 11:25:36 -0700
commit7ff99d97a544e1665ddaafd8d80c0dd9ba3131ac (patch)
treeab2f7ad8d763d6c1147a5a2518ee08401a9c7c8f /src/features
parentfaa20f7380a517f04395b2395616d75e24007fdd (diff)
downloadcoinosv3-7ff99d97a544e1665ddaafd8d80c0dd9ba3131ac.tar.gz
coinosv3-7ff99d97a544e1665ddaafd8d80c0dd9ba3131ac.zip
Profile posts keep a draft across reloads, like DMs and channels do.
The new-post composer held its text in a transient ui field, so the reload that reconnects a signer (or any reload) lost the post. It now rides the same persisted draft store under a 'post' key: the composer reopens with the text after a reload, posting clears it, Cancel closes the composer and keeps the text for next time. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Nw1Dijik1tLVKRM1WkU7xE
Diffstat (limited to 'src/features')
-rw-r--r--src/features/messages.js17
1 files changed, 12 insertions, 5 deletions
diff --git a/src/features/messages.js b/src/features/messages.js
index a57ec8e..1eb3e41 100644
--- a/src/features/messages.js
+++ b/src/features/messages.js
@@ -605,6 +605,7 @@ export function messagesFeature(ctx) {
// debounce so typing doesn't hammer storage.
const sessionDrafts = new Map();
let draftPersist = 0;
+ const POST_DRAFT = 'post'; // the profile page's new-post composer
const draftFor = (key) =>
(sessionDrafts.has(key) ? sessionDrafts.get(key) : (st().drafts || {})[key] || '');
function setDraft(key, text) {
@@ -2481,25 +2482,31 @@ export function messagesFeature(ctx) {
? h('div', { class: 'col', style: 'gap:8px' },
h('div', { class: 'row gap6 wrap' },
h('button', { class: 'btn-primary grow', onClick: openEditor }, t('profEdit')),
- h('button', { class: 'grow', onClick: () => { ui.profCompose = ui.profCompose == null ? '' : null; render(); } }, t('profNewPost'))),
- ui.profCompose == null ? null : h('div', { class: 'col', style: 'gap:8px' },
+ h('button', { class: 'grow', onClick: () => { ui.profCompose = ui.profCompose == null ? draftFor(POST_DRAFT) : null; render(); } }, t('profNewPost'))),
+ // The post draft rides the same persisted draft store as DMs
+ // and channels: a reload (say, to reconnect a signer) brings
+ // the half-written post back, composer open. Posting clears
+ // it; Cancel just closes the composer and keeps the text.
+ (ui.profCompose == null && !draftFor(POST_DRAFT)) ? null : h('div', { class: 'col', style: 'gap:8px' },
h('textarea', {
rows: '3', placeholder: t('profComposePh'),
style: 'font-family:var(--sans);min-height:64px',
- value: ui.profCompose,
- onInput: (ev) => { ui.profCompose = ev.target.value; },
+ value: ui.profCompose == null ? draftFor(POST_DRAFT) : ui.profCompose,
+ onInput: (ev) => { ui.profCompose = ev.target.value; setDraft(POST_DRAFT, ev.target.value); },
}),
h('div', { class: 'row gap6' },
h('button', { class: 'btn-primary grow', onClick: async () => {
- const text = (ui.profCompose || '').trim();
+ const text = (ui.profCompose == null ? draftFor(POST_DRAFT) : ui.profCompose || '').trim();
if (!text) return;
// the post is on screen instantly (publishPost is
// optimistic) — close the composer now; a failure
// reopens it with the text intact
ui.profCompose = null;
+ setDraft(POST_DRAFT, '');
try { await publishPost(text); toast(t('profPosted')); }
catch (e) {
ui.profCompose = text;
+ setDraft(POST_DRAFT, text);
if (!e.silent) toast(e.message || String(e));
render();
}