chore: revamp mobile database toolbar (#4579)

* chore: revamp mobile database toolbar

* chore: code cleanup
This commit is contained in:
Richard Shiue 2024-02-04 00:55:44 +08:00 committed by GitHub
parent 8c1d0106dd
commit ca93cb20ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 107 additions and 180 deletions

View File

@ -81,6 +81,7 @@ class _MobileRowDetailPageState extends State<MobileRowDetailPage> {
child: Scaffold(
appBar: FlowyAppBar(
leadingType: FlowyAppBarLeadingType.close,
showDivider: false,
actions: [
AppBarMoreButton(
onTap: (_) => _showCardActions(context),

View File

@ -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<ViewBloc>().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],
);

View File

@ -240,6 +240,7 @@ class DatabaseViewSettingTile extends StatelessWidget {
value: context.read<ViewBloc>(),
child: MobileDatabaseFieldList(
databaseController: databaseController,
canCreate: true,
),
);
},

View File

@ -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<MobileTabBarHeader> {
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<DatabaseTabBarBloc, DatabaseTabBarState>(
builder: (context, state) {
final currentView = state.tabBars.firstWhereIndexedOrNull(
@ -51,134 +56,80 @@ class _MobileTabBarHeaderState extends State<MobileTabBarHeader> {
}
}
class _DatabaseViewList extends StatelessWidget {
const _DatabaseViewList();
class _DatabaseViewSelectorButton extends StatelessWidget {
const _DatabaseViewSelectorButton();
@override
Widget build(BuildContext context) {
return BlocBuilder<DatabaseTabBarBloc, DatabaseTabBarState>(
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<Widget>((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<ViewBloc>.value(
value: context.read<ViewBloc>(),
),
BlocProvider<DatabaseTabBarBloc>.value(
value: context.read<DatabaseTabBarBloc>(),
),
],
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(
<MaterialState>{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<DatabaseTabBarBloc>()
.add(DatabaseTabBarEvent.selectView(widget.tabBar.viewId));
}
},
);
}
Widget _buildViewIconButton(BuildContext context, ViewPB view) {
return view.icon.value.isNotEmpty

View File

@ -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<ViewBloc>(
create: (_) {
return ViewBloc(
view: context
.read<DatabaseTabBarBloc>()
.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<ViewBloc>.value(
value: context.read<ViewBloc>(),
),
BlocProvider<DatabaseTabBarBloc>.value(
value: context.read<DatabaseTabBarBloc>(),
),
],
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<ViewBloc>(),
child: MobileDatabaseFieldList(
databaseController: controller,
canCreate: false,
),
);
},
),
);
},
),

View File

@ -0,0 +1,5 @@
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.9">
<path d="M1.59505 3.16079C1.40444 2.97017 1.0954 2.97017 0.904783 3.16079C0.71417 3.3514 0.71417 3.66044 0.904783 3.85106L4.36016 7.30643C4.71349 7.65976 5.28635 7.65976 5.63968 7.30643L9.09505 3.85106C9.28567 3.66044 9.28567 3.3514 9.09505 3.16079C8.90444 2.97017 8.5954 2.97017 8.40478 3.16079L4.99992 6.56565L1.59505 3.16079Z" fill="#2B2F36" stroke="black" stroke-width="0.142857" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 559 B