- MessageInput: paperclip button (team-only, controlled by teamUserIds
from ThreadDetail) uploads through the media service and hands the URL
to the WebSocket; Enter now inserts a newline — sending is button-only
since accidental Enter-sends were noisy for staff replies.
- MessageBubble: renders image messages inline (tap to open), shows the
coworker's username at the top of team-side bubbles so staff can tell
who typed what.
- MessageList / ThreadChatPage: any message from a store team member
(owner or active staff) renders on the "our" side of the bubble even
for a viewer who isn't the sender, using team_user_ids from
ThreadDetail. Delete option stays gated to the actual sender.
- ThreadsPage: inbox now shows smart-relative timestamps
(today HH:MM / دیروز HH:MM / N روز پیش / Persian date), plus a
reply-state icon per row (red bell = customer waiting, blue double-check
= you replied and they've seen it, nothing = you replied not yet seen).
Image-only last messages preview as "📷 تصویر".
- Push notifications: on mount we re-POST the current PushSubscription so
a browser-rotated sub or a backend row deleted after a 410 auto-heals.
- useWebSocket: SendMessagePayload and NewMessageEvent carry image_url so
the server relay can round-trip images.
- API types: MessageList.imageUrl, LastMessage.imageUrl,
ThreadList.lastMessageFromTeam/otherPartySeenLast, ThreadDetail.teamUserIds.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Content was drawing under the iOS status bar and home indicator because
the app uses viewport-fit=cover + black-translucent but the fixed/sticky
chrome didn't reserve the safe areas.
- bottom nav (MyLayout): move the 50px row into an inner box and let the
bar extend by env(safe-area-inset-bottom) so icons sit above the home
indicator (previously the fixed height clipped the inset padding).
- top headers gain env(safe-area-inset-top): HomePageTopBar, ExploreTopBar,
SearchTopBar, CartHeader, ChatHeader, and wrapper-padded HeaderWithSupport
/ ProfilePagesHeader (so their absolutely-positioned buttons shift too).
- chat input pads bottom by the inset; chat scroll area height accounts for
the taller header/input.
- _index.tsx no longer overrides the viewport meta (it was dropping
viewport-fit=cover on the home page); the global one in root.tsx wins.
env(safe-area-inset-*) is 0 on non-notch devices, so desktop/Android render
identically — only iOS gains the padding.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>