Polish floating bottom bar: elevation, height, overlap, and FAB shape

- Give the floating bar and search satellite the app's one shadow
  (nooDialogShadow) plus a smaller, tighter height on both platforms.
- Let every tab's scrollable list compute its own bottom clearance
  (bottomBarClearance) instead of a flat 100px, so the floating bar no
  longer overlaps the last row/card.
- Square the Android upload FAB off to a rounded-square radius when the
  bottom bar is attached, keeping it fully round only when floating.
- Let a swipe on a file row trigger its action directly once dragged
  past 1.8x the reveal width, instead of requiring a second tap.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-30 16:30:14 -04:00
co-authored by Claude Sonnet 5
parent 5f4caa2a3b
commit 5e5acc3fc6
18 changed files with 361 additions and 55 deletions
+1 -1
View File
@@ -92,7 +92,7 @@ class ActivityView extends StatelessWidget {
final List<Widget> contentSlivers = [
const SliverToBoxAdapter(child: SizedBox(height: NooSpace.md)),
feed,
...tabBottomInsetSlivers,
...tabBottomInsetSlivers(context),
];
final scrollView = CustomScrollView(
+2 -1
View File
@@ -29,6 +29,7 @@ import '../widgets/noo/overlays/noo_sheet.dart';
import '../widgets/noo/core/noo_button.dart';
import '../widgets/share_sheet.dart';
import '../widgets/sticky_header_delegate.dart';
import '../widgets/tabs/tab_state_slivers.dart';
import '../widgets/synced_header_scaffold.dart' show formatBytes;
import 'file_viewer_screen.dart';
import 'move_copy_destination_picker.dart';
@@ -638,7 +639,7 @@ class _FavoritesViewState extends State<FavoritesView> {
}, childCount: favorites.length),
),
),
const SliverToBoxAdapter(child: SizedBox(height: 100)),
SliverToBoxAdapter(child: SizedBox(height: bottomBarClearance(context))),
];
return PopScope(
+11
View File
@@ -39,11 +39,13 @@ import '../widgets/noo/lists/noo_selection_bar.dart';
import '../widgets/noo/lists/noo_settings_row.dart';
import '../widgets/noo/lists/noo_summary_card.dart';
import '../widgets/noo/media/noo_grid_card.dart';
import '../widgets/noo/nav/noo_bottom_bar.dart';
import '../widgets/noo/noo_layout.dart';
import '../widgets/noo/overlays/noo_sheet.dart';
import '../widgets/share_sheet.dart';
import '../widgets/sticky_header_delegate.dart';
import '../widgets/synced_header_scaffold.dart' show formatBytes;
import '../widgets/tabs/tab_state_slivers.dart';
import 'file_viewer_screen.dart';
import 'move_copy_destination_picker.dart';
@@ -815,6 +817,15 @@ class _FilesViewState extends State<FilesView> {
}, childCount: browser.items.length),
),
),
// List/grid/table above only pad NooSpace.lg at the bottom - plenty
// once Scaffold shrinks the body above an attached bar, but floating
// draws the body behind the bar instead, so it needs the bar's own
// footprint added on top or the last row ends up under it.
if (context.watch<SettingsController>().bottomBarStyle ==
NooBottomBarStyle.floating)
SliverToBoxAdapter(
child: SizedBox(height: bottomBarClearance(context)),
),
];
return PopScope(
+5 -3
View File
@@ -30,6 +30,7 @@ import '../widgets/noo/overlays/noo_sheet.dart';
import '../widgets/share_sheet.dart';
import '../widgets/sort_menu_button.dart' show sortFieldLabel;
import '../widgets/sticky_header_delegate.dart';
import '../widgets/tabs/tab_state_slivers.dart';
import 'file_viewer_screen.dart';
import 'move_copy_destination_picker.dart';
@@ -346,9 +347,10 @@ class _PhotosViewState extends State<PhotosView> {
),
],
// Fixed clearance so the last row isn't hidden behind the floating
// nav bar, regardless of grid length.
const SliverToBoxAdapter(child: SizedBox(height: 100)),
// Clearance so the last row isn't hidden behind the nav bar,
// regardless of grid length - see `bottomBarClearance`'s own doc
// comment for why this has to be dynamic rather than a flat 100.
SliverToBoxAdapter(child: SizedBox(height: bottomBarClearance(context))),
];
return PopScope(
+1 -1
View File
@@ -74,7 +74,7 @@ class _RecentViewState extends State<RecentView> {
_buildDesktopTable(context, groups)
else
_buildMobileGroups(context, groups),
...tabBottomInsetSlivers,
...tabBottomInsetSlivers(context),
];
return ColoredBox(
+1 -1
View File
@@ -120,7 +120,7 @@ class _SharesViewState extends State<SharesView> {
_buildDesktopTable(context, shares)
else
_buildMobileList(context, shares),
...tabBottomInsetSlivers,
...tabBottomInsetSlivers(context),
];
return ColoredBox(
+1 -1
View File
@@ -89,7 +89,7 @@ class _TrashViewState extends State<TrashView> {
_buildDesktopTable(context, trash)
else
_buildMobileList(context, trash),
...tabBottomInsetSlivers,
...tabBottomInsetSlivers(context),
];
return ColoredBox(