mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
## Summary - make mobile unread state visible with bold channel names, an animated Inbox badge, and swipe-to-toggle Inbox rows - add directional transitions for top-level mobile navigation - let mobile send while media uploads, with cancellable progress UI - normalize iOS and Android video uploads, attach poster frames, and improve native video playback ## Validation - `just mobile-check` - `just mobile-test` - `cargo test -p buzz-media` - Pixel smoke test - iPhone smoke test Desktop background uploads moved to #4522 so the two platforms can be reviewed independently. --------- Signed-off-by: kenny lopez <klopez4212@gmail.com> Signed-off-by: Tom Brow <tomb@block.xyz> Co-authored-by: leader <71e9f2c44a6932b6772caaaccda1911d010463c3e2c6c40410b8329956046801@buzz.block.builderlab.xyz> Co-authored-by: Tom Brow <tomb@block.xyz>
45 lines
1.5 KiB
Dart
45 lines
1.5 KiB
Dart
import 'read_state_format.dart';
|
|
import 'read_state_provider.dart';
|
|
|
|
/// Effective read timestamp for a single message: the newest of the channel
|
|
/// marker, the message's own `msg:` marker, and (for thread replies) the
|
|
/// thread's `thread:` marker — the same precedence the unread badge uses via
|
|
/// `observedUnreadEventReadAt`.
|
|
int? effectiveMessageReadAt(
|
|
ReadStateState readState, {
|
|
required String channelId,
|
|
required String messageId,
|
|
String? threadRootId,
|
|
}) {
|
|
return maxReadAt([
|
|
readState.effectiveTimestamp(channelId),
|
|
readState.effectiveTimestamp(msgContextKey(messageId)),
|
|
if (threadRootId != null)
|
|
readState.effectiveTimestamp(threadContextKey(threadRootId)),
|
|
]);
|
|
}
|
|
|
|
/// Whether a message should currently show as unread in the actions menu.
|
|
///
|
|
/// A message-level forced unread (from this menu) wins; otherwise the
|
|
/// timestamp precedence decides. A channel-level forced unread (from the
|
|
/// channel tile) is deliberately not consulted: it is a channel-scoped
|
|
/// choice, and letting it leak in here would make the message-level toggle
|
|
/// unable to round-trip without clearing the channel-level choice.
|
|
bool isMessageUnread(
|
|
ReadStateState readState, {
|
|
required String channelId,
|
|
required String messageId,
|
|
required int createdAt,
|
|
String? threadRootId,
|
|
}) {
|
|
if (readState.isForcedUnread(msgContextKey(messageId))) return true;
|
|
final readAt = effectiveMessageReadAt(
|
|
readState,
|
|
channelId: channelId,
|
|
messageId: messageId,
|
|
threadRootId: threadRootId,
|
|
);
|
|
return readAt == null || createdAt > readAt;
|
|
}
|