mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-11-09 13:09:21 +03:00
feat: bottom sheets with transition (#4608)
* feat: shiny new bottom sheets * chore: code review
This commit is contained in:
parent
7802c75d7c
commit
4a0c48f419
@ -3,7 +3,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int64_t init_sdk(char *data);
|
||||
int64_t init_sdk(int64_t port, char *data);
|
||||
|
||||
void async_event(int64_t port, const uint8_t *input, uintptr_t len);
|
||||
|
||||
|
@ -7,3 +7,4 @@ export 'bottom_sheet_view_item_body.dart';
|
||||
export 'bottom_sheet_view_page.dart';
|
||||
export 'default_mobile_action_pane.dart';
|
||||
export 'show_mobile_bottom_sheet.dart';
|
||||
export 'show_transition_bottom_sheet.dart';
|
||||
|
@ -79,7 +79,7 @@ Future<T?> showMobileBottomSheet<T>(
|
||||
|
||||
if (showHeader) {
|
||||
children.add(
|
||||
_Header(
|
||||
BottomSheetHeader(
|
||||
showCloseButton: showCloseButton,
|
||||
showBackButton: showBackButton,
|
||||
showDoneButton: showDoneButton,
|
||||
@ -152,8 +152,9 @@ Future<T?> showMobileBottomSheet<T>(
|
||||
);
|
||||
}
|
||||
|
||||
class _Header extends StatelessWidget {
|
||||
const _Header({
|
||||
class BottomSheetHeader extends StatelessWidget {
|
||||
const BottomSheetHeader({
|
||||
super.key,
|
||||
required this.showBackButton,
|
||||
required this.showCloseButton,
|
||||
required this.title,
|
||||
|
@ -0,0 +1,345 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:appflowy/plugins/base/drag_handler.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:sheet/route.dart';
|
||||
import 'package:sheet/sheet.dart';
|
||||
|
||||
import 'show_mobile_bottom_sheet.dart';
|
||||
|
||||
Future<T?> showTransitionMobileBottomSheet<T>(
|
||||
BuildContext context, {
|
||||
required WidgetBuilder builder,
|
||||
bool useRootNavigator = false,
|
||||
EdgeInsets contentPadding = EdgeInsets.zero,
|
||||
Color? backgroundColor,
|
||||
// drag handle
|
||||
bool showDragHandle = false,
|
||||
// header
|
||||
bool showHeader = false,
|
||||
String title = '',
|
||||
bool showBackButton = false,
|
||||
bool showCloseButton = false,
|
||||
bool showDoneButton = false,
|
||||
bool showDivider = true,
|
||||
// stops
|
||||
double initialStop = 1.0,
|
||||
List<double>? stops,
|
||||
}) {
|
||||
assert(
|
||||
showHeader ||
|
||||
title.isEmpty &&
|
||||
!showCloseButton &&
|
||||
!showBackButton &&
|
||||
!showDoneButton &&
|
||||
!showDivider,
|
||||
);
|
||||
assert(!(showCloseButton && showBackButton));
|
||||
|
||||
backgroundColor ??= Theme.of(context).brightness == Brightness.light
|
||||
? const Color(0xFFF7F8FB)
|
||||
: const Color(0xFF626364);
|
||||
|
||||
return Navigator.of(
|
||||
context,
|
||||
rootNavigator: useRootNavigator,
|
||||
).push<T>(
|
||||
TransitionSheetRoute<T>(
|
||||
backgroundColor: backgroundColor,
|
||||
initialStop: initialStop,
|
||||
stops: stops,
|
||||
builder: (context) {
|
||||
final Widget child = builder(context);
|
||||
|
||||
// if the children is only one, we don't need to wrap it with a column
|
||||
if (!showDragHandle && !showHeader) {
|
||||
return child;
|
||||
}
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (showDragHandle) const DragHandle(),
|
||||
if (showHeader) ...[
|
||||
BottomSheetHeader(
|
||||
showCloseButton: showCloseButton,
|
||||
showBackButton: showBackButton,
|
||||
showDoneButton: showDoneButton,
|
||||
title: title,
|
||||
),
|
||||
if (showDivider)
|
||||
const Divider(
|
||||
height: 0.5,
|
||||
thickness: 0.5,
|
||||
),
|
||||
],
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: contentPadding,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// The top offset that will be displayed from the bottom route
|
||||
const double _kPreviousRouteVisibleOffset = 10.0;
|
||||
|
||||
/// Minimal distance from the top of the screen to the top of the previous route
|
||||
/// It will be used ff the top safe area is less than this value.
|
||||
/// In iPhones the top SafeArea is more or equal to this distance.
|
||||
const double _kSheetMinimalOffset = 10;
|
||||
|
||||
const Curve _kCupertinoSheetCurve = Curves.easeOutExpo;
|
||||
const Curve _kCupertinoTransitionCurve = Curves.linear;
|
||||
|
||||
/// Wraps the child into a cupertino modal sheet appearance. This is used to
|
||||
/// create a [SheetRoute].
|
||||
///
|
||||
/// Clip the child widget to rectangle with top rounded corners and adds
|
||||
/// top padding and top safe area.
|
||||
class _CupertinoSheetDecorationBuilder extends StatelessWidget {
|
||||
const _CupertinoSheetDecorationBuilder({
|
||||
required this.child,
|
||||
required this.topRadius,
|
||||
this.backgroundColor,
|
||||
});
|
||||
|
||||
/// The child contained by the modal sheet
|
||||
final Widget child;
|
||||
|
||||
/// The color to paint behind the child
|
||||
final Color? backgroundColor;
|
||||
|
||||
/// The top corners of this modal sheet are rounded by this Radius
|
||||
final Radius topRadius;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Builder(
|
||||
builder: (BuildContext context) {
|
||||
return Container(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.vertical(top: topRadius),
|
||||
color: backgroundColor,
|
||||
),
|
||||
child: MediaQuery.removePadding(
|
||||
context: context,
|
||||
removeTop: true,
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Customized CupertinoSheetRoute from the sheets package
|
||||
///
|
||||
/// A modal route that overlays a widget over the current route and animates
|
||||
/// it from the bottom with a cupertino modal sheet appearance
|
||||
///
|
||||
/// Clip the child widget to rectangle with top rounded corners and adds
|
||||
/// top padding and top safe area.
|
||||
class TransitionSheetRoute<T> extends SheetRoute<T> {
|
||||
TransitionSheetRoute({
|
||||
required WidgetBuilder builder,
|
||||
super.stops,
|
||||
double initialStop = 1.0,
|
||||
super.settings,
|
||||
Color? backgroundColor,
|
||||
super.maintainState = true,
|
||||
super.fit,
|
||||
}) : super(
|
||||
builder: (BuildContext context) {
|
||||
return _CupertinoSheetDecorationBuilder(
|
||||
backgroundColor: backgroundColor,
|
||||
topRadius: const Radius.circular(16),
|
||||
child: Builder(builder: builder),
|
||||
);
|
||||
},
|
||||
animationCurve: _kCupertinoSheetCurve,
|
||||
initialExtent: initialStop,
|
||||
);
|
||||
|
||||
@override
|
||||
bool get draggable => true;
|
||||
|
||||
final SheetController _sheetController = SheetController();
|
||||
|
||||
@override
|
||||
SheetController createSheetController() => _sheetController;
|
||||
|
||||
@override
|
||||
Color? get barrierColor => Colors.transparent;
|
||||
|
||||
@override
|
||||
bool get barrierDismissible => true;
|
||||
|
||||
@override
|
||||
Widget buildSheet(BuildContext context, Widget child) {
|
||||
final effectivePhysics = draggable
|
||||
? BouncingSheetPhysics(
|
||||
parent: SnapSheetPhysics(
|
||||
stops: stops ?? <double>[0, 1],
|
||||
parent: physics,
|
||||
),
|
||||
)
|
||||
: const NeverDraggableSheetPhysics();
|
||||
final MediaQueryData mediaQuery = MediaQuery.of(context);
|
||||
final double topMargin =
|
||||
math.max(_kSheetMinimalOffset, mediaQuery.padding.top) +
|
||||
_kPreviousRouteVisibleOffset;
|
||||
return Sheet.raw(
|
||||
initialExtent: initialExtent,
|
||||
decorationBuilder: decorationBuilder,
|
||||
fit: fit,
|
||||
maxExtent: mediaQuery.size.height - topMargin,
|
||||
physics: effectivePhysics,
|
||||
controller: sheetController,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildTransitions(
|
||||
BuildContext context,
|
||||
Animation<double> animation,
|
||||
Animation<double> secondaryAnimation,
|
||||
Widget child,
|
||||
) {
|
||||
final double topPadding = MediaQuery.of(context).padding.top;
|
||||
final double topOffset = math.max(_kSheetMinimalOffset, topPadding);
|
||||
return AnimatedBuilder(
|
||||
animation: secondaryAnimation,
|
||||
child: child,
|
||||
builder: (BuildContext context, Widget? child) {
|
||||
final double progress = secondaryAnimation.value;
|
||||
final double scale = 1 - progress / 10;
|
||||
final double distanceWithScale =
|
||||
(topOffset + _kPreviousRouteVisibleOffset) * 0.9;
|
||||
final Offset offset =
|
||||
Offset(0, progress * (topOffset - distanceWithScale));
|
||||
return Transform.translate(
|
||||
offset: offset,
|
||||
child: Transform.scale(
|
||||
scale: scale,
|
||||
alignment: Alignment.topCenter,
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool canDriveSecondaryTransitionForPreviousRoute(
|
||||
Route<dynamic> previousRoute,
|
||||
) =>
|
||||
true;
|
||||
|
||||
@override
|
||||
Widget buildSecondaryTransitionForPreviousRoute(
|
||||
BuildContext context,
|
||||
Animation<double> secondaryAnimation,
|
||||
Widget child,
|
||||
) {
|
||||
final Animation<double> delayAnimation = CurvedAnimation(
|
||||
parent: _sheetController.animation,
|
||||
curve: Interval(
|
||||
initialExtent == 1 ? 0 : initialExtent,
|
||||
1,
|
||||
),
|
||||
);
|
||||
|
||||
final Animation<double> secondaryAnimation = CurvedAnimation(
|
||||
parent: _sheetController.animation,
|
||||
curve: Interval(
|
||||
0,
|
||||
initialExtent,
|
||||
),
|
||||
);
|
||||
|
||||
return CupertinoSheetBottomRouteTransition(
|
||||
body: child,
|
||||
sheetAnimation: delayAnimation,
|
||||
secondaryAnimation: secondaryAnimation,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Animation for previous route when a [TransitionSheetRoute] enters/exits
|
||||
@visibleForTesting
|
||||
class CupertinoSheetBottomRouteTransition extends StatelessWidget {
|
||||
const CupertinoSheetBottomRouteTransition({
|
||||
super.key,
|
||||
required this.sheetAnimation,
|
||||
required this.secondaryAnimation,
|
||||
required this.body,
|
||||
});
|
||||
|
||||
final Widget body;
|
||||
|
||||
final Animation<double> sheetAnimation;
|
||||
final Animation<double> secondaryAnimation;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double topPadding = MediaQuery.of(context).padding.top;
|
||||
final double topOffset = math.max(_kSheetMinimalOffset, topPadding);
|
||||
|
||||
final CurvedAnimation curvedAnimation = CurvedAnimation(
|
||||
parent: sheetAnimation,
|
||||
curve: _kCupertinoTransitionCurve,
|
||||
);
|
||||
|
||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||
value: SystemUiOverlayStyle.light,
|
||||
child: AnimatedBuilder(
|
||||
animation: secondaryAnimation,
|
||||
child: body,
|
||||
builder: (BuildContext context, Widget? child) {
|
||||
final double progress = curvedAnimation.value;
|
||||
final double scale = 1 - progress / 10;
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
Container(color: Colors.black),
|
||||
Transform.translate(
|
||||
offset: Offset(0, progress * topOffset),
|
||||
child: Transform.scale(
|
||||
scale: scale,
|
||||
alignment: Alignment.topCenter,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: Radius.lerp(
|
||||
Radius.zero,
|
||||
const Radius.circular(16.0),
|
||||
progress,
|
||||
)!,
|
||||
),
|
||||
child: ColorFiltered(
|
||||
colorFilter: ColorFilter.mode(
|
||||
(Theme.of(context).brightness == Brightness.dark
|
||||
? Colors.grey
|
||||
: Colors.black)
|
||||
.withOpacity(secondaryAnimation.value * 0.1),
|
||||
BlendMode.srcOver,
|
||||
),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -44,7 +44,6 @@ void showCreateFieldBottomSheet(
|
||||
elevation: 20,
|
||||
title: LocaleKeys.grid_field_newProperty.tr(),
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
barrierColor: Colors.transparent,
|
||||
enableDraggableScrollable: true,
|
||||
builder: (context) {
|
||||
final typeOptionMenuItemValue = mobileSupportedFieldTypes
|
||||
|
@ -447,14 +447,12 @@ class _PropertyType extends StatelessWidget {
|
||||
onTap: () {
|
||||
showMobileBottomSheet(
|
||||
context,
|
||||
padding: EdgeInsets.zero,
|
||||
showHeader: true,
|
||||
showDragHandle: true,
|
||||
showCloseButton: true,
|
||||
elevation: 20,
|
||||
title: LocaleKeys.grid_field_editProperty.tr(),
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
barrierColor: Colors.transparent,
|
||||
enableDraggableScrollable: true,
|
||||
builder: (context) {
|
||||
final typeOptionMenuItemValue = mobileSupportedFieldTypes
|
||||
|
@ -68,7 +68,7 @@ class _MobileDatabaseFieldListBody extends StatelessWidget {
|
||||
viewId: viewId,
|
||||
fieldController: databaseController.fieldController,
|
||||
fieldInfo: firstField,
|
||||
showTopBorder: true,
|
||||
showTopBorder: false,
|
||||
);
|
||||
final cells = fields
|
||||
.mapIndexed(
|
||||
@ -124,9 +124,10 @@ class _MobileDatabaseFieldListBody extends StatelessWidget {
|
||||
children: [
|
||||
_divider(),
|
||||
_NewDatabaseFieldTile(viewId: viewId),
|
||||
const VSpace(24),
|
||||
],
|
||||
)
|
||||
: null,
|
||||
: const VSpace(24),
|
||||
itemCount: cells.length,
|
||||
itemBuilder: (context, index) => cells[index],
|
||||
);
|
||||
|
@ -3,7 +3,6 @@ import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/base/app_bar_actions.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
||||
import 'package:appflowy/plugins/base/drag_handler.dart';
|
||||
import 'package:appflowy/plugins/database/application/database_controller.dart';
|
||||
import 'package:appflowy/plugins/database/application/tab_bar_bloc.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_bloc.dart';
|
||||
@ -27,50 +26,39 @@ class MobileDatabaseViewList extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DraggableScrollableSheet(
|
||||
expand: false,
|
||||
snap: true,
|
||||
initialChildSize: 0.98,
|
||||
minChildSize: 0.98,
|
||||
maxChildSize: 0.98,
|
||||
builder: (context, scrollController) {
|
||||
return BlocBuilder<ViewBloc, ViewState>(
|
||||
builder: (context, state) {
|
||||
final views = [state.view, ...state.view.childViews];
|
||||
return BlocBuilder<ViewBloc, ViewState>(
|
||||
builder: (context, state) {
|
||||
final views = [state.view, ...state.view.childViews];
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
const DragHandle(),
|
||||
_Header(
|
||||
title: LocaleKeys.grid_settings_viewList.plural(
|
||||
context.watch<DatabaseTabBarBloc>().state.tabBars.length,
|
||||
namedArgs: {
|
||||
'count':
|
||||
'${context.watch<DatabaseTabBarBloc>().state.tabBars.length}',
|
||||
},
|
||||
return Column(
|
||||
children: [
|
||||
_Header(
|
||||
title: LocaleKeys.grid_settings_viewList.plural(
|
||||
context.watch<DatabaseTabBarBloc>().state.tabBars.length,
|
||||
namedArgs: {
|
||||
'count':
|
||||
'${context.watch<DatabaseTabBarBloc>().state.tabBars.length}',
|
||||
},
|
||||
),
|
||||
showBackButton: false,
|
||||
useFilledDoneButton: false,
|
||||
onDone: (context) => Navigator.pop(context),
|
||||
),
|
||||
SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
...views.mapIndexed(
|
||||
(index, view) => MobileDatabaseViewListButton(
|
||||
view: view,
|
||||
showTopBorder: index == 0,
|
||||
),
|
||||
),
|
||||
showBackButton: false,
|
||||
useFilledDoneButton: false,
|
||||
onDone: (context) => Navigator.pop(context),
|
||||
),
|
||||
SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
child: Column(
|
||||
children: [
|
||||
...views.mapIndexed(
|
||||
(index, view) => MobileDatabaseViewListButton(
|
||||
view: view,
|
||||
showTopBorder: index == 0,
|
||||
),
|
||||
),
|
||||
const VSpace(20),
|
||||
const MobileNewDatabaseViewButton(),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
const VSpace(20),
|
||||
const MobileNewDatabaseViewButton(),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/show_transition_bottom_sheet.dart';
|
||||
import 'package:appflowy/mobile/presentation/widgets/flowy_mobile_quick_action_button.dart';
|
||||
import 'package:appflowy/plugins/database/application/database_controller.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_bloc.dart';
|
||||
@ -33,15 +33,11 @@ class MobileDatabaseViewQuickActions extends StatelessWidget {
|
||||
_actionButton(context, _Action.edit, () {
|
||||
final bloc = context.read<ViewBloc>();
|
||||
context.pop();
|
||||
showMobileBottomSheet(
|
||||
showTransitionMobileBottomSheet(
|
||||
context,
|
||||
showHeader: true,
|
||||
showDoneButton: true,
|
||||
title: LocaleKeys.grid_settings_editView.tr(),
|
||||
enableDraggableScrollable: true,
|
||||
initialChildSize: 0.98,
|
||||
minChildSize: 0.98,
|
||||
maxChildSize: 0.98,
|
||||
builder: (_) => BlocProvider.value(
|
||||
value: bloc,
|
||||
child: MobileEditDatabaseViewScreen(
|
||||
|
@ -33,8 +33,7 @@ class MobileEditDatabaseViewScreen extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<ViewBloc, ViewState>(
|
||||
builder: (context, state) {
|
||||
return ListView(
|
||||
shrinkWrap: true,
|
||||
return Column(
|
||||
children: [
|
||||
_NameAndIcon(view: state.view),
|
||||
_divider(),
|
||||
@ -91,13 +90,15 @@ class _NameAndIconState extends State<_NameAndIcon> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FlowyOptionTile.textField(
|
||||
autofocus: true,
|
||||
showTopBorder: false,
|
||||
controller: textEditingController,
|
||||
onTextChanged: (text) {
|
||||
context.read<ViewBloc>().add(ViewEvent.rename(text));
|
||||
},
|
||||
return Material(
|
||||
child: FlowyOptionTile.textField(
|
||||
autofocus: true,
|
||||
showTopBorder: false,
|
||||
controller: textEditingController,
|
||||
onTextChanged: (text) {
|
||||
context.read<ViewBloc>().add(ViewEvent.rename(text));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -228,18 +229,12 @@ class DatabaseViewSettingTile extends StatelessWidget {
|
||||
}
|
||||
|
||||
if (setting == DatabaseViewSettings.fields) {
|
||||
await showMobileBottomSheet(
|
||||
await showTransitionMobileBottomSheet(
|
||||
context,
|
||||
useSafeArea: false,
|
||||
showDragHandle: true,
|
||||
showHeader: true,
|
||||
showBackButton: true,
|
||||
title: LocaleKeys.grid_settings_properties.tr(),
|
||||
showDivider: true,
|
||||
enableDraggableScrollable: true,
|
||||
initialChildSize: 0.98,
|
||||
minChildSize: 0.98,
|
||||
maxChildSize: 0.98,
|
||||
builder: (_) {
|
||||
return BlocProvider.value(
|
||||
value: context.read<ViewBloc>(),
|
||||
|
@ -1,5 +1,5 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/show_transition_bottom_sheet.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/view/database_view_list.dart';
|
||||
import 'package:appflowy/plugins/base/emoji/emoji_text.dart';
|
||||
import 'package:appflowy/plugins/database/application/tab_bar_bloc.dart';
|
||||
@ -108,9 +108,10 @@ class _DatabaseViewSelectorButton extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
onPressed: () {
|
||||
showMobileBottomSheet(
|
||||
showTransitionMobileBottomSheet(
|
||||
context,
|
||||
showDivider: false,
|
||||
initialStop: 1.0,
|
||||
builder: (_) {
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
|
@ -58,9 +58,8 @@ class MobileDatabaseControls extends StatelessWidget {
|
||||
|
||||
return _DatabaseControlButton(
|
||||
icon: FlowySvgs.m_field_hide_s,
|
||||
onTap: () => showMobileBottomSheet(
|
||||
onTap: () => showTransitionMobileBottomSheet(
|
||||
context,
|
||||
showDragHandle: true,
|
||||
showHeader: true,
|
||||
showBackButton: true,
|
||||
title: LocaleKeys.grid_settings_properties.tr(),
|
||||
|
@ -30,6 +30,7 @@ import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flowy_infra/time/duration.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:sheet/route.dart';
|
||||
|
||||
GoRouter generateRouter(Widget child) {
|
||||
return GoRouter(
|
||||
@ -193,7 +194,7 @@ GoRoute _mobileHomeSettingPageRoute() {
|
||||
parentNavigatorKey: AppGlobals.rootNavKey,
|
||||
path: MobileHomeSettingPage.routeName,
|
||||
pageBuilder: (context, state) {
|
||||
return const MaterialPage(child: MobileHomeSettingPage());
|
||||
return const MaterialExtendedPage(child: MobileHomeSettingPage());
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -203,7 +204,7 @@ GoRoute _mobileCloudSettingAppFlowyCloudPageRoute() {
|
||||
parentNavigatorKey: AppGlobals.rootNavKey,
|
||||
path: AppFlowyCloudPage.routeName,
|
||||
pageBuilder: (context, state) {
|
||||
return const MaterialPage(child: AppFlowyCloudPage());
|
||||
return const MaterialExtendedPage(child: AppFlowyCloudPage());
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -213,7 +214,7 @@ GoRoute _mobileLaunchSettingsPageRoute() {
|
||||
parentNavigatorKey: AppGlobals.rootNavKey,
|
||||
path: MobileLaunchSettingsPage.routeName,
|
||||
pageBuilder: (context, state) {
|
||||
return const MaterialPage(child: MobileLaunchSettingsPage());
|
||||
return const MaterialExtendedPage(child: MobileLaunchSettingsPage());
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -223,7 +224,7 @@ GoRoute _mobileHomeTrashPageRoute() {
|
||||
parentNavigatorKey: AppGlobals.rootNavKey,
|
||||
path: MobileHomeTrashPage.routeName,
|
||||
pageBuilder: (context, state) {
|
||||
return const MaterialPage(child: MobileHomeTrashPage());
|
||||
return const MaterialExtendedPage(child: MobileHomeTrashPage());
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -239,7 +240,7 @@ GoRoute _mobileBlockSettingsPageRoute() {
|
||||
?.split(',')
|
||||
.map(MobileBlockActionType.fromActionString)
|
||||
.toList();
|
||||
return MaterialPage(
|
||||
return MaterialExtendedPage(
|
||||
child: MobileBlockSettingsScreen(
|
||||
actions: actions ?? MobileBlockActionType.standard,
|
||||
),
|
||||
@ -255,7 +256,7 @@ GoRoute _mobileEmojiPickerPageRoute() {
|
||||
pageBuilder: (context, state) {
|
||||
final title =
|
||||
state.uri.queryParameters[MobileEmojiPickerScreen.pageTitle];
|
||||
return MaterialPage(
|
||||
return MaterialExtendedPage(
|
||||
child: MobileEmojiPickerScreen(
|
||||
title: title,
|
||||
),
|
||||
@ -271,7 +272,7 @@ GoRoute _mobileColorPickerPageRoute() {
|
||||
pageBuilder: (context, state) {
|
||||
final title =
|
||||
state.uri.queryParameters[MobileColorPickerScreen.pageTitle] ?? '';
|
||||
return MaterialPage(
|
||||
return MaterialExtendedPage(
|
||||
child: MobileColorPickerScreen(
|
||||
title: title,
|
||||
),
|
||||
@ -285,7 +286,7 @@ GoRoute _mobileImagePickerPageRoute() {
|
||||
parentNavigatorKey: AppGlobals.rootNavKey,
|
||||
path: MobileImagePickerScreen.routeName,
|
||||
pageBuilder: (context, state) {
|
||||
return const MaterialPage(
|
||||
return const MaterialExtendedPage(
|
||||
child: MobileImagePickerScreen(),
|
||||
);
|
||||
},
|
||||
@ -297,7 +298,7 @@ GoRoute _mobileCodeLanguagePickerPageRoute() {
|
||||
parentNavigatorKey: AppGlobals.rootNavKey,
|
||||
path: MobileCodeLanguagePickerScreen.routeName,
|
||||
pageBuilder: (context, state) {
|
||||
return const MaterialPage(
|
||||
return const MaterialExtendedPage(
|
||||
child: MobileCodeLanguagePickerScreen(),
|
||||
);
|
||||
},
|
||||
@ -309,7 +310,7 @@ GoRoute _mobileLanguagePickerPageRoute() {
|
||||
parentNavigatorKey: AppGlobals.rootNavKey,
|
||||
path: LanguagePickerScreen.routeName,
|
||||
pageBuilder: (context, state) {
|
||||
return const MaterialPage(
|
||||
return const MaterialExtendedPage(
|
||||
child: LanguagePickerScreen(),
|
||||
);
|
||||
},
|
||||
@ -321,7 +322,7 @@ GoRoute _mobileFontPickerPageRoute() {
|
||||
parentNavigatorKey: AppGlobals.rootNavKey,
|
||||
path: FontPickerScreen.routeName,
|
||||
pageBuilder: (context, state) {
|
||||
return const MaterialPage(
|
||||
return const MaterialExtendedPage(
|
||||
child: FontPickerScreen(),
|
||||
);
|
||||
},
|
||||
@ -339,7 +340,7 @@ GoRoute _mobileNewPropertyPageRoute() {
|
||||
state.uri.queryParameters[MobileNewPropertyScreen.argFieldTypeId] ??
|
||||
FieldType.RichText.value.toString();
|
||||
final value = int.parse(fieldTypeId);
|
||||
return MaterialPage(
|
||||
return MaterialExtendedPage(
|
||||
fullscreenDialog: true,
|
||||
child: MobileNewPropertyScreen(
|
||||
viewId: viewId,
|
||||
@ -356,7 +357,7 @@ GoRoute _mobileEditPropertyPageRoute() {
|
||||
path: MobileEditPropertyScreen.routeName,
|
||||
pageBuilder: (context, state) {
|
||||
final args = state.extra as Map<String, dynamic>;
|
||||
return MaterialPage(
|
||||
return MaterialExtendedPage(
|
||||
fullscreenDialog: true,
|
||||
child: MobileEditPropertyScreen(
|
||||
viewId: args[MobileEditPropertyScreen.argViewId],
|
||||
@ -374,7 +375,7 @@ GoRoute _mobileCalendarEventsPageRoute() {
|
||||
pageBuilder: (context, state) {
|
||||
final args = state.extra as Map<String, dynamic>;
|
||||
|
||||
return MaterialPage(
|
||||
return MaterialExtendedPage(
|
||||
child: MobileCalendarEventsScreen(
|
||||
calendarBloc: args[MobileCalendarEventsScreen.calendarBlocKey],
|
||||
date: args[MobileCalendarEventsScreen.calendarDateKey],
|
||||
@ -468,7 +469,9 @@ GoRoute _mobileEditorScreenRoute() {
|
||||
final id = state.uri.queryParameters[MobileEditorScreen.viewId]!;
|
||||
final title = state.uri.queryParameters[MobileEditorScreen.viewTitle];
|
||||
|
||||
return MaterialPage(child: MobileEditorScreen(id: id, title: title));
|
||||
return MaterialExtendedPage(
|
||||
child: MobileEditorScreen(id: id, title: title),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -482,7 +485,7 @@ GoRoute _mobileGridScreenRoute() {
|
||||
final title = state.uri.queryParameters[MobileGridScreen.viewTitle];
|
||||
final arguments = state.uri.queryParameters[MobileGridScreen.viewArgs];
|
||||
|
||||
return MaterialPage(
|
||||
return MaterialExtendedPage(
|
||||
child: MobileGridScreen(
|
||||
id: id,
|
||||
title: title,
|
||||
@ -500,7 +503,7 @@ GoRoute _mobileBoardScreenRoute() {
|
||||
pageBuilder: (context, state) {
|
||||
final id = state.uri.queryParameters[MobileBoardScreen.viewId]!;
|
||||
final title = state.uri.queryParameters[MobileBoardScreen.viewTitle];
|
||||
return MaterialPage(
|
||||
return MaterialExtendedPage(
|
||||
child: MobileBoardScreen(
|
||||
id: id,
|
||||
title: title,
|
||||
@ -517,7 +520,7 @@ GoRoute _mobileCalendarScreenRoute() {
|
||||
pageBuilder: (context, state) {
|
||||
final id = state.uri.queryParameters[MobileCalendarScreen.viewId]!;
|
||||
final title = state.uri.queryParameters[MobileCalendarScreen.viewTitle]!;
|
||||
return MaterialPage(
|
||||
return MaterialExtendedPage(
|
||||
child: MobileCalendarScreen(
|
||||
id: id,
|
||||
title: title,
|
||||
@ -537,7 +540,7 @@ GoRoute _mobileCardDetailScreenRoute() {
|
||||
args[MobileRowDetailPage.argDatabaseController];
|
||||
final rowId = args[MobileRowDetailPage.argRowId]!;
|
||||
|
||||
return MaterialPage(
|
||||
return MaterialExtendedPage(
|
||||
child: MobileRowDetailPage(
|
||||
databaseController: databaseController,
|
||||
rowId: rowId,
|
||||
@ -586,7 +589,7 @@ GoRoute _rootRoute(Widget child) {
|
||||
},
|
||||
// Root route is SplashScreen.
|
||||
// It needs LaunchConfiguration as a parameter, so we get it from ApplicationWidget's child.
|
||||
pageBuilder: (context, state) => MaterialPage(
|
||||
pageBuilder: (context, state) => MaterialExtendedPage(
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
|
@ -1602,6 +1602,15 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
sheet:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: sheet
|
||||
ref: "8ee20bd"
|
||||
resolved-ref: "8ee20bd36acaeb36996a09ba9d0f9e7059bb49df"
|
||||
url: "https://github.com/richardshiue/modal_bottom_sheet"
|
||||
source: git
|
||||
version: "1.0.0-pre"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -129,6 +129,7 @@ dependencies:
|
||||
scrollable_positioned_list: ^0.3.8
|
||||
flutter_cache_manager: ^3.3.1
|
||||
share_plus: ^7.2.1
|
||||
sheet:
|
||||
|
||||
dev_dependencies:
|
||||
flutter_lints: ^3.0.1
|
||||
@ -167,6 +168,12 @@ dependency_overrides:
|
||||
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
||||
ref: "1715ed4"
|
||||
|
||||
sheet:
|
||||
git:
|
||||
url: https://github.com/richardshiue/modal_bottom_sheet
|
||||
ref: 8ee20bd
|
||||
path: sheet
|
||||
|
||||
uuid: ^4.1.0
|
||||
|
||||
# The "flutter_lints" package below contains a set of recommended lints to
|
||||
|
Loading…
Reference in New Issue
Block a user