Files
noo/lib/widgets/viewer/viewer_icon_button.dart
ayushya 0abea46b1c Fix sheet peek for async content, and rework several screens' details
showNooSheet's peek detection previously measured content once, right
after the first frame - Details' Versions/Activity tabs fetch their
data asynchronously, so that one-shot measurement only ever saw the
initial loading-spinner height, never the eventual (often long) list,
and the sheet still snapped to full height once data arrived. Replaced
it with a ScrollMetricsNotification-based check that keeps content
capped at the peek height from frame one and upgrades to a draggable
sheet whenever it actually overflows that cap, however and whenever
that happens - fixed for good this time, with a regression test that
mirrors the async-load shape.

Also, in the same pass:
- Upload/Move/Copy's bottom bar meta line now always reads as a count
  ("Uploading 3 items"), never a filename for the single-item case,
  and is centered rather than left-aligned - matches the approved
  design and removes a bespoke marquee/chip implementation that only
  Upload had.
- Upload/Move/Copy now show the same FilesControlsRow (sort, filter,
  List/Grid) Files itself uses, including a folder-grid rendering
  path for when List/Grid is set to grid.
- Files' filter chip reads "Filters" instead of "All types" when idle.
- Trash's overflow button - whose only action is "Delete forever" -
  is now a direct delete icon (mobile) / "Delete" danger pill
  (desktop) instead of a generic "..." menu that hid a single action
  behind an extra tap.
- The media viewer's floating chrome (top bar, bottom action bar,
  video transport row) now follows the app's light/dark theme instead
  of a fixed dark panel - a dark panel read as out of place over a
  light-theme stage. Panel tint and icon/text colors come from the
  theme's own surface/fg1 tokens (at a higher blur opacity to stay
  legible over arbitrary photo/video brightness), and the edge scrim
  gradients fade toward the panel's own tint instead of a fixed black.
  Mirrored the same change into the design canvas's Main.dc.html/
  MainAndroid.dc.html mockups (now with a theme prop) so they match.
2026-09-28 19:26:18 -04:00

48 lines
1.6 KiB
Dart

import 'package:flutter/material.dart';
import '../../theme/design_tokens.dart';
/// Icon-only action button for the media viewer's floating chrome (top bar,
/// bottom action bar, video transport controls) - a fixed 22px icon in a
/// round hit box. Colored from [NooColors.fg1] by default, matching
/// [FrostedGlassContainer]'s own theme-following panel underneath it (both
/// used to be fixed white-on-black regardless of theme - see their git
/// history). Kept as one small widget so every floating control in this
/// screen looks the same instead of drifting apart across the three call
/// sites that need one.
class ViewerIconButton extends StatelessWidget {
final IconData icon;
final String tooltip;
final VoidCallback? onTap;
/// Overrides the default [NooColors.fg1] (e.g. `danger` for delete,
/// `accent-text` for a favorited state). Ignored while [onTap] is null -
/// a disabled button always dims regardless of its normal color.
final Color? color;
const ViewerIconButton({
super.key,
required this.icon,
required this.tooltip,
required this.onTap,
this.color,
});
@override
Widget build(BuildContext context) {
final fg1 = context.nooColors.fg1;
final fg = onTap == null ? fg1.withValues(alpha: 0.4) : (color ?? fg1);
return Tooltip(
message: tooltip,
child: InkWell(
onTap: onTap,
customBorder: const CircleBorder(),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
child: Icon(icon, color: fg, size: 22),
),
),
);
}
}