feat: Improved floating player bar

This commit is contained in:
PartyDonut 2025-07-31 16:24:41 +02:00
parent 82e09b3e0c
commit 013722fc96
8 changed files with 338 additions and 210 deletions

View file

@ -10,7 +10,6 @@ import 'package:fladder/routes/auto_router.dart';
import 'package:fladder/screens/shared/animated_fade_size.dart';
import 'package:fladder/screens/shared/nested_bottom_appbar.dart';
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
import 'package:fladder/util/theme_extensions.dart';
import 'package:fladder/widgets/navigation_scaffold/components/destination_model.dart';
import 'package:fladder/widgets/navigation_scaffold/components/fladder_app_bar.dart';
import 'package:fladder/widgets/navigation_scaffold/components/floating_player_bar.dart';
@ -58,9 +57,15 @@ class _NavigationScaffoldState extends ConsumerState<NavigationScaffold> {
final isDesktop = AdaptiveLayout.of(context).isDesktop;
final bottomPadding = isDesktop || kIsWeb ? 0.0 : MediaQuery.paddingOf(context).bottom;
final mediaQuery = MediaQuery.of(context);
final paddingOf = mediaQuery.padding;
final viewPaddingOf = mediaQuery.viewPadding;
final bottomPadding = isDesktop || kIsWeb ? 0.0 : paddingOf.bottom;
final bottomViewPadding = isDesktop || kIsWeb ? 0.0 : viewPaddingOf.bottom;
final isHomeScreen = currentIndex != -1;
return PopScope(
canPop: currentIndex == 0,
onPopInvokedWithResult: (didPop, result) {
@ -72,58 +77,66 @@ class _NavigationScaffoldState extends ConsumerState<NavigationScaffold> {
alignment: Alignment.bottomCenter,
children: [
Positioned.fill(
child: Padding(
padding: EdgeInsets.only(bottom: showPlayerBar ? floatingPlayerHeight - 12 + bottomPadding : 0),
child: Scaffold(
key: _key,
appBar: const FladderAppBar(),
extendBodyBehindAppBar: true,
resizeToAvoidBottomInset: false,
extendBody: true,
floatingActionButton: AdaptiveLayout.layoutModeOf(context) == LayoutMode.single && isHomeScreen
? widget.destinations.elementAtOrNull(currentIndex)?.floatingActionButton?.normal
: null,
drawer: homeRoutes.any((element) => element.name.contains(currentLocation))
? NestedNavigationDrawer(
actionButton: null,
toggleExpanded: (value) => _key.currentState?.closeDrawer(),
views: views,
destinations: widget.destinations,
currentLocation: currentLocation,
)
: null,
bottomNavigationBar: isHomeScreen && AdaptiveLayout.viewSizeOf(context) == ViewSize.phone
? HideOnScroll(
controller: AdaptiveLayout.scrollOf(context),
forceHide: !homeRoutes.any((element) => element.name.contains(currentLocation)),
child: NestedBottomAppBar(
child: SizedBox(
height: 65,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: widget.destinations
.map(
(destination) => destination.toNavigationButton(
widget.currentRouteName == destination.route?.routeName, false, false),
)
.toList(),
child: MediaQuery(
data: mediaQuery.copyWith(
padding: paddingOf.copyWith(
bottom: showPlayerBar ? floatingPlayerHeight(context) + 12 + bottomPadding : bottomPadding),
viewPadding: viewPaddingOf.copyWith(
bottom: showPlayerBar ? floatingPlayerHeight(context) + bottomViewPadding : bottomViewPadding),
),
//Builder to correctly apply new padding
child: Builder(builder: (context) {
return Scaffold(
key: _key,
appBar: const FladderAppBar(),
extendBodyBehindAppBar: true,
resizeToAvoidBottomInset: false,
extendBody: true,
floatingActionButton: AdaptiveLayout.layoutModeOf(context) == LayoutMode.single && isHomeScreen
? widget.destinations.elementAtOrNull(currentIndex)?.floatingActionButton?.normal
: null,
drawer: homeRoutes.any((element) => element.name.contains(currentLocation))
? NestedNavigationDrawer(
actionButton: null,
toggleExpanded: (value) => _key.currentState?.closeDrawer(),
views: views,
destinations: widget.destinations,
currentLocation: currentLocation,
)
: null,
bottomNavigationBar: isHomeScreen && AdaptiveLayout.viewSizeOf(context) == ViewSize.phone
? HideOnScroll(
controller: AdaptiveLayout.scrollOf(context),
forceHide: !homeRoutes.any((element) => element.name.contains(currentLocation)),
child: NestedBottomAppBar(
child: SizedBox(
height: 65,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: widget.destinations
.map(
(destination) => destination.toNavigationButton(
widget.currentRouteName == destination.route?.routeName, false, false),
)
.toList(),
),
),
),
),
)
: null,
body: widget.nestedChild != null
? NavigationBody(
child: widget.nestedChild!,
parentContext: context,
currentIndex: currentIndex,
destinations: widget.destinations,
currentLocation: currentLocation,
drawerKey: _key,
)
: null,
),
)
: null,
body: widget.nestedChild != null
? NavigationBody(
child: widget.nestedChild!,
parentContext: context,
currentIndex: currentIndex,
destinations: widget.destinations,
currentLocation: currentLocation,
drawerKey: _key,
)
: null,
);
}),
),
),
Material(
@ -131,19 +144,7 @@ class _NavigationScaffoldState extends ConsumerState<NavigationScaffold> {
child: AnimatedFadeSize(
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: context.colors.surface,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12),
),
),
child: showPlayerBar
? Padding(
padding: EdgeInsets.only(bottom: bottomPadding),
child: const FloatingPlayerBar(),
)
: const SizedBox.shrink(),
child: showPlayerBar ? const FloatingPlayerBar() : const SizedBox.shrink(),
),
),
)