feature: Rework responsive layout (#217)

Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
PartyDonut 2025-02-07 15:55:01 +01:00 committed by GitHub
parent e07f280124
commit 8012fdcea8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
48 changed files with 1468 additions and 1040 deletions

View file

@ -1,12 +1,15 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:auto_route/auto_route.dart';
import 'package:collection/collection.dart';
import 'package:ficonsax/ficonsax.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/models/settings/home_settings_model.dart';
import 'package:fladder/providers/settings/client_settings_provider.dart';
import 'package:fladder/providers/views_provider.dart';
import 'package:fladder/routes/auto_router.dart';
import 'package:fladder/routes/auto_router.gr.dart';
import 'package:fladder/screens/shared/animated_fade_size.dart';
import 'package:fladder/util/adaptive_layout.dart';
@ -50,6 +53,8 @@ class _NavigationBodyState extends ConsumerState<NavigationBody> {
@override
Widget build(BuildContext context) {
final views = ref.watch(viewsProvider.select((value) => value.views));
final hasOverlay = AdaptiveLayout.layoutModeOf(context) == LayoutMode.dual ||
homeRoutes.any((element) => element.name.contains(context.router.current.name));
ref.listen(
clientSettingsProvider,
(previous, next) {
@ -62,48 +67,66 @@ class _NavigationBodyState extends ConsumerState<NavigationBody> {
);
return switch (AdaptiveLayout.layoutOf(context)) {
LayoutState.phone => MediaQuery.removePadding(
ViewSize.phone => MediaQuery.removePadding(
context: widget.parentContext,
child: widget.child,
),
LayoutState.tablet => Row(
ViewSize.tablet => Row(
children: [
navigationRail(context),
AnimatedFadeSize(
duration: const Duration(milliseconds: 250),
child: hasOverlay ? navigationRail(context) : const SizedBox(),
),
Flexible(
child: widget.child,
child: MediaQuery(
data: semiNestedPadding(context, hasOverlay),
child: widget.child,
),
)
],
),
LayoutState.desktop => Row(
ViewSize.desktop => Row(
children: [
AnimatedFadeSize(
duration: const Duration(milliseconds: 125),
child: expandedSideBar
? MediaQuery.removePadding(
context: widget.parentContext,
child: NestedNavigationDrawer(
isExpanded: expandedSideBar,
actionButton: actionButton(),
toggleExpanded: (value) {
setState(() {
expandedSideBar = value;
});
},
views: views,
destinations: widget.destinations,
currentLocation: widget.currentLocation,
),
)
: navigationRail(context),
child: hasOverlay
? expandedSideBar
? MediaQuery.removePadding(
context: widget.parentContext,
child: NestedNavigationDrawer(
isExpanded: expandedSideBar,
actionButton: actionButton(),
toggleExpanded: (value) {
setState(() {
expandedSideBar = value;
});
},
views: views,
destinations: widget.destinations,
currentLocation: widget.currentLocation,
),
)
: navigationRail(context)
: const SizedBox(),
),
Flexible(
child: widget.child,
child: MediaQuery(
data: semiNestedPadding(context, hasOverlay),
child: widget.child,
),
),
],
)
};
}
MediaQueryData semiNestedPadding(BuildContext context, bool hasOverlay) {
final paddingOf = MediaQuery.paddingOf(context);
return MediaQuery.of(context).copyWith(
padding: paddingOf.copyWith(left: hasOverlay ? 0 : paddingOf.left),
);
}
AdaptiveFab? actionButton() {
return (widget.currentIndex >= 0 && widget.currentIndex < widget.destinations.length)
? widget.destinations[widget.currentIndex].floatingActionButton
@ -120,7 +143,8 @@ class _NavigationBodyState extends ConsumerState<NavigationBody> {
style: Theme.of(context).textTheme.titleSmall,
),
},
if (AdaptiveLayout.of(context).platform == TargetPlatform.macOS) SizedBox(height: MediaQuery.of(context).padding.top),
if (AdaptiveLayout.of(context).platform == TargetPlatform.macOS)
SizedBox(height: MediaQuery.of(context).padding.top),
Flexible(
child: Padding(
key: const Key('navigation_rail'),
@ -130,7 +154,7 @@ class _NavigationBodyState extends ConsumerState<NavigationBody> {
children: [
IconButton(
onPressed: () {
if (AdaptiveLayout.layoutOf(context) != LayoutState.desktop) {
if (AdaptiveLayout.layoutOf(context) != ViewSize.desktop) {
widget.drawerKey.currentState?.openDrawer();
} else {
setState(() {
@ -140,7 +164,7 @@ class _NavigationBodyState extends ConsumerState<NavigationBody> {
},
icon: const Icon(IconsaxBold.menu),
),
if (AdaptiveLayout.of(context).size == ScreenLayout.dual) ...[
if (AdaptiveLayout.layoutModeOf(context) == LayoutMode.dual) ...[
const SizedBox(height: 8),
AnimatedFadeSize(
child: AnimatedSwitcher(

View file

@ -6,6 +6,7 @@ import 'package:ficonsax/ficonsax.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/models/collection_types.dart';
import 'package:fladder/models/settings/home_settings_model.dart';
import 'package:fladder/models/view_model.dart';
import 'package:fladder/routes/auto_router.gr.dart';
import 'package:fladder/screens/metadata/refresh_metadata.dart';
@ -116,11 +117,11 @@ class NestedNavigationDrawer extends ConsumerWidget {
selected: currentLocation.contains(const SettingsRoute().routeName),
icon: const SizedBox(width: 35, height: 35, child: SettingsUserIcon()),
onPressed: () {
switch (AdaptiveLayout.of(context).size) {
case ScreenLayout.single:
switch (AdaptiveLayout.layoutModeOf(context)) {
case LayoutMode.single:
const SettingsRoute().push(context);
break;
case ScreenLayout.dual:
case LayoutMode.dual:
context.router.push(const ClientSettingsRoute());
break;
}
@ -135,11 +136,11 @@ class NestedNavigationDrawer extends ConsumerWidget {
icon: const Icon(IconsaxOutline.setting_2),
selected: currentLocation.contains(const SettingsRoute().routeName),
onPressed: () {
switch (AdaptiveLayout.of(context).size) {
case ScreenLayout.single:
switch (AdaptiveLayout.layoutModeOf(context)) {
case LayoutMode.single:
const SettingsRoute().push(context);
break;
case ScreenLayout.dual:
case LayoutMode.dual:
context.router.push(const ClientSettingsRoute());
break;
}

View file

@ -1,10 +1,14 @@
import 'package:flutter/material.dart';
import 'package:auto_route/auto_route.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/models/settings/home_settings_model.dart';
import 'package:fladder/providers/user_provider.dart';
import 'package:fladder/routes/auto_router.gr.dart';
import 'package:fladder/screens/shared/user_icon.dart';
import 'package:fladder/util/adaptive_layout.dart';
import 'package:fladder/util/localization_helper.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class SettingsUserIcon extends ConsumerWidget {
const SettingsUserIcon({super.key});
@ -19,7 +23,13 @@ class SettingsUserIcon extends ConsumerWidget {
user: users,
cornerRadius: 200,
onLongPress: () => context.router.push(const LockRoute()),
onTap: () => context.router.navigate(const SettingsRoute()),
onTap: () {
if (AdaptiveLayout.layoutModeOf(context) == LayoutMode.single) {
context.router.push(const SettingsRoute());
} else {
context.router.push(const ClientSettingsRoute());
}
},
),
);
}