mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-27 00:05:25 +00:00
0d251ad20c119ff5bc3e94470fd25e5af7fc0949
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0d251ad20c |
Require confirmation before deleting a received image; label media controls (#1358)
* Require confirmation before deleting a received image; label media controls
Double-tapping a received image permanently deleted the message and its
file — no confirmation, no undo — while double-tap is the most ingrained
photo gesture on mobile, and it raced the reveal tap via
`.exclusively(before:)`. A mesh may never re-deliver that image, so an
accidental double-tap can destroy the only copy.
- Remove the double-tap-to-delete gesture. Delete moves into a
long-press context menu behind a confirmation dialog ("this cannot be
undone — the sender may not be in range to send it again"), alongside
explicit open and hide-image actions (the swipe-to-re-blur was
undiscoverable). Taps now only reveal and open.
- The blur overlay says "tap to reveal" instead of a bare eye-slash.
- Add the first accessibility support to these media views: labeled
image states (hidden/revealed/sending) with custom actions, labeled
voice play/pause with the duration as the value, and labeled cancel
buttons.
Delete remains available and its underlying behavior is unchanged — it's
just gated. New strings are added source-language (en) only.
* Expose the in-flight cancel button to VoiceOver
The image tile uses accessibilityElement(children: .ignore), which
collapses the whole subtree — including the visible cancel button shown
while a send is in flight — into one element. VoiceOver users could not
cancel an in-progress image send. Add a cancel accessibility action for
the sending state.
* Mark the accessibility delete action destructive too
The context-menu delete already uses role: .destructive; the matching
accessibility action did not. Make them consistent.
* Deduplicate image actions and align accessibility labels with convention
Extract the open/hide/delete button set shared by the context menu and
accessibilityActions into a single @ViewBuilder so the two can't drift.
Move the interaction hints out of the accessibility labels into
accessibilityHint (labels stay nouns; "tap to reveal" was wrong for
VoiceOver activation anyway), and rename the blurred-state action to
"reveal image" since it reveals rather than opens.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Offer cancel-send in the context menu while an image is sending
The context menu body was empty during sends, which some OS versions
still present as an empty preview. The accessibility path already
exposed a cancel-send action in that state; share the same button with
the context menu so pointer/touch users get a cancel path too.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Label broken images honestly and drop actions that need the file
When the image file fails to load, the placeholder kept the "hidden
image"/"image" accessibility label with a reveal/open hint, and the
context menu still offered open/reveal on a URL that will not load.
Track the failed load, announce "image unavailable" with no interaction
hint, show a broken-photo glyph instead of an endless spinner, disable
the reveal/open gestures, and drop open/hide/reveal from the context
menu and accessibility actions -- keeping delete so received broken
attachments can still be cleaned up.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: jack <212554440+jackjackbits@users.noreply.github.com>
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
c8ceac1968 |
Give private DMs an unmistakable visual signature (#1357)
* Give private DMs an unmistakable visual signature An open DM renders identically to the public room — same view, same green-on-black surface, with a small header name and two orange icons as the only cues. For this audience the cost of misreading "am I in the encrypted DM or the public channel?" is severe: sensitive text typed into the wrong composer. Four presentation-layer cues; no formatter or cache changes: - The composer placeholder states the destination instead of a generic prompt: "message @jack — private" in a DM, "message #mesh — public, nearby" on mesh, "message #9q8yy — public" in a geohash channel. - A persistent lock caption sits above the DM composer. It reads "private · end-to-end encrypted" only once the Noise session is actually secured or verified, and "private conversation" before that — the caption must not overstate encryption mid-handshake. - The DM sheet header carries a faint orange wash (6%), extending the existing orange self-accent to the chrome. - Each private message row is prefixed with a small orange lock glyph (view-layer, hidden from VoiceOver — the caption carries the semantic; the cached AttributedString formatter is untouched). New strings are added source-language (en) only. * Fix geohash-DM caption and placeholder Two carve/review follow-ups: - The privacy caption showed "private conversation" for geohash DMs, implying they are not encrypted — but geohash DMs are NIP-17 gift-wrapped (always end-to-end encrypted), they just carry no Noise session status. Show the encrypted caption for geohash DMs and for secured Noise sessions; the pre-secured wording now applies only while a mesh handshake is still in progress. - The private-chat placeholder prepended "@" to the partner name, which for a geohash DM (whose display name is already "#geohash/@name") produced a doubled "@". The "@" is now added only for mesh nicknames. * Make the DM header orange wash visible in the matrix theme The 6% orange background was chained after .themedSurface(), so in the default matrix theme (whose themedSurface paints an opaque background) the wash sat behind the surface and never rendered — it was only visible in liquid glass. Apply the orange tint before .themedSurface() so it layers in front of the themed background. * Align DM lock glyph across text and media rows; keep header wash visible under glass Media rows in a private conversation now get the same leading lock glyph as text rows, so left edges line up instead of misaligning by the glyph's width. The DM header's orange wash gets a higher opacity under the liquid-glass theme, where themedSurface() adds no opaque backing and 6% orange disappears into the backdrop gradient. Also drops the dead sender != "system" guard in TextMessageView — system messages are routed to systemMessageRow before this view is built. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Remove orphaned content.input.message_placeholder from the string catalog The destination-stating placeholders replaced its last code reference; nothing on the branch resolves this key anymore. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: jack <212554440+jackjackbits@users.noreply.github.com> Co-authored-by: jack <jackjackbits@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
9ccff9cce4 |
Make private-message delivery status legible and accessible (#1356)
* Make private-message delivery status legible and accessible
The delivery indicator is the most stress-relevant signal in an
off-grid messenger, but it is hard to read:
- The status glyphs are 10pt icons whose only explanation is a
`.help()` tooltip, which does not exist on iOS.
- Delivered vs read is the same double-checkmark distinguished only by
colour.
- No case carries an accessibility label, so VoiceOver announces
nothing.
- Two failure reasons ("Not delivered", "Encryption failed") bypass the
localized reason catalog and are hardcoded English.
Changes (presentation only; the DeliveryStatus enum and the
contract-tested `displayText` are untouched):
- Add `DeliveryStatus.bitchatDescription`, a localized app-layer
description, used as the macOS tooltip, a VoiceOver label on every
status glyph, and — on iOS, where tooltips don't exist — a
tap-to-reveal caption under the message.
- Failure reasons stay visible as a red caption without a tap.
- Read vs delivered is now legible without colour: read uses
filled-circle checkmarks.
- Route the two hardcoded failure reasons through the localized catalog.
New strings are added source-language (en) only.
* Show the failure reason on failed media messages too
TextMessageView gained a visible red failure caption (the status
glyph's .help() tooltip does not exist on iOS), but MediaMessageView
still rendered the bare glyph — so a failed voice-note or image send
showed only a 10pt red triangle with no reason on iOS. Add the same
failure caption to media messages.
* Collapse revealed delivery detail when the status changes
A caption revealed while a message was "sending" stayed open and
silently morphed through later statuses (sent, delivered, read).
Reset showDeliveryDetail when the snapshotted DeliveryStatus changes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Add tap-to-reveal delivery detail to media rows
Media rows showed the same delivery glyphs as text rows but offered no
way to explain them on iOS, where .help() tooltips don't exist. Mirror
the text-row pattern: the glyph is now a button that reveals the
localized status caption below the header, failure reasons stay
visible without a tap, and the revealed caption collapses when the
status advances.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Localize the remaining voice-note failure reasons
ChatMediaTransferCoordinator still passed hardcoded English reasons
into .failed(reason:), which now surface verbatim in the always-visible
failure caption. Route them through String(localized:) under the
existing content.delivery.reason.* convention.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
e191e9c6f2 |
Fix slash-command suggestions that insert commands the processor rejects (#1354)
The autocomplete panel is the only in-app surface for discovering slash
commands, but several suggestions do not match what CommandProcessor
accepts, so tapping them inserts a command that returns "unknown
command":
- CommandInfo suggests /dm, /favorite, /unfavorite, but the processor
only handles /m, /msg, /fav, /unfav. Aliases are aligned to the
accepted spellings (msg, fav, unfav).
- Favorites are suggested only in geohash contexts (isGeoPublic ||
isGeoDM) — exactly where the processor rejects them ("favorites are
only for mesh peers"). The gating is inverted so they appear in mesh,
where they work.
Also, small related fixes to the discovery surface:
- /help is now handled (the ChatViewModel command docstring already
claimed it existed); it prints a local system line listing the valid
commands, and the unknown-command error points at it.
- The suggestion panel keeps the matched command's usage row (e.g.
"/msg <nickname>") visible while arguments are typed, instead of
vanishing at the first space; in that mode the row is informational
and no longer overwrites the draft on tap.
New string is added source-language (en) only. The CommandInfo contract
test is updated to the corrected metadata.
|