diff --git a/lib/components/page_route.dart b/lib/components/page_route.dart index f0c03f7..8400606 100644 --- a/lib/components/page_route.dart +++ b/lib/components/page_route.dart @@ -298,3 +298,88 @@ class _IOSBackGestureDetectorState extends State { _convertToLogical(details.primaryDelta! / context.size!.width)); } } + +const _kSideBarWidth = 420.0; + +class SideBarRoute extends PopupRoute { + SideBarRoute(this.child); + + final Widget child; + + @override + Color? get barrierColor => const Color.fromARGB(64, 205, 205, 205); + + @override + bool get barrierDismissible => true; + + @override + String? get barrierLabel => "side bar"; + + @override + Widget buildPage(BuildContext context, Animation animation, + Animation secondaryAnimation) { + return Align( + alignment: Alignment.centerRight, + child: Stack( + children: [ + Positioned( + right: 0, + top: 0, + bottom: 0, + child: Container( + decoration: BoxDecoration( + color: FluentTheme.of(context).micaBackgroundColor.withOpacity(0.98), + borderRadius: const BorderRadius.only(topLeft: Radius.circular(4), bottomLeft: Radius.circular(4)) + ), + constraints: const BoxConstraints(maxWidth: _kSideBarWidth), + width: double.infinity, + child: child, + ), + ) + ], + ), + ); + } + + @override + Duration get transitionDuration => const Duration(milliseconds: 200); + + static bool _isPopGestureEnabled(PopupRoute route) { + if (route.isFirst || + route.willHandlePopInternally || + route.popDisposition == RoutePopDisposition.doNotPop || + route.animation!.status != AnimationStatus.completed || + route.secondaryAnimation!.status != AnimationStatus.dismissed || + route.navigator!.userGestureInProgress) { + return false; + } + + return true; + } + + bool get enableIOSGesture => true; + + @override + Widget buildTransitions(BuildContext context, Animation animation, + Animation secondaryAnimation, Widget child) { + var offset = + Tween(begin: const Offset(1, 0), end: const Offset(0, 0)); + return SlideTransition( + position: offset.animate(CurvedAnimation( + parent: animation, + curve: Curves.fastOutSlowIn, + )), + child: enableIOSGesture + ? IOSBackGestureDetector( + gestureWidth: _kBackGestureWidth, + enabledCallback: () => _isPopGestureEnabled(this), + onStartPopGesture: () => _startPopGesture(this), + child: child) + : child, + ); + } + + IOSBackGestureController _startPopGesture(PopupRoute route) { + return IOSBackGestureController(route.controller!, route.navigator!); + } +} diff --git a/lib/pages/search_page.dart b/lib/pages/search_page.dart index c7b58d6..39621cf 100644 --- a/lib/pages/search_page.dart +++ b/lib/pages/search_page.dart @@ -1,6 +1,7 @@ import 'package:fluent_ui/fluent_ui.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:pixes/components/loading.dart'; +import 'package:pixes/components/page_route.dart'; import 'package:pixes/foundation/app.dart'; import 'package:pixes/network/network.dart'; import 'package:pixes/pages/user_info_page.dart'; @@ -108,6 +109,18 @@ class _SearchPageState extends State { ); }, ), + ), + const SizedBox(width: 4,), + Button( + child: const SizedBox( + height: 42, + child: Center( + child: Icon(FluentIcons.settings), + ), + ), + onPressed: () { + Navigator.of(context).push(SideBarRoute(const SearchSettings())); + }, ) ], ), @@ -219,6 +232,40 @@ class _TrendingTagsViewState extends LoadingState<_TrendingTagsView, List createState() => _SearchSettingsState(); +} + +class _SearchSettingsState extends State { + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), + child: Text("Search Settings".tl, style: const TextStyle(fontSize: 18),), + ).toAlign(Alignment.centerLeft), + ], + ), + ); + } + + Widget buildItem({required String title, required Widget child}) { + return Card( + margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + padding: EdgeInsets.zero, + child: ListTile( + title: Text(title), + trailing: child, + ), + ); + } +} + class SearchResultPage extends StatefulWidget { const SearchResultPage(this.keyword, {super.key});