mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: adjust board card UI (#3954)
* chore: adjust board card UI * chore: fix accessory popover and add title placeholder * chore: add pubspec.lock * chore: fix integration test * chore: apply suggestions from code review Co-authored-by: Mathias Mogensen <42929161+Xazin@users.noreply.github.com> * chore: apply suggestions from Mathias --------- Co-authored-by: Mathias Mogensen <42929161+Xazin@users.noreply.github.com>
This commit is contained in:
parent
bddaac05ae
commit
e18e031710
@ -1,5 +1,6 @@
|
|||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/plugins/database_view/board/presentation/widgets/board_column_header.dart';
|
import 'package:appflowy/plugins/database_view/board/presentation/widgets/board_column_header.dart';
|
||||||
|
import 'package:appflowy/plugins/database_view/widgets/card/container/card_container.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
|
||||||
import 'package:appflowy_board/appflowy_board.dart';
|
import 'package:appflowy_board/appflowy_board.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
@ -15,8 +16,8 @@ const defaultLastCardName = 'Card 3';
|
|||||||
void main() {
|
void main() {
|
||||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
group('board add row test', () {
|
group('board add row test:', () {
|
||||||
testWidgets('Add card from header', (tester) async {
|
testWidgets('from header', (tester) async {
|
||||||
await tester.initializeAppFlowy();
|
await tester.initializeAppFlowy();
|
||||||
await tester.tapGoButton();
|
await tester.tapGoButton();
|
||||||
|
|
||||||
@ -45,7 +46,7 @@ void main() {
|
|||||||
const newCardName = 'Card 4';
|
const newCardName = 'Card 4';
|
||||||
await tester.enterText(
|
await tester.enterText(
|
||||||
find.descendant(
|
find.descendant(
|
||||||
of: find.byType(IntrinsicHeight),
|
of: find.byType(RowCardContainer),
|
||||||
matching: find.byType(TextField),
|
matching: find.byType(TextField),
|
||||||
),
|
),
|
||||||
newCardName,
|
newCardName,
|
||||||
@ -59,7 +60,7 @@ void main() {
|
|||||||
expect(firstCardText.text, newCardName);
|
expect(firstCardText.text, newCardName);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Add card from footer', (tester) async {
|
testWidgets('from footer', (tester) async {
|
||||||
await tester.initializeAppFlowy();
|
await tester.initializeAppFlowy();
|
||||||
await tester.tapGoButton();
|
await tester.tapGoButton();
|
||||||
|
|
||||||
@ -87,7 +88,7 @@ void main() {
|
|||||||
const newCardName = 'Card 4';
|
const newCardName = 'Card 4';
|
||||||
await tester.enterText(
|
await tester.enterText(
|
||||||
find.descendant(
|
find.descendant(
|
||||||
of: find.byType(IntrinsicHeight),
|
of: find.byType(RowCardContainer),
|
||||||
matching: find.byType(TextField),
|
matching: find.byType(TextField),
|
||||||
),
|
),
|
||||||
newCardName,
|
newCardName,
|
||||||
|
@ -17,6 +17,7 @@ import 'package:appflowy_backend/protobuf/flowy-database2/row_entities.pb.dart';
|
|||||||
import 'package:appflowy_board/appflowy_board.dart';
|
import 'package:appflowy_board/appflowy_board.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
import 'package:flowy_infra_ui/widget/error_page.dart';
|
import 'package:flowy_infra_ui/widget/error_page.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
import 'package:flutter/material.dart' hide Card;
|
import 'package:flutter/material.dart' hide Card;
|
||||||
@ -159,10 +160,12 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
boardScrollController: scrollManager,
|
boardScrollController: scrollManager,
|
||||||
scrollController: scrollController,
|
scrollController: scrollController,
|
||||||
controller: context.read<BoardBloc>().boardController,
|
controller: context.read<BoardBloc>().boardController,
|
||||||
groupConstraints: const BoxConstraints.tightFor(width: 300),
|
groupConstraints: const BoxConstraints.tightFor(width: 256),
|
||||||
config: const AppFlowyBoardConfig(
|
config: const AppFlowyBoardConfig(
|
||||||
groupPadding: EdgeInsets.symmetric(horizontal: 4),
|
groupPadding: EdgeInsets.symmetric(horizontal: 4),
|
||||||
groupItemPadding: EdgeInsets.symmetric(horizontal: 4),
|
groupItemPadding: EdgeInsets.symmetric(horizontal: 4),
|
||||||
|
footerPadding: EdgeInsets.fromLTRB(4, 14, 4, 4),
|
||||||
|
stretchGroupHeight: false,
|
||||||
),
|
),
|
||||||
leading: HiddenGroupsColumn(margin: config.headerPadding),
|
leading: HiddenGroupsColumn(margin: config.headerPadding),
|
||||||
trailing: showCreateGroupButton
|
trailing: showCreateGroupButton
|
||||||
@ -200,20 +203,15 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
|
|
||||||
Widget _buildFooter(BuildContext context, AppFlowyGroupData columnData) {
|
Widget _buildFooter(BuildContext context, AppFlowyGroupData columnData) {
|
||||||
return AppFlowyGroupFooter(
|
return AppFlowyGroupFooter(
|
||||||
height: 50,
|
height: 36,
|
||||||
margin: config.footerPadding,
|
margin: config.footerPadding,
|
||||||
icon: SizedBox(
|
icon: FlowySvg(
|
||||||
height: 20,
|
FlowySvgs.add_s,
|
||||||
width: 20,
|
color: Theme.of(context).hintColor,
|
||||||
child: FlowySvg(
|
|
||||||
FlowySvgs.add_s,
|
|
||||||
color: Theme.of(context).hintColor,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
title: FlowyText.medium(
|
title: FlowyText.medium(
|
||||||
LocaleKeys.board_column_createNewCard.tr(),
|
LocaleKeys.board_column_createNewCard.tr(),
|
||||||
color: Theme.of(context).hintColor,
|
color: Theme.of(context).hintColor,
|
||||||
fontSize: 14,
|
|
||||||
),
|
),
|
||||||
onAddButtonClick: () => context
|
onAddButtonClick: () => context
|
||||||
.read<BoardBloc>()
|
.read<BoardBloc>()
|
||||||
@ -266,6 +264,14 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
rowMeta: rowMeta,
|
rowMeta: rowMeta,
|
||||||
rowCache: rowCache,
|
rowCache: rowCache,
|
||||||
),
|
),
|
||||||
|
styleConfiguration: RowCardStyleConfiguration(
|
||||||
|
hoverStyle: HoverStyle(
|
||||||
|
hoverColor: Theme.of(context).brightness == Brightness.light
|
||||||
|
? const Color(0x0F1F2329)
|
||||||
|
: const Color(0x0FEFF4FB),
|
||||||
|
foregroundColorOnHover: Theme.of(context).colorScheme.onBackground,
|
||||||
|
),
|
||||||
|
),
|
||||||
onStartEditing: () => boardBloc
|
onStartEditing: () => boardBloc
|
||||||
.add(BoardEvent.startEditingRow(groupData.group, groupItem.row)),
|
.add(BoardEvent.startEditingRow(groupData.group, groupItem.row)),
|
||||||
onEndEditing: () =>
|
onEndEditing: () =>
|
||||||
@ -280,8 +286,10 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||||
border: Border.fromBorderSide(
|
border: Border.fromBorderSide(
|
||||||
BorderSide(
|
BorderSide(
|
||||||
color: Theme.of(context).dividerColor,
|
color: Theme.of(context).brightness == Brightness.light
|
||||||
width: 1.4,
|
? const Color(0xFF1F2329).withOpacity(0.12)
|
||||||
|
: const Color(0xFF59647A),
|
||||||
|
width: 1.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
|
@ -3,7 +3,6 @@ import 'package:appflowy/generated/locale_keys.g.dart';
|
|||||||
import 'package:appflowy/plugins/database_view/board/application/board_bloc.dart';
|
import 'package:appflowy/plugins/database_view/board/application/board_bloc.dart';
|
||||||
import 'package:appflowy/plugins/database_view/grid/presentation/layout/sizes.dart';
|
import 'package:appflowy/plugins/database_view/grid/presentation/layout/sizes.dart';
|
||||||
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_extension.dart';
|
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_extension.dart';
|
||||||
import 'package:appflowy/plugins/database_view/widgets/card/define.dart';
|
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/group.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/group.pb.dart';
|
||||||
import 'package:appflowy_board/appflowy_board.dart';
|
import 'package:appflowy_board/appflowy_board.dart';
|
||||||
@ -158,10 +157,8 @@ class _BoardColumnHeaderState extends State<BoardColumnHeader> {
|
|||||||
filled: true,
|
filled: true,
|
||||||
fillColor: Theme.of(context).colorScheme.surface,
|
fillColor: Theme.of(context).colorScheme.surface,
|
||||||
hoverColor: Colors.transparent,
|
hoverColor: Colors.transparent,
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding:
|
||||||
vertical: CardSizes.cardCellVPadding + 4,
|
const EdgeInsets.symmetric(vertical: 12, horizontal: 8),
|
||||||
horizontal: 8,
|
|
||||||
),
|
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
@ -73,9 +73,9 @@ class RowCard<CustomCardData> extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _RowCardState<T> extends State<RowCard<T>> {
|
class _RowCardState<T> extends State<RowCard<T>> {
|
||||||
|
final popoverController = PopoverController();
|
||||||
late final CardBloc _cardBloc;
|
late final CardBloc _cardBloc;
|
||||||
late final EditableRowNotifier rowNotifier;
|
late final EditableRowNotifier rowNotifier;
|
||||||
late final PopoverController popoverController;
|
|
||||||
AccessoryType? accessoryType;
|
AccessoryType? accessoryType;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -100,8 +100,6 @@ class _RowCardState<T> extends State<RowCard<T>> {
|
|||||||
widget.onEndEditing();
|
widget.onEndEditing();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
popoverController = PopoverController();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -111,26 +109,21 @@ class _RowCardState<T> extends State<RowCard<T>> {
|
|||||||
child: BlocBuilder<CardBloc, RowCardState>(
|
child: BlocBuilder<CardBloc, RowCardState>(
|
||||||
buildWhen: (previous, current) {
|
buildWhen: (previous, current) {
|
||||||
// Rebuild when:
|
// Rebuild when:
|
||||||
// 1.If the length of the cells is not the same
|
// 1. If the length of the cells is not the same or isEditing changed
|
||||||
// 2.isEditing changed
|
|
||||||
if (previous.cells.length != current.cells.length ||
|
if (previous.cells.length != current.cells.length ||
|
||||||
previous.isEditing != current.isEditing) {
|
previous.isEditing != current.isEditing) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3.Compare the content of the cells. The cells consists of
|
// 2. the content of the cells changed
|
||||||
// list of [BoardCellEquatable] that extends the [Equatable].
|
|
||||||
return !listEquals(previous.cells, current.cells);
|
return !listEquals(previous.cells, current.cells);
|
||||||
},
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
// mobile
|
|
||||||
if (PlatformExtension.isMobile) {
|
if (PlatformExtension.isMobile) {
|
||||||
// TODO(yijing): refactor it in mobile to display card in database view
|
// TODO(yijing): refactor it in mobile to display card in database view
|
||||||
return RowCardContainer(
|
return RowCardContainer(
|
||||||
buildAccessoryWhen: () => state.isEditing == false,
|
buildAccessoryWhen: () => state.isEditing == false,
|
||||||
accessoryBuilder: (context) {
|
accessories: const [],
|
||||||
return [];
|
|
||||||
},
|
|
||||||
openAccessory: (p0) {},
|
openAccessory: (p0) {},
|
||||||
openCard: (context) => widget.openCard(context),
|
openCard: (context) => widget.openCard(context),
|
||||||
child: _CardContent<T>(
|
child: _CardContent<T>(
|
||||||
@ -143,29 +136,27 @@ class _RowCardState<T> extends State<RowCard<T>> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// desktop
|
|
||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
controller: popoverController,
|
controller: popoverController,
|
||||||
triggerActions: PopoverTriggerFlags.none,
|
triggerActions: PopoverTriggerFlags.none,
|
||||||
constraints: BoxConstraints.loose(const Size(140, 200)),
|
constraints: BoxConstraints.loose(const Size(140, 200)),
|
||||||
margin: const EdgeInsets.all(6),
|
|
||||||
direction: PopoverDirection.rightWithCenterAligned,
|
direction: PopoverDirection.rightWithCenterAligned,
|
||||||
popupBuilder: (popoverContext) => _handlePopoverBuilder(
|
popupBuilder: (popoverContext) {
|
||||||
context,
|
return RowActions(
|
||||||
popoverContext,
|
viewId: _cardBloc.viewId,
|
||||||
),
|
rowId: _cardBloc.rowMeta.id,
|
||||||
|
groupId: widget.groupId,
|
||||||
|
);
|
||||||
|
},
|
||||||
child: RowCardContainer(
|
child: RowCardContainer(
|
||||||
buildAccessoryWhen: () => state.isEditing == false,
|
buildAccessoryWhen: () => state.isEditing == false,
|
||||||
accessoryBuilder: (context) {
|
accessories: [
|
||||||
if (widget.styleConfiguration.showAccessory == false) {
|
if (widget.styleConfiguration.showAccessory) ...[
|
||||||
return [];
|
_CardEditOption(rowNotifier: rowNotifier),
|
||||||
} else {
|
const CardMoreOption(),
|
||||||
return [
|
],
|
||||||
_CardEditOption(rowNotifier: rowNotifier),
|
],
|
||||||
CardMoreOption(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openAccessory: _handleOpenAccessory,
|
openAccessory: _handleOpenAccessory,
|
||||||
openCard: (context) => widget.openCard(context),
|
openCard: (context) => widget.openCard(context),
|
||||||
child: _CardContent<T>(
|
child: _CardContent<T>(
|
||||||
@ -194,22 +185,6 @@ class _RowCardState<T> extends State<RowCard<T>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _handlePopoverBuilder(
|
|
||||||
BuildContext context,
|
|
||||||
BuildContext popoverContext,
|
|
||||||
) {
|
|
||||||
switch (accessoryType!) {
|
|
||||||
case AccessoryType.edit:
|
|
||||||
throw UnimplementedError();
|
|
||||||
case AccessoryType.more:
|
|
||||||
return RowActions(
|
|
||||||
viewId: context.read<CardBloc>().viewId,
|
|
||||||
rowId: context.read<CardBloc>().rowMeta.id,
|
|
||||||
groupId: widget.groupId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
rowNotifier.dispose();
|
rowNotifier.dispose();
|
||||||
@ -241,6 +216,7 @@ class _CardContent<CustomCardData> extends StatelessWidget {
|
|||||||
if (styleConfiguration.hoverStyle != null) {
|
if (styleConfiguration.hoverStyle != null) {
|
||||||
return FlowyHover(
|
return FlowyHover(
|
||||||
style: styleConfiguration.hoverStyle,
|
style: styleConfiguration.hoverStyle,
|
||||||
|
buildWhenOnHover: () => !rowNotifier.isEditing.value,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: styleConfiguration.cardPadding,
|
padding: styleConfiguration.cardPadding,
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -296,21 +272,21 @@ class _CardContent<CustomCardData> extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CardMoreOption extends StatelessWidget with CardAccessory {
|
class CardMoreOption extends StatelessWidget with CardAccessory {
|
||||||
CardMoreOption({Key? key}) : super(key: key);
|
const CardMoreOption({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
AccessoryType get type => AccessoryType.more;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(3.0),
|
padding: const EdgeInsets.all(3.0),
|
||||||
child: FlowySvg(
|
child: FlowySvg(
|
||||||
FlowySvgs.details_s,
|
FlowySvgs.three_dots_s,
|
||||||
color: Theme.of(context).iconTheme.color,
|
color: Theme.of(context).hintColor,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
AccessoryType get type => AccessoryType.more;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CardEditOption extends StatelessWidget with CardAccessory {
|
class _CardEditOption extends StatelessWidget with CardAccessory {
|
||||||
@ -326,7 +302,7 @@ class _CardEditOption extends StatelessWidget with CardAccessory {
|
|||||||
padding: const EdgeInsets.all(3.0),
|
padding: const EdgeInsets.all(3.0),
|
||||||
child: FlowySvg(
|
child: FlowySvg(
|
||||||
FlowySvgs.edit_s,
|
FlowySvgs.edit_s,
|
||||||
color: Theme.of(context).iconTheme.color,
|
color: Theme.of(context).hintColor,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -346,7 +322,7 @@ class RowCardStyleConfiguration {
|
|||||||
|
|
||||||
const RowCardStyleConfiguration({
|
const RowCardStyleConfiguration({
|
||||||
this.showAccessory = true,
|
this.showAccessory = true,
|
||||||
this.cellPadding = const EdgeInsets.only(left: 4, right: 4),
|
this.cellPadding = EdgeInsets.zero,
|
||||||
this.cardPadding = const EdgeInsets.all(8),
|
this.cardPadding = const EdgeInsets.all(8),
|
||||||
this.hoverStyle,
|
this.hoverStyle,
|
||||||
});
|
});
|
||||||
|
@ -5,6 +5,7 @@ import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
import '../define.dart';
|
||||||
import 'card_cell.dart';
|
import 'card_cell.dart';
|
||||||
|
|
||||||
class CheckboxCardCell extends CardCell {
|
class CheckboxCardCell extends CardCell {
|
||||||
@ -24,11 +25,11 @@ class _CheckboxCellState extends State<CheckboxCardCell> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
super.initState();
|
||||||
final cellController =
|
final cellController =
|
||||||
widget.cellControllerBuilder.build() as CheckboxCellController;
|
widget.cellControllerBuilder.build() as CheckboxCellController;
|
||||||
_cellBloc = CheckboxCellBloc(cellController: cellController);
|
_cellBloc = CheckboxCellBloc(cellController: cellController)
|
||||||
_cellBloc.add(const CheckboxCellEvent.initial());
|
..add(const CheckboxCellEvent.initial());
|
||||||
super.initState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -47,7 +48,7 @@ class _CheckboxCellState extends State<CheckboxCardCell> {
|
|||||||
return Align(
|
return Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
padding: CardSizes.cardCellPadding,
|
||||||
child: FlowyIconButton(
|
child: FlowyIconButton(
|
||||||
iconPadding: EdgeInsets.zero,
|
iconPadding: EdgeInsets.zero,
|
||||||
icon: icon,
|
icon: icon,
|
||||||
|
@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../../row/cells/checklist_cell/checklist_cell_bloc.dart';
|
import '../../row/cells/checklist_cell/checklist_cell_bloc.dart';
|
||||||
|
import '../define.dart';
|
||||||
import 'card_cell.dart';
|
import 'card_cell.dart';
|
||||||
|
|
||||||
class ChecklistCardCell extends CardCell {
|
class ChecklistCardCell extends CardCell {
|
||||||
@ -37,7 +38,7 @@ class _ChecklistCellState extends State<ChecklistCardCell> {
|
|||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
padding: CardSizes.cardCellPadding,
|
||||||
child: ChecklistProgressBar(
|
child: ChecklistProgressBar(
|
||||||
tasks: state.tasks,
|
tasks: state.tasks,
|
||||||
percent: state.percent,
|
percent: state.percent,
|
||||||
|
@ -42,31 +42,28 @@ class _DateCellState extends State<DateCardCell> {
|
|||||||
buildWhen: (previous, current) => previous.dateStr != current.dateStr,
|
buildWhen: (previous, current) => previous.dateStr != current.dateStr,
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state.dateStr.isEmpty) {
|
if (state.dateStr.isEmpty) {
|
||||||
return const SizedBox();
|
return const SizedBox.shrink();
|
||||||
} else {
|
|
||||||
final Widget? custom = widget.renderHook?.call(
|
|
||||||
state.data,
|
|
||||||
widget.cardData,
|
|
||||||
context,
|
|
||||||
);
|
|
||||||
if (custom != null) {
|
|
||||||
return custom;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Align(
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.symmetric(
|
|
||||||
vertical: CardSizes.cardCellVPadding,
|
|
||||||
),
|
|
||||||
child: FlowyText.regular(
|
|
||||||
state.dateStr,
|
|
||||||
fontSize: 13,
|
|
||||||
color: Theme.of(context).hintColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
final Widget? custom = widget.renderHook?.call(
|
||||||
|
state.data,
|
||||||
|
widget.cardData,
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
if (custom != null) {
|
||||||
|
return custom;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Padding(
|
||||||
|
padding: CardSizes.cardCellPadding,
|
||||||
|
child: FlowyText.regular(
|
||||||
|
state.dateStr,
|
||||||
|
fontSize: 11,
|
||||||
|
color: Theme.of(context).hintColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -52,30 +52,28 @@ class _NumberCellState extends State<NumberCardCell> {
|
|||||||
previous.cellContent != current.cellContent,
|
previous.cellContent != current.cellContent,
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state.cellContent.isEmpty) {
|
if (state.cellContent.isEmpty) {
|
||||||
return const SizedBox();
|
return const SizedBox.shrink();
|
||||||
} else {
|
|
||||||
final Widget? custom = widget.renderHook?.call(
|
|
||||||
state.cellContent,
|
|
||||||
widget.cardData,
|
|
||||||
context,
|
|
||||||
);
|
|
||||||
if (custom != null) {
|
|
||||||
return custom;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Align(
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.symmetric(
|
|
||||||
vertical: CardSizes.cardCellVPadding,
|
|
||||||
),
|
|
||||||
child: FlowyText.medium(
|
|
||||||
state.cellContent,
|
|
||||||
fontSize: widget.style?.fontSize ?? 14,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
final Widget? custom = widget.renderHook?.call(
|
||||||
|
state.cellContent,
|
||||||
|
widget.cardData,
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
if (custom != null) {
|
||||||
|
return custom;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Padding(
|
||||||
|
padding: CardSizes.cardCellPadding,
|
||||||
|
child: FlowyText.regular(
|
||||||
|
state.cellContent,
|
||||||
|
fontSize: widget.style?.fontSize ?? 11,
|
||||||
|
color: Theme.of(context).hintColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -5,6 +5,7 @@ import 'package:appflowy_backend/protobuf/flowy-database2/select_option.pb.dart'
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
import '../define.dart';
|
||||||
import 'card_cell.dart';
|
import 'card_cell.dart';
|
||||||
|
|
||||||
class SelectOptionCardCellStyle extends CardCellStyle {}
|
class SelectOptionCardCellStyle extends CardCellStyle {}
|
||||||
@ -69,12 +70,11 @@ class _SelectOptionCellState extends State<SelectOptionCardCell> {
|
|||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
return IntrinsicHeight(
|
return Align(
|
||||||
|
alignment: AlignmentDirectional.topStart,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
padding: CardSizes.cardCellPadding,
|
||||||
child: SizedBox.expand(
|
child: Wrap(spacing: 4, runSpacing: 2, children: children),
|
||||||
child: Wrap(spacing: 4, runSpacing: 2, children: children),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
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/plugins/database_view/application/cell/cell_controller_builder.dart';
|
import 'package:appflowy/plugins/database_view/application/cell/cell_controller_builder.dart';
|
||||||
import 'package:appflowy/plugins/database_view/widgets/row/cells/text_cell/text_cell_bloc.dart';
|
import 'package:appflowy/plugins/database_view/widgets/row/cells/text_cell/text_cell_bloc.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../../row/cell_builder.dart';
|
import '../../row/cell_builder.dart';
|
||||||
import '../define.dart';
|
import '../define.dart';
|
||||||
import 'card_cell.dart';
|
import 'card_cell.dart';
|
||||||
@ -120,24 +123,30 @@ class _TextCellState extends State<TextCardCell> {
|
|||||||
return custom;
|
return custom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final isTitle =
|
||||||
|
context.read<TextCellBloc>().cellController.fieldInfo.isPrimary;
|
||||||
if (state.content.isEmpty &&
|
if (state.content.isEmpty &&
|
||||||
state.enableEdit == false &&
|
state.enableEdit == false &&
|
||||||
focusWhenInit == false) {
|
focusWhenInit == false &&
|
||||||
return const SizedBox();
|
!isTitle) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
final child = state.enableEdit || focusWhenInit
|
final child = state.enableEdit || focusWhenInit
|
||||||
? _buildTextField()
|
? _buildTextField()
|
||||||
: _buildText(state);
|
: _buildText(state, isTitle);
|
||||||
|
|
||||||
return Row(
|
return Padding(
|
||||||
children: [
|
padding: CardSizes.cardCellPadding,
|
||||||
if (widget.showNotes) ...[
|
child: Row(
|
||||||
const FlowySvg(FlowySvgs.notes_s),
|
children: [
|
||||||
const HSpace(4),
|
if (widget.showNotes) ...[
|
||||||
|
const FlowySvg(FlowySvgs.notes_s),
|
||||||
|
const HSpace(4),
|
||||||
|
],
|
||||||
|
Expanded(child: child),
|
||||||
],
|
],
|
||||||
Expanded(child: child),
|
),
|
||||||
],
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -157,47 +166,46 @@ class _TextCellState extends State<TextCardCell> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
double _fontSize() {
|
Widget _buildText(TextCellState state, bool isTitle) {
|
||||||
if (widget.style != null) {
|
final text = state.content.isEmpty
|
||||||
return widget.style!.fontSize;
|
? LocaleKeys.grid_row_titlePlaceholder.tr()
|
||||||
}
|
: state.content;
|
||||||
|
final color = state.content.isEmpty ? Theme.of(context).hintColor : null;
|
||||||
return 14;
|
return FlowyText(
|
||||||
}
|
text,
|
||||||
|
fontSize: _fontSize(isTitle),
|
||||||
Widget _buildText(TextCellState state) {
|
fontWeight: _fontWeight(isTitle),
|
||||||
return Padding(
|
color: color,
|
||||||
padding: EdgeInsets.symmetric(
|
maxLines: null, // Enable multiple lines
|
||||||
vertical: CardSizes.cardCellVPadding,
|
|
||||||
),
|
|
||||||
child: FlowyText.medium(
|
|
||||||
state.content,
|
|
||||||
fontSize: _fontSize(),
|
|
||||||
maxLines: null, // Enable multiple lines
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double _fontSize(bool isTitle) {
|
||||||
|
return widget.style?.fontSize ?? (isTitle ? 12 : 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
FontWeight _fontWeight(bool isTitle) {
|
||||||
|
return isTitle ? FontWeight.w500 : FontWeight.w400;
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildTextField() {
|
Widget _buildTextField() {
|
||||||
return IntrinsicHeight(
|
return TextField(
|
||||||
child: TextField(
|
controller: _controller,
|
||||||
controller: _controller,
|
focusNode: focusNode,
|
||||||
focusNode: focusNode,
|
onChanged: (value) => focusChanged(),
|
||||||
onChanged: (value) => focusChanged(),
|
onEditingComplete: () => focusNode.unfocus(),
|
||||||
onEditingComplete: () => focusNode.unfocus(),
|
maxLines: null,
|
||||||
maxLines: null,
|
style: Theme.of(context)
|
||||||
style: Theme.of(context)
|
.textTheme
|
||||||
.textTheme
|
.bodyMedium!
|
||||||
.bodyMedium!
|
.copyWith(fontSize: _fontSize(true)),
|
||||||
.copyWith(fontSize: _fontSize()),
|
decoration: InputDecoration(
|
||||||
decoration: InputDecoration(
|
contentPadding:
|
||||||
// Magic number 4 makes the textField take up the same space as FlowyText
|
EdgeInsets.symmetric(vertical: CardSizes.cardCellPadding.top),
|
||||||
contentPadding: EdgeInsets.symmetric(
|
border: InputBorder.none,
|
||||||
vertical: CardSizes.cardCellVPadding + 4,
|
isDense: true,
|
||||||
),
|
isCollapsed: true,
|
||||||
border: InputBorder.none,
|
hintText: LocaleKeys.grid_row_titlePlaceholder.tr(),
|
||||||
isDense: true,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -56,12 +56,10 @@ class _TimestampCellState extends State<TimestampCardCell> {
|
|||||||
return Align(
|
return Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.symmetric(
|
padding: CardSizes.cardCellPadding,
|
||||||
vertical: CardSizes.cardCellVPadding,
|
|
||||||
),
|
|
||||||
child: FlowyText.regular(
|
child: FlowyText.regular(
|
||||||
state.dateStr,
|
state.dateStr,
|
||||||
fontSize: 13,
|
fontSize: 11,
|
||||||
color: Theme.of(context).hintColor,
|
color: Theme.of(context).hintColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import 'package:appflowy/plugins/database_view/application/cell/cell_controller_builder.dart';
|
import 'package:appflowy/plugins/database_view/application/cell/cell_controller_builder.dart';
|
||||||
import 'package:appflowy/plugins/database_view/widgets/row/cells/url_cell/url_cell_bloc.dart';
|
import 'package:appflowy/plugins/database_view/widgets/row/cells/url_cell/url_cell_bloc.dart';
|
||||||
import 'package:flowy_infra/size.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
@ -48,27 +47,24 @@ class _URLCellState extends State<URLCardCell> {
|
|||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state.content.isEmpty) {
|
if (state.content.isEmpty) {
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
} else {
|
}
|
||||||
return Align(
|
return Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.symmetric(
|
padding: CardSizes.cardCellPadding,
|
||||||
vertical: CardSizes.cardCellVPadding,
|
child: RichText(
|
||||||
),
|
textAlign: TextAlign.left,
|
||||||
child: RichText(
|
text: TextSpan(
|
||||||
textAlign: TextAlign.left,
|
text: state.content,
|
||||||
text: TextSpan(
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
text: state.content,
|
fontSize: widget.style?.fontSize ?? 11,
|
||||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
color: Theme.of(context).colorScheme.primary,
|
||||||
fontSize: widget.style?.fontSize ?? FontSizes.s14,
|
decoration: TextDecoration.underline,
|
||||||
color: Theme.of(context).colorScheme.primary,
|
),
|
||||||
decoration: TextDecoration.underline,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
}
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -26,7 +26,7 @@ class CardAccessoryContainer extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final children = accessories.map((accessory) {
|
final children = accessories.map<Widget>((accessory) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@ -36,32 +36,62 @@ class CardAccessoryContainer extends StatelessWidget {
|
|||||||
child: _wrapHover(context, accessory),
|
child: _wrapHover(context, accessory),
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
return _wrapDecoration(context, Row(children: children));
|
|
||||||
|
children.insert(
|
||||||
|
1,
|
||||||
|
VerticalDivider(
|
||||||
|
width: 1,
|
||||||
|
thickness: 1,
|
||||||
|
color: Theme.of(context).brightness == Brightness.light
|
||||||
|
? const Color(0xFF1F2329).withOpacity(0.12)
|
||||||
|
: const Color(0xff59647a),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return _wrapDecoration(
|
||||||
|
context,
|
||||||
|
IntrinsicHeight(child: Row(children: children)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
FlowyHover _wrapHover(BuildContext context, CardAccessory accessory) {
|
Widget _wrapHover(BuildContext context, CardAccessory accessory) {
|
||||||
return FlowyHover(
|
return SizedBox(
|
||||||
style: HoverStyle(
|
width: 24,
|
||||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
height: 22,
|
||||||
borderRadius: BorderRadius.zero,
|
child: FlowyHover(
|
||||||
),
|
style: HoverStyle(
|
||||||
builder: (_, onHover) => SizedBox(
|
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||||
width: 24,
|
borderRadius: BorderRadius.zero,
|
||||||
height: 24,
|
),
|
||||||
child: accessory,
|
child: accessory,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _wrapDecoration(BuildContext context, Widget child) {
|
Widget _wrapDecoration(BuildContext context, Widget child) {
|
||||||
final borderSide = BorderSide(
|
|
||||||
color: Theme.of(context).dividerColor,
|
|
||||||
width: 1.0,
|
|
||||||
);
|
|
||||||
final decoration = BoxDecoration(
|
final decoration = BoxDecoration(
|
||||||
color: Colors.transparent,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
border: Border.fromBorderSide(borderSide),
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
||||||
|
border: Border.fromBorderSide(
|
||||||
|
BorderSide(
|
||||||
|
color: Theme.of(context).brightness == Brightness.light
|
||||||
|
? const Color(0xFF1F2329).withOpacity(0.12)
|
||||||
|
: const Color(0xff59647a),
|
||||||
|
width: 1.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
blurRadius: 4,
|
||||||
|
spreadRadius: 0,
|
||||||
|
color: const Color(0xFF1F2329).withOpacity(0.02),
|
||||||
|
),
|
||||||
|
BoxShadow(
|
||||||
|
blurRadius: 4,
|
||||||
|
spreadRadius: -2,
|
||||||
|
color: const Color(0xFF1F2329).withOpacity(0.02),
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
return Container(
|
return Container(
|
||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
|
@ -5,7 +5,7 @@ import 'accessory.dart';
|
|||||||
|
|
||||||
class RowCardContainer extends StatelessWidget {
|
class RowCardContainer extends StatelessWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
final CardAccessoryBuilder? accessoryBuilder;
|
final List<CardAccessory> accessories;
|
||||||
final bool Function()? buildAccessoryWhen;
|
final bool Function()? buildAccessoryWhen;
|
||||||
final void Function(BuildContext) openCard;
|
final void Function(BuildContext) openCard;
|
||||||
final void Function(AccessoryType) openAccessory;
|
final void Function(AccessoryType) openAccessory;
|
||||||
@ -13,7 +13,7 @@ class RowCardContainer extends StatelessWidget {
|
|||||||
required this.child,
|
required this.child,
|
||||||
required this.openCard,
|
required this.openCard,
|
||||||
required this.openAccessory,
|
required this.openAccessory,
|
||||||
this.accessoryBuilder,
|
required this.accessories,
|
||||||
this.buildAccessoryWhen,
|
this.buildAccessoryWhen,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@ -30,15 +30,12 @@ class RowCardContainer extends StatelessWidget {
|
|||||||
shouldBuildAccessory = buildAccessoryWhen!.call();
|
shouldBuildAccessory = buildAccessoryWhen!.call();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accessoryBuilder != null && shouldBuildAccessory) {
|
if (shouldBuildAccessory && accessories.isNotEmpty) {
|
||||||
final accessories = accessoryBuilder!(context);
|
container = _CardEnterRegion(
|
||||||
if (accessories.isNotEmpty) {
|
accessories: accessories,
|
||||||
container = _CardEnterRegion(
|
onTapAccessory: openAccessory,
|
||||||
accessories: accessories,
|
child: container,
|
||||||
onTapAccessory: openAccessory,
|
);
|
||||||
child: container,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
@ -75,8 +72,8 @@ class _CardEnterRegion extends StatelessWidget {
|
|||||||
if (onEnter) {
|
if (onEnter) {
|
||||||
children.add(
|
children.add(
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 8.0,
|
top: 10.0,
|
||||||
right: 8.0,
|
right: 10.0,
|
||||||
child: CardAccessoryContainer(
|
child: CardAccessoryContainer(
|
||||||
accessories: accessories,
|
accessories: accessories,
|
||||||
onTapAccessory: onTapAccessory,
|
onTapAccessory: onTapAccessory,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
class CardSizes {
|
class CardSizes {
|
||||||
static double get cardCellVPadding => 6;
|
static EdgeInsets get cardCellPadding => const EdgeInsets.all(4);
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ class GridChecklistCellState extends GridCellState<GridChecklistCell> {
|
|||||||
: LocaleKeys.grid_checklist_hideComplete.tr(),
|
: LocaleKeys.grid_checklist_hideComplete.tr(),
|
||||||
width: 32,
|
width: 32,
|
||||||
iconColorOnHover:
|
iconColorOnHover:
|
||||||
Theme.of(context).colorScheme.onPrimary,
|
Theme.of(context).colorScheme.onSurface,
|
||||||
icon: FlowySvg(
|
icon: FlowySvg(
|
||||||
showIncompleteOnly
|
showIncompleteOnly
|
||||||
? FlowySvgs.show_m
|
? FlowySvgs.show_m
|
||||||
|
@ -106,7 +106,7 @@ class SelectOptionTag extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Flexible(
|
Flexible(
|
||||||
child: FlowyText.medium(
|
child: FlowyText.regular(
|
||||||
name,
|
name,
|
||||||
fontSize: FontSizes.s11,
|
fontSize: FontSizes.s11,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
@ -135,11 +135,11 @@ class SelectOptionTagCell extends StatelessWidget {
|
|||||||
final void Function(SelectOptionPB) onSelected;
|
final void Function(SelectOptionPB) onSelected;
|
||||||
final SelectOptionPB option;
|
final SelectOptionPB option;
|
||||||
const SelectOptionTagCell({
|
const SelectOptionTagCell({
|
||||||
|
super.key,
|
||||||
required this.option,
|
required this.option,
|
||||||
required this.onSelected,
|
required this.onSelected,
|
||||||
this.children = const [],
|
this.children = const [],
|
||||||
Key? key,
|
});
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -17,5 +17,6 @@ export 'style_widget/button.dart';
|
|||||||
export 'style_widget/icon_button.dart';
|
export 'style_widget/icon_button.dart';
|
||||||
export 'style_widget/scrolling/styled_scroll_bar.dart';
|
export 'style_widget/scrolling/styled_scroll_bar.dart';
|
||||||
export '/widget/spacing.dart';
|
export '/widget/spacing.dart';
|
||||||
|
export '/widget/separated_flex.dart';
|
||||||
export 'style_widget/scrolling/styled_list.dart';
|
export 'style_widget/scrolling/styled_list.dart';
|
||||||
export 'style_widget/color_picker.dart';
|
export 'style_widget/color_picker.dart';
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
typedef SeparatorBuilder = Widget Function();
|
||||||
|
|
||||||
|
class SeparatedColumn extends Column {
|
||||||
|
SeparatedColumn({
|
||||||
|
super.key,
|
||||||
|
super.mainAxisAlignment,
|
||||||
|
super.crossAxisAlignment,
|
||||||
|
super.mainAxisSize,
|
||||||
|
super.textBaseline,
|
||||||
|
super.textDirection,
|
||||||
|
super.verticalDirection,
|
||||||
|
required SeparatorBuilder separatorBuilder,
|
||||||
|
required List<Widget> children,
|
||||||
|
}) : super(children: _insertSeparators(children, separatorBuilder));
|
||||||
|
}
|
||||||
|
|
||||||
|
class SeparatedRow extends Row {
|
||||||
|
SeparatedRow({
|
||||||
|
super.key,
|
||||||
|
super.mainAxisAlignment,
|
||||||
|
super.crossAxisAlignment,
|
||||||
|
super.mainAxisSize,
|
||||||
|
super.textBaseline,
|
||||||
|
super.textDirection,
|
||||||
|
super.verticalDirection,
|
||||||
|
required SeparatorBuilder separatorBuilder,
|
||||||
|
required List<Widget> children,
|
||||||
|
}) : super(children: _insertSeparators(children, separatorBuilder));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> _insertSeparators(
|
||||||
|
List<Widget> children,
|
||||||
|
SeparatorBuilder separatorBuilder,
|
||||||
|
) {
|
||||||
|
if (children.length < 2) {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> newChildren = [];
|
||||||
|
for (int i = 0; i < children.length - 1; i++) {
|
||||||
|
newChildren.add(children[i]);
|
||||||
|
newChildren.add(separatorBuilder());
|
||||||
|
}
|
||||||
|
return newChildren..add(children.last);
|
||||||
|
}
|
@ -1,43 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
typedef SeparatorBuilder = Widget Function();
|
|
||||||
|
|
||||||
class SeparatedColumn extends StatelessWidget {
|
|
||||||
final List<Widget> children;
|
|
||||||
final SeparatorBuilder? separatorBuilder;
|
|
||||||
final MainAxisAlignment mainAxisAlignment;
|
|
||||||
final CrossAxisAlignment crossAxisAlignment;
|
|
||||||
final MainAxisSize mainAxisSize;
|
|
||||||
final TextBaseline? textBaseline;
|
|
||||||
final TextDirection? textDirection;
|
|
||||||
final VerticalDirection verticalDirection;
|
|
||||||
|
|
||||||
const SeparatedColumn({
|
|
||||||
Key? key,
|
|
||||||
required this.children,
|
|
||||||
this.separatorBuilder,
|
|
||||||
this.mainAxisAlignment = MainAxisAlignment.start,
|
|
||||||
this.crossAxisAlignment = CrossAxisAlignment.center,
|
|
||||||
this.mainAxisSize = MainAxisSize.max,
|
|
||||||
this.verticalDirection = VerticalDirection.down,
|
|
||||||
this.textBaseline,
|
|
||||||
this.textDirection,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
var c = children.toList();
|
|
||||||
for (var i = c.length; i-- > 0;) {
|
|
||||||
if (i > 0 && separatorBuilder != null) c.insert(i, separatorBuilder!());
|
|
||||||
}
|
|
||||||
return Column(
|
|
||||||
mainAxisAlignment: mainAxisAlignment,
|
|
||||||
crossAxisAlignment: crossAxisAlignment,
|
|
||||||
mainAxisSize: mainAxisSize,
|
|
||||||
textBaseline: textBaseline,
|
|
||||||
textDirection: textDirection,
|
|
||||||
verticalDirection: verticalDirection,
|
|
||||||
children: c,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user