Space never presses a focused button; chat toasts open the chat; plain wheel always scrolls the page

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
foxyzandClaude Opus 5.5 committed 2026-10-09 07:52:48 +03:00
1 parent cf80bb2167
commit f2272d7980
8 files changed
+56 -21

No files matched your search

+5 -1
View File
@@ -669,7 +669,11 @@ class AppShellState extends State<AppShell> with SingleTickerProviderStateMixin
),
),
if (online && _shown != PlayerMode.none) _playerLayer(area),
Positioned(left: 16, bottom: _fullscreen ? 90 : 16, child: const PartyToasts()),
Positioned(left: 16, bottom: _fullscreen ? 90 : 16, child: PartyToasts(
onOpenChat: () {
if (!_chatOpen) _toggleChat();
},
)),
],
);
});
+7 -7
View File
@@ -90,17 +90,17 @@ Future<T?> showPopover<T>(
},
);
/// Horizontal lists for mouse users: drag with the mouse, and the plain
/// (vertical) wheel moves them sideways. At either end the wheel is left
/// to the page, so a row never traps vertical scrolling.
/// Horizontal lists for mouse users: drag with the mouse or Shift+wheel;
/// the plain wheel stays vertical (the page scrolls under the cursor, not
/// the row).
class HScroll extends StatefulWidget {
final ScrollController? controller;
final Widget Function(ScrollController controller) builder;
/// Map the plain (vertical) wheel to sideways scrolling. Off where the
/// children scroll vertically themselves (the schedule's day columns):
/// there only mouse drag and Shift+wheel move sideways.
/// Also map the plain (vertical) wheel to sideways scrolling (at either
/// end the wheel goes to the page). Off by default: one wheel doing two
/// things was confusing.
final bool wheel;
const HScroll({super.key, this.controller, required this.builder, this.wheel = true});
const HScroll({super.key, this.controller, required this.builder, this.wheel = false});
@override
State<HScroll> createState() => _HScrollState();
@@ -92,6 +92,7 @@ class PartyStrip extends StatelessWidget {
message: 'Your profile',
child: InkWell(
key: const ValueKey('strip-profile'),
canRequestFocus: false,
customBorder: const CircleBorder(),
onTap: onProfile,
child: StatusAvatar(
+32 -5
View File
@@ -43,10 +43,13 @@ ShellToast shellToastFor(ToastItem t, AvatarInfo Function(String name) avatar) {
}
/// The coordinator's toasts as cards with avatars, bottom-left: each
/// slides in, stays [life], then slides out and collapses its gap.
/// slides in, stays [life], then slides out and collapses its gap. A click
/// on a chat toast opens the chat ([onOpenChat]); the rest let clicks
/// through.
class PartyToasts extends StatefulWidget {
final Duration life;
const PartyToasts({super.key, this.life = const Duration(seconds: 5)});
final VoidCallback? onOpenChat;
const PartyToasts({super.key, this.life = const Duration(seconds: 5), this.onOpenChat});
@override
State<PartyToasts> createState() => _PartyToastsState();
@@ -101,13 +104,37 @@ class _PartyToastsState extends State<PartyToasts> {
super.dispose();
}
void _open(ShellToast t) {
widget.onOpenChat?.call();
setState(() => t.leaving = true);
}
@override
Widget build(BuildContext context) => IgnorePointer(child: ToastColumn(toasts: _shown.reversed.take(6).toList().reversed.toList()));
Widget build(BuildContext context) => ToastColumn(
toasts: _shown.reversed.take(6).toList().reversed.toList(),
onTap: widget.onOpenChat == null ? null : _open,
);
}
class ToastColumn extends StatelessWidget {
final List<ShellToast> toasts;
const ToastColumn({super.key, required this.toasts});
/// Clicks on chat toasts; null (or any other toast): clicks pass through.
final ValueChanged<ShellToast>? onTap;
const ToastColumn({super.key, required this.toasts, this.onTap});
Widget _card(ShellToast t) {
final card = ToastCard(toast: t);
final tap = onTap;
if (!t.chat || tap == null || t.leaving) return IgnorePointer(child: card);
return MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
key: ValueKey('toast-open-chat-${t.id}'),
onTap: () => tap(t),
child: card,
),
);
}
@override
Widget build(BuildContext context) {
@@ -139,7 +166,7 @@ class ToastColumn extends StatelessWidget {
duration: easeTime,
curve: ease,
opacity: t.leaving ? 0 : 1,
child: Padding(padding: const EdgeInsets.only(top: 8), child: ToastCard(toast: t)),
child: Padding(padding: const EdgeInsets.only(top: 8), child: _card(t)),
),
),
),