Skip to content

fix(chat): bypass draft-rune reactivity for the send button on iOS PWA#20

Merged
Nkburdick merged 2 commits intomainfrom
fix/send-button-ios-direct
Apr 24, 2026
Merged

fix(chat): bypass draft-rune reactivity for the send button on iOS PWA#20
Nkburdick merged 2 commits intomainfrom
fix/send-button-ios-direct

Conversation

@Nkburdick
Copy link
Copy Markdown
Owner

Second-attempt fix for the iOS PWA send button. PR #19 explicitly mirrored textarea into draft on oninput but Nick still reported no send action. This PR defensively removes draft-rune from the disabled= binding and reads textareaEl.value directly in sendCurrentMessage + post-send DOM clears. See commit message for full rationale.

Verified: bun run build ✅, bun run lint ✅, bun run test:unit 80/80 ✅.

🤖 Generated with Claude Code

Nkburdick and others added 2 commits April 24, 2026 10:35
Three issues in Nick's 2026-04-24 screenshot after PR #18:

1. Tapping the send arrow did nothing. Root cause: `bind:value={draft}`
   on the composer textarea wasn't reliably propagating to the `draft`
   rune in the iOS PWA runtime (same class as the onMount/$effect
   hydration issue — feedback_ios_pwa_hydration.md). With `draft` stuck
   at "", `disabled={sending || draft.trim() === ''}` stayed true and
   the button genuinely was disabled in the DOM. Fix: mirror the DOM
   value into `draft` explicitly inside `handleTextareaInput`, which
   fires on every keystroke. Event-handler-driven state updates work
   in iOS PWA even when bindings don't.

2. Project title header visibly overlapped the iPhone notch and the
   spacing below the project tabs was huge. Root cause: the chat
   thread page was designed as a full-screen takeover (app.css has
   `.app-shell:has([data-chat-thread]) .app-main { padding: 0 }` +
   hides the mobile tab bar + notification bell for exactly this
   mode), but the project layout's own header + tab bar kept
   rendering on top of the thread page. Result: double chrome,
   negative-margin safe-area math that breaks when there's no
   parent pt-safe-area to cancel, and empty vertical space where
   the thread page's own safe-area header then lands below the
   project tabs.

   Fix: suppress the project layout header + tab bar when we're on
   a chat thread route. Detected via regex against pathname —
   reactive to client nav and works on SSR. Thread page's own
   header now sits cleanly at the top of the viewport where its
   safe-area-inset-top padding is meaningful.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The PR #19 fix (explicit \`draft = el.value\` in oninput) wasn't enough
on iOS PWA — Nick still reported the send button doing nothing after
typing. Two remaining weak points:

1. \`disabled={sending || draft.trim() === ''}\` still gated the button
   on the draft rune. If Svelte 5 reactivity in the iOS PWA runtime
   fails to re-evaluate that expression when draft changes, the button
   stays visually+functionally disabled even when the textarea has
   text. Disabled <button> elements don't fire click events, so the
   tap produces no feedback.

2. \`sendCurrentMessage\` read \`draft.trim()\` internally. Same risk —
   if the rune never observed the update, the send aborts silently.

Fixes, stacked defensively:

- Send button \`disabled\` is now gated on \`sending\` only. Empty-text
  checks moved inside \`sendCurrentMessage\`, which now reads
  \`textareaEl.value\` directly as the source of truth and falls back
  to \`draft\` only if the element ref isn't bound.
- Post-send + post-error textarea clears explicitly set
  \`textareaEl.value\` alongside the rune, so bind:value not syncing
  the empty string back to the DOM doesn't leave stale text in the
  composer.

Net effect on iOS PWA: the button is always clickable (except during
an in-flight send), clicks always read a fresh textarea value, and
post-send clearing happens on the DOM regardless of bind:value.
Desktop and Android Chrome are unaffected — bind:value works there,
and the added DOM reads/writes are idempotent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 24, 2026

Warning

Rate limit exceeded

@Nkburdick has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 23 minutes and 54 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 23 minutes and 54 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e4368188-254f-46db-9565-bfbe43a94296

📥 Commits

Reviewing files that changed from the base of the PR and between 18567bd and 419058e.

📒 Files selected for processing (2)
  • src/routes/projects/[slug]/+layout.svelte
  • src/routes/projects/[slug]/chats/[threadId]/+page.svelte
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/send-button-ios-direct

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Nkburdick Nkburdick merged commit 7782311 into main Apr 24, 2026
2 checks passed
@Nkburdick Nkburdick deleted the fix/send-button-ios-direct branch April 24, 2026 18:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant