Files
buzz/mobile/lib/shared/widgets/directional_transition_scope.dart
feccf4eabc Polish mobile inbox and media flows (#4512)
## 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>
2026-08-04 00:05:13 -07:00

68 lines
2.1 KiB
Dart

import 'package:flutter/material.dart';
/// Supplies a shared directional entrance to separate foreground surfaces.
///
/// Descendants opt in with [DirectionalTransitionMotion], which lets a page
/// move its body and app-bar content together while leaving decorative
/// backgrounds stationary.
class DirectionalTransitionScope extends InheritedWidget {
/// Horizontal displacement remaining in the transition.
final double horizontalOffset;
/// Current foreground opacity, from zero to one.
final double opacity;
/// Creates a directional transition scope.
const DirectionalTransitionScope({
super.key,
required this.horizontalOffset,
required this.opacity,
required super.child,
});
/// Returns the closest transition, or null outside a transitioning surface.
static DirectionalTransitionScope? maybeOf(BuildContext context) =>
context.dependOnInheritedWidgetOfExactType<DirectionalTransitionScope>();
@override
bool updateShouldNotify(DirectionalTransitionScope oldWidget) =>
horizontalOffset != oldWidget.horizontalOffset ||
opacity != oldWidget.opacity;
}
/// Applies the nearest [DirectionalTransitionScope] to one foreground layer.
class DirectionalTransitionMotion extends StatelessWidget {
/// Foreground content that participates in the shared transition.
final Widget child;
/// Optional key for inspecting the composited translation layer.
final Key? transformKey;
/// Optional key for inspecting the composited opacity layer.
final Key? opacityKey;
/// Creates a foreground transition participant.
const DirectionalTransitionMotion({
super.key,
required this.child,
this.transformKey,
this.opacityKey,
});
@override
Widget build(BuildContext context) {
final transition = DirectionalTransitionScope.maybeOf(context);
if (transition == null) return child;
return Transform.translate(
key: transformKey,
offset: Offset(transition.horizontalOffset, 0),
child: Opacity(
key: opacityKey,
opacity: transition.opacity,
child: child,
),
);
}
}