mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-08 23:18:16 -07:00
feature: Rework responsive layout (#217)
Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
parent
e07f280124
commit
8012fdcea8
48 changed files with 1468 additions and 1040 deletions
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import 'package:fladder/models/media_playback_model.dart';
|
||||
import 'package:fladder/models/settings/home_settings_model.dart';
|
||||
import 'package:fladder/providers/video_player_provider.dart';
|
||||
import 'package:fladder/providers/views_provider.dart';
|
||||
import 'package:fladder/routes/auto_router.dart';
|
||||
import 'package:fladder/screens/shared/nested_bottom_appbar.dart';
|
||||
import 'package:fladder/util/adaptive_layout.dart';
|
||||
import 'package:fladder/widgets/navigation_scaffold/components/destination_model.dart';
|
||||
|
|
@ -65,7 +67,7 @@ class _NavigationScaffoldState extends ConsumerState<NavigationScaffold> {
|
|||
extendBody: true,
|
||||
floatingActionButtonLocation:
|
||||
playerState == VideoPlayerState.minimized ? FloatingActionButtonLocation.centerFloat : null,
|
||||
floatingActionButton: AdaptiveLayout.of(context).size == ScreenLayout.single
|
||||
floatingActionButton: AdaptiveLayout.layoutModeOf(context) == LayoutMode.single
|
||||
? switch (playerState) {
|
||||
VideoPlayerState.minimized => const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
|
|
@ -83,9 +85,10 @@ class _NavigationScaffoldState extends ConsumerState<NavigationScaffold> {
|
|||
destinations: widget.destinations,
|
||||
currentLocation: currentLocation,
|
||||
),
|
||||
bottomNavigationBar: AdaptiveLayout.of(context).layout == LayoutState.phone
|
||||
bottomNavigationBar: AdaptiveLayout.viewSizeOf(context) == ViewSize.phone
|
||||
? HideOnScroll(
|
||||
controller: AdaptiveLayout.scrollOf(context),
|
||||
forceHide: !homeRoutes.any((element) => element.name.contains(currentLocation)),
|
||||
child: NestedBottomAppBar(
|
||||
child: Transform.translate(
|
||||
offset: const Offset(0, 8),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue