diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/database/card/card_detail/mobile_card_detail_screen.dart b/frontend/appflowy_flutter/lib/mobile/presentation/database/card/card_detail/mobile_card_detail_screen.dart index 28b50454db..2a1e8ca22b 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/database/card/card_detail/mobile_card_detail_screen.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/database/card/card_detail/mobile_card_detail_screen.dart @@ -81,6 +81,7 @@ class _MobileRowDetailPageState extends State { child: Scaffold( appBar: FlowyAppBar( leadingType: FlowyAppBarLeadingType.close, + showDivider: false, actions: [ AppBarMoreButton( onTap: (_) => _showCardActions(context), diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/database/view/database_field_list.dart b/frontend/appflowy_flutter/lib/mobile/presentation/database/view/database_field_list.dart index d1322d6b90..ae1948ac16 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/database/view/database_field_list.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/database/view/database_field_list.dart @@ -22,15 +22,18 @@ class MobileDatabaseFieldList extends StatelessWidget { const MobileDatabaseFieldList({ super.key, required this.databaseController, + required this.canCreate, }); final DatabaseController databaseController; + final bool canCreate; @override Widget build(BuildContext context) { return _MobileDatabaseFieldListBody( databaseController: databaseController, viewId: context.read().state.view.id, + canCreate: canCreate, ); } } @@ -39,10 +42,12 @@ class _MobileDatabaseFieldListBody extends StatelessWidget { const _MobileDatabaseFieldListBody({ required this.databaseController, required this.viewId, + required this.canCreate, }); final DatabaseController databaseController; final String viewId; + final bool canCreate; @override Widget build(BuildContext context) { @@ -113,13 +118,15 @@ class _MobileDatabaseFieldListBody extends StatelessWidget { .add(DatabasePropertyEvent.moveField(from, to)); }, header: firstCell, - footer: Column( - mainAxisSize: MainAxisSize.min, - children: [ - _divider(), - _NewDatabaseFieldTile(viewId: viewId), - ], - ), + footer: canCreate + ? Column( + mainAxisSize: MainAxisSize.min, + children: [ + _divider(), + _NewDatabaseFieldTile(viewId: viewId), + ], + ) + : null, itemCount: cells.length, itemBuilder: (context, index) => cells[index], ); diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/database/view/edit_database_view_screen.dart b/frontend/appflowy_flutter/lib/mobile/presentation/database/view/edit_database_view_screen.dart index 2c1c7859bb..9603f28803 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/database/view/edit_database_view_screen.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/database/view/edit_database_view_screen.dart @@ -240,6 +240,7 @@ class DatabaseViewSettingTile extends StatelessWidget { value: context.read(), child: MobileDatabaseFieldList( databaseController: databaseController, + canCreate: true, ), ); }, diff --git a/frontend/appflowy_flutter/lib/plugins/database/tab_bar/mobile/mobile_tab_bar_header.dart b/frontend/appflowy_flutter/lib/plugins/database/tab_bar/mobile/mobile_tab_bar_header.dart index eb32bbe103..043d5802e5 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/tab_bar/mobile/mobile_tab_bar_header.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/tab_bar/mobile/mobile_tab_bar_header.dart @@ -1,7 +1,11 @@ +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/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'; import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart'; import 'package:appflowy/plugins/database/widgets/setting/mobile_database_controls.dart'; +import 'package:appflowy/workspace/application/view/view_bloc.dart'; import 'package:appflowy/workspace/application/view/view_ext.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:collection/collection.dart'; @@ -24,10 +28,11 @@ class _MobileTabBarHeaderState extends State { return Padding( padding: const EdgeInsets.symmetric(vertical: 14), child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - const Expanded(child: _DatabaseViewList()), - const HSpace(10), + HSpace(GridSize.leadingHeaderPadding), + const _DatabaseViewSelectorButton(), + const Spacer(), BlocBuilder( builder: (context, state) { final currentView = state.tabBars.firstWhereIndexedOrNull( @@ -51,134 +56,80 @@ class _MobileTabBarHeaderState extends State { } } -class _DatabaseViewList extends StatelessWidget { - const _DatabaseViewList(); +class _DatabaseViewSelectorButton extends StatelessWidget { + const _DatabaseViewSelectorButton(); @override Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { - final currentView = state.tabBars.firstWhereIndexedOrNull( + final tabBar = state.tabBars.firstWhereIndexedOrNull( (index, tabBar) => index == state.selectedIndex, ); - if (currentView == null) { + if (tabBar == null) { return const SizedBox.shrink(); } - final children = state.tabBars.mapIndexed((index, tabBar) { - return Padding( - padding: EdgeInsetsDirectional.only( - start: index == 0 ? 0 : 2, - end: 2, + return TextButton( + style: ButtonStyle( + padding: const MaterialStatePropertyAll( + EdgeInsets.fromLTRB(12, 8, 8, 8), ), - child: _DatabaseViewListItem( - tabBar: tabBar, - isSelected: currentView.viewId == tabBar.viewId, + maximumSize: const MaterialStatePropertyAll(Size(200, 48)), + minimumSize: const MaterialStatePropertyAll(Size(48, 0)), + shape: const MaterialStatePropertyAll( + RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(12)), + ), ), - ); - }).toList(); - - children.insert(0, HSpace(GridSize.leadingHeaderPadding)); - - return SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row(children: children), + backgroundColor: const MaterialStatePropertyAll(Color(0x0F212729)), + overlayColor: MaterialStatePropertyAll( + Theme.of(context).colorScheme.secondary, + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + _buildViewIconButton(context, tabBar.view), + const HSpace(6), + Flexible( + child: FlowyText.medium( + tabBar.view.name, + fontSize: 13, + overflow: TextOverflow.ellipsis, + ), + ), + const HSpace(8), + const FlowySvg( + FlowySvgs.arrow_tight_s, + size: Size.square(10), + ), + ], + ), + onPressed: () { + showMobileBottomSheet( + context, + showDivider: false, + builder: (_) { + return MultiBlocProvider( + providers: [ + BlocProvider.value( + value: context.read(), + ), + BlocProvider.value( + value: context.read(), + ), + ], + child: const MobileDatabaseViewList(), + ); + }, + ); + }, ); }, ); } -} - -class _DatabaseViewListItem extends StatefulWidget { - const _DatabaseViewListItem({ - required this.tabBar, - required this.isSelected, - }); - - final DatabaseTabBar tabBar; - final bool isSelected; - - @override - State<_DatabaseViewListItem> createState() => _DatabaseViewListItemState(); -} - -class _DatabaseViewListItemState extends State<_DatabaseViewListItem> { - late final MaterialStatesController statesController; - - @override - void initState() { - super.initState(); - statesController = MaterialStatesController( - {if (widget.isSelected) MaterialState.selected}, - ); - } - - @override - void didUpdateWidget(covariant oldWidget) { - super.didUpdateWidget(oldWidget); - if (widget.isSelected != oldWidget.isSelected) { - statesController.update(MaterialState.selected, widget.isSelected); - } - } - - @override - Widget build(BuildContext context) { - return TextButton( - statesController: statesController, - style: ButtonStyle( - padding: const MaterialStatePropertyAll( - EdgeInsets.symmetric(horizontal: 12, vertical: 7), - ), - maximumSize: MaterialStateProperty.resolveWith((states) { - if (states.contains(MaterialState.selected)) { - return const Size(150, 48); - } - return const Size(120, 48); - }), - minimumSize: const MaterialStatePropertyAll(Size(48, 0)), - shape: const MaterialStatePropertyAll( - RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(12)), - ), - ), - backgroundColor: MaterialStateProperty.resolveWith((states) { - if (states.contains(MaterialState.selected)) { - return const Color(0x0F212729); - } - return Colors.transparent; - }), - overlayColor: MaterialStateProperty.resolveWith((states) { - if (states.contains(MaterialState.selected)) { - return Colors.transparent; - } - return Theme.of(context).colorScheme.secondary; - }), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - _buildViewIconButton(context, widget.tabBar.view), - const HSpace(6), - Flexible( - child: FlowyText( - widget.tabBar.view.name, - fontSize: 14, - fontWeight: widget.isSelected ? FontWeight.w500 : FontWeight.w400, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - onPressed: () { - if (!widget.isSelected) { - context - .read() - .add(DatabaseTabBarEvent.selectView(widget.tabBar.viewId)); - } - }, - ); - } Widget _buildViewIconButton(BuildContext context, ViewPB view) { return view.icon.value.isNotEmpty diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/mobile_database_controls.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/mobile_database_controls.dart index 37f3816d03..e7207c7f53 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/mobile_database_controls.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/mobile_database_controls.dart @@ -1,10 +1,8 @@ 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/database/view/database_view_list.dart'; -import 'package:appflowy/mobile/presentation/database/view/edit_database_view_screen.dart'; +import 'package:appflowy/mobile/presentation/database/view/database_field_list.dart'; import 'package:appflowy/plugins/database/application/database_controller.dart'; -import 'package:appflowy/plugins/database/application/tab_bar_bloc.dart'; import 'package:appflowy/plugins/database/grid/application/filter/filter_menu_bloc.dart'; import 'package:appflowy/plugins/database/grid/application/sort/sort_menu_bloc.dart'; import 'package:appflowy/plugins/database/grid/presentation/grid_page.dart'; @@ -58,62 +56,26 @@ class MobileDatabaseControls extends StatelessWidget { return const SizedBox.shrink(); } - return Row( - children: [ - _DatabaseControlButton( - icon: FlowySvgs.settings_s, - onTap: () { - showMobileBottomSheet( - context, - showHeader: true, - showDoneButton: true, - title: LocaleKeys.grid_settings_editView.tr(), - enableDraggableScrollable: true, - initialChildSize: 0.98, - minChildSize: 0.98, - maxChildSize: 0.98, - builder: (_) { - return BlocProvider( - create: (_) { - return ViewBloc( - view: context - .read() - .state - .tabBarControllerByViewId[controller.viewId]! - .view, - )..add(const ViewEvent.initial()); - }, - child: MobileEditDatabaseViewScreen( - databaseController: controller, - ), - ); - }, - ); - }, - ), - _DatabaseControlButton( - icon: FlowySvgs.align_left_s, - onTap: () { - showMobileBottomSheet( - context, - showDivider: false, - builder: (_) { - return MultiBlocProvider( - providers: [ - BlocProvider.value( - value: context.read(), - ), - BlocProvider.value( - value: context.read(), - ), - ], - child: const MobileDatabaseViewList(), - ); - }, - ); - }, - ), - ], + return _DatabaseControlButton( + icon: FlowySvgs.m_field_hide_s, + onTap: () => showMobileBottomSheet( + context, + resizeToAvoidBottomInset: false, + showDragHandle: true, + showHeader: true, + showBackButton: true, + title: LocaleKeys.grid_settings_properties.tr(), + showDivider: true, + builder: (_) { + return BlocProvider.value( + value: context.read(), + child: MobileDatabaseFieldList( + databaseController: controller, + canCreate: false, + ), + ); + }, + ), ); }, ), diff --git a/frontend/resources/flowy_icons/16x/arrow_tight.svg b/frontend/resources/flowy_icons/16x/arrow_tight.svg new file mode 100644 index 0000000000..5c4996a65d --- /dev/null +++ b/frontend/resources/flowy_icons/16x/arrow_tight.svg @@ -0,0 +1,5 @@ + + + + +