mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: revamp mobile database toolbar (#4579)
* chore: revamp mobile database toolbar * chore: code cleanup
This commit is contained in:
parent
8c1d0106dd
commit
ca93cb20ec
@ -81,6 +81,7 @@ class _MobileRowDetailPageState extends State<MobileRowDetailPage> {
|
|||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: FlowyAppBar(
|
appBar: FlowyAppBar(
|
||||||
leadingType: FlowyAppBarLeadingType.close,
|
leadingType: FlowyAppBarLeadingType.close,
|
||||||
|
showDivider: false,
|
||||||
actions: [
|
actions: [
|
||||||
AppBarMoreButton(
|
AppBarMoreButton(
|
||||||
onTap: (_) => _showCardActions(context),
|
onTap: (_) => _showCardActions(context),
|
||||||
|
@ -22,15 +22,18 @@ class MobileDatabaseFieldList extends StatelessWidget {
|
|||||||
const MobileDatabaseFieldList({
|
const MobileDatabaseFieldList({
|
||||||
super.key,
|
super.key,
|
||||||
required this.databaseController,
|
required this.databaseController,
|
||||||
|
required this.canCreate,
|
||||||
});
|
});
|
||||||
|
|
||||||
final DatabaseController databaseController;
|
final DatabaseController databaseController;
|
||||||
|
final bool canCreate;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return _MobileDatabaseFieldListBody(
|
return _MobileDatabaseFieldListBody(
|
||||||
databaseController: databaseController,
|
databaseController: databaseController,
|
||||||
viewId: context.read<ViewBloc>().state.view.id,
|
viewId: context.read<ViewBloc>().state.view.id,
|
||||||
|
canCreate: canCreate,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -39,10 +42,12 @@ class _MobileDatabaseFieldListBody extends StatelessWidget {
|
|||||||
const _MobileDatabaseFieldListBody({
|
const _MobileDatabaseFieldListBody({
|
||||||
required this.databaseController,
|
required this.databaseController,
|
||||||
required this.viewId,
|
required this.viewId,
|
||||||
|
required this.canCreate,
|
||||||
});
|
});
|
||||||
|
|
||||||
final DatabaseController databaseController;
|
final DatabaseController databaseController;
|
||||||
final String viewId;
|
final String viewId;
|
||||||
|
final bool canCreate;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -113,13 +118,15 @@ class _MobileDatabaseFieldListBody extends StatelessWidget {
|
|||||||
.add(DatabasePropertyEvent.moveField(from, to));
|
.add(DatabasePropertyEvent.moveField(from, to));
|
||||||
},
|
},
|
||||||
header: firstCell,
|
header: firstCell,
|
||||||
footer: Column(
|
footer: canCreate
|
||||||
mainAxisSize: MainAxisSize.min,
|
? Column(
|
||||||
children: [
|
mainAxisSize: MainAxisSize.min,
|
||||||
_divider(),
|
children: [
|
||||||
_NewDatabaseFieldTile(viewId: viewId),
|
_divider(),
|
||||||
],
|
_NewDatabaseFieldTile(viewId: viewId),
|
||||||
),
|
],
|
||||||
|
)
|
||||||
|
: null,
|
||||||
itemCount: cells.length,
|
itemCount: cells.length,
|
||||||
itemBuilder: (context, index) => cells[index],
|
itemBuilder: (context, index) => cells[index],
|
||||||
);
|
);
|
||||||
|
@ -240,6 +240,7 @@ class DatabaseViewSettingTile extends StatelessWidget {
|
|||||||
value: context.read<ViewBloc>(),
|
value: context.read<ViewBloc>(),
|
||||||
child: MobileDatabaseFieldList(
|
child: MobileDatabaseFieldList(
|
||||||
databaseController: databaseController,
|
databaseController: databaseController,
|
||||||
|
canCreate: true,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -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/base/emoji/emoji_text.dart';
|
||||||
import 'package:appflowy/plugins/database/application/tab_bar_bloc.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/grid/presentation/layout/sizes.dart';
|
||||||
import 'package:appflowy/plugins/database/widgets/setting/mobile_database_controls.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/workspace/application/view/view_ext.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
@ -24,10 +28,11 @@ class _MobileTabBarHeaderState extends State<MobileTabBarHeader> {
|
|||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
const Expanded(child: _DatabaseViewList()),
|
HSpace(GridSize.leadingHeaderPadding),
|
||||||
const HSpace(10),
|
const _DatabaseViewSelectorButton(),
|
||||||
|
const Spacer(),
|
||||||
BlocBuilder<DatabaseTabBarBloc, DatabaseTabBarState>(
|
BlocBuilder<DatabaseTabBarBloc, DatabaseTabBarState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final currentView = state.tabBars.firstWhereIndexedOrNull(
|
final currentView = state.tabBars.firstWhereIndexedOrNull(
|
||||||
@ -51,134 +56,80 @@ class _MobileTabBarHeaderState extends State<MobileTabBarHeader> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _DatabaseViewList extends StatelessWidget {
|
class _DatabaseViewSelectorButton extends StatelessWidget {
|
||||||
const _DatabaseViewList();
|
const _DatabaseViewSelectorButton();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<DatabaseTabBarBloc, DatabaseTabBarState>(
|
return BlocBuilder<DatabaseTabBarBloc, DatabaseTabBarState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final currentView = state.tabBars.firstWhereIndexedOrNull(
|
final tabBar = state.tabBars.firstWhereIndexedOrNull(
|
||||||
(index, tabBar) => index == state.selectedIndex,
|
(index, tabBar) => index == state.selectedIndex,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (currentView == null) {
|
if (tabBar == null) {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
final children = state.tabBars.mapIndexed<Widget>((index, tabBar) {
|
return TextButton(
|
||||||
return Padding(
|
style: ButtonStyle(
|
||||||
padding: EdgeInsetsDirectional.only(
|
padding: const MaterialStatePropertyAll(
|
||||||
start: index == 0 ? 0 : 2,
|
EdgeInsets.fromLTRB(12, 8, 8, 8),
|
||||||
end: 2,
|
|
||||||
),
|
),
|
||||||
child: _DatabaseViewListItem(
|
maximumSize: const MaterialStatePropertyAll(Size(200, 48)),
|
||||||
tabBar: tabBar,
|
minimumSize: const MaterialStatePropertyAll(Size(48, 0)),
|
||||||
isSelected: currentView.viewId == tabBar.viewId,
|
shape: const MaterialStatePropertyAll(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
backgroundColor: const MaterialStatePropertyAll(Color(0x0F212729)),
|
||||||
}).toList();
|
overlayColor: MaterialStatePropertyAll(
|
||||||
|
Theme.of(context).colorScheme.secondary,
|
||||||
children.insert(0, HSpace(GridSize.leadingHeaderPadding));
|
),
|
||||||
|
),
|
||||||
return SingleChildScrollView(
|
child: Row(
|
||||||
scrollDirection: Axis.horizontal,
|
mainAxisSize: MainAxisSize.min,
|
||||||
child: Row(children: children),
|
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) {
|
Widget _buildViewIconButton(BuildContext context, ViewPB view) {
|
||||||
return view.icon.value.isNotEmpty
|
return view.icon.value.isNotEmpty
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.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/bottom_sheet.dart';
|
||||||
import 'package:appflowy/mobile/presentation/database/view/database_view_list.dart';
|
import 'package:appflowy/mobile/presentation/database/view/database_field_list.dart';
|
||||||
import 'package:appflowy/mobile/presentation/database/view/edit_database_view_screen.dart';
|
|
||||||
import 'package:appflowy/plugins/database/application/database_controller.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/filter/filter_menu_bloc.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/application/sort/sort_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';
|
import 'package:appflowy/plugins/database/grid/presentation/grid_page.dart';
|
||||||
@ -58,62 +56,26 @@ class MobileDatabaseControls extends StatelessWidget {
|
|||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Row(
|
return _DatabaseControlButton(
|
||||||
children: [
|
icon: FlowySvgs.m_field_hide_s,
|
||||||
_DatabaseControlButton(
|
onTap: () => showMobileBottomSheet(
|
||||||
icon: FlowySvgs.settings_s,
|
context,
|
||||||
onTap: () {
|
resizeToAvoidBottomInset: false,
|
||||||
showMobileBottomSheet(
|
showDragHandle: true,
|
||||||
context,
|
showHeader: true,
|
||||||
showHeader: true,
|
showBackButton: true,
|
||||||
showDoneButton: true,
|
title: LocaleKeys.grid_settings_properties.tr(),
|
||||||
title: LocaleKeys.grid_settings_editView.tr(),
|
showDivider: true,
|
||||||
enableDraggableScrollable: true,
|
builder: (_) {
|
||||||
initialChildSize: 0.98,
|
return BlocProvider.value(
|
||||||
minChildSize: 0.98,
|
value: context.read<ViewBloc>(),
|
||||||
maxChildSize: 0.98,
|
child: MobileDatabaseFieldList(
|
||||||
builder: (_) {
|
databaseController: controller,
|
||||||
return BlocProvider<ViewBloc>(
|
canCreate: false,
|
||||||
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(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
5
frontend/resources/flowy_icons/16x/arrow_tight.svg
Normal file
5
frontend/resources/flowy_icons/16x/arrow_tight.svg
Normal 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 |
Loading…
Reference in New Issue
Block a user