Skip to content

Commit

Permalink
feat: custom database field icons (AppFlowy-IO#6415)
Browse files Browse the repository at this point in the history
  • Loading branch information
richardshiue authored Sep 30, 2024
1 parent 7ac3b72 commit 70e72d8
Show file tree
Hide file tree
Showing 51 changed files with 632 additions and 403 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ void main() {

// Invoke the field editor
await tester.tapGridFieldWithName('Name');
await tester.tapEditFieldButton();

await tester.renameField('hello world');
await tester.dismissFieldEditor();
Expand All @@ -33,6 +32,32 @@ void main() {
await tester.pumpAndSettle();
});

testWidgets('edit field icon', (tester) async {
const icon = 'artificial_intelligence/ai-upscale-spark';
await tester.initializeAppFlowy();
await tester.tapAnonymousSignInButton();

await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Grid);

tester.assertFieldSvg('Name', FieldType.RichText);

// choose specific icon
await tester.tapGridFieldWithName('Name');
await tester.changeFieldIcon(icon);
await tester.dismissFieldEditor();

tester.assertFieldCustomSvg('Name', icon);

// remove icon
await tester.tapGridFieldWithName('Name');
await tester.changeFieldIcon('');
await tester.dismissFieldEditor();

tester.assertFieldSvg('Name', FieldType.RichText);

await tester.pumpAndSettle();
});

testWidgets('update field type of existing field', (tester) async {
await tester.initializeAppFlowy();
await tester.tapAnonymousSignInButton();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'dart:io';

import 'package:appflowy/plugins/database/application/field/filter_entities.dart';
import 'package:appflowy/shared/icon_emoji_picker/flowy_icon_emoji_picker.dart';
import 'package:appflowy/shared/icon_emoji_picker/icon_picker.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
Expand Down Expand Up @@ -681,6 +683,53 @@ extension AppFlowyDatabaseTest on WidgetTester {
await dismissFieldEditor();
}

Future<void> changeFieldIcon(String icon) async {
await tapButton(find.byType(FieldEditIconButton));
if (icon.isEmpty) {
final button = find.descendant(
of: find.byType(FlowyIconEmojiPicker),
matching: find.text(
LocaleKeys.button_remove.tr(),
),
);
await tapButton(button);
} else {
final svgContent = kIconGroups?.findSvgContent(icon);
await tapButton(
find.byWidgetPredicate(
(widget) => widget is FlowySvg && widget.svgString == svgContent,
),
);
}
}

void assertFieldSvg(String name, FieldType fieldType) {
final svgFinder = find.byWidgetPredicate(
(widget) => widget is FlowySvg && widget.svg == fieldType.svgData,
);
final fieldButton = find.byWidgetPredicate(
(widget) => widget is FieldCellButton && widget.field.name == name,
);
expect(
find.descendant(of: fieldButton, matching: svgFinder),
findsOneWidget,
);
}

void assertFieldCustomSvg(String name, String svg) {
final svgContent = kIconGroups?.findSvgContent(svg);
final svgFinder = find.byWidgetPredicate(
(widget) => widget is FlowySvg && widget.svgString == svgContent,
);
final fieldButton = find.byWidgetPredicate(
(widget) => widget is FieldCellButton && widget.field.name == name,
);
expect(
find.descendant(of: fieldButton, matching: svgFinder),
findsOneWidget,
);
}

Future<void> changeCalculateAtIndex(int index, CalculationType type) async {
await tap(find.byType(CalculateCell).at(index));
await pumpAndSettle();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import 'package:flutter/material.dart';

import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
import 'package:appflowy/plugins/database/grid/application/row/row_detail_bloc.dart';
import 'package:appflowy/plugins/database/grid/presentation/widgets/header/desktop_field_cell.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_builder.dart';
import 'package:appflowy/util/field_type_extension.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class MobileRowPropertyList extends StatelessWidget {
Expand Down Expand Up @@ -77,10 +75,8 @@ class _PropertyCellState extends State<_PropertyCell> {
children: [
Row(
children: [
FlowySvg(
fieldInfo.fieldType.svgData,
color: Theme.of(context).hintColor,
size: const Size.square(16),
FieldIcon(
fieldInfo: fieldInfo,
),
const HSpace(6),
Expanded(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ class OptionTextField extends StatelessWidget {
const OptionTextField({
super.key,
required this.controller,
required this.type,
required this.fieldType,
required this.onTextChanged,
required this.onFieldTypeChanged,
});

final TextEditingController controller;
final FieldType type;
final FieldType fieldType;
final void Function(String value) onTextChanged;
final void Function(FieldType value) onFieldTypeChanged;

Expand All @@ -43,12 +43,12 @@ class OptionTextField extends StatelessWidget {
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Theme.of(context).brightness == Brightness.light
? type.mobileIconBackgroundColor
: type.mobileIconBackgroundColorDark,
? fieldType.mobileIconBackgroundColor
: fieldType.mobileIconBackgroundColorDark,
),
child: Center(
child: FlowySvg(
type.svgData,
fieldType.svgData,
size: const Size.square(22),
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class _MobileNewPropertyScreenState extends State<MobileNewPropertyScreen> {
final type = widget.fieldType ?? FieldType.RichText;
optionValues = FieldOptionValues(
type: type,
icon: "",
name: type.i18n,
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/mobile/presentation/base/app_bar/app_bar_actions.dart';
import 'package:appflowy/mobile/presentation/widgets/flowy_option_tile.dart';
import 'package:appflowy/plugins/base/drag_handler.dart';
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
import 'package:appflowy/plugins/database/application/field/field_info.dart';
import 'package:appflowy/util/field_type_extension.dart';
import 'package:appflowy/plugins/database/grid/presentation/widgets/header/desktop_field_cell.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
Expand Down Expand Up @@ -132,9 +131,9 @@ class _FieldButton extends StatelessWidget {
return FlowyOptionTile.checkbox(
text: field.name,
isSelected: isSelected,
leftIcon: FlowySvg(
field.fieldType.svgData,
size: const Size.square(20),
leftIcon: FieldIcon(
fieldInfo: field,
dimension: 20,
),
showTopBorder: showTopBorder,
onTap: () => onSelect(field.id),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class FieldOptionValues {
FieldOptionValues({
required this.type,
required this.name,
required this.icon,
this.dateFormat,
this.timeFormat,
this.includeTime,
Expand All @@ -48,6 +49,7 @@ class FieldOptionValues {
return FieldOptionValues(
type: fieldType,
name: field.name,
icon: field.icon,
numberFormat: fieldType == FieldType.Number
? NumberTypeOptionPB.fromBuffer(buffer).format
: null,
Expand Down Expand Up @@ -83,6 +85,7 @@ class FieldOptionValues {

FieldType type;
String name;
String icon;

// FieldType.DateTime
// FieldType.LastEditedTime
Expand Down Expand Up @@ -221,7 +224,7 @@ class _MobileFieldEditorState extends State<MobileFieldEditor> {
const _Divider(),
OptionTextField(
controller: controller,
type: values.type,
fieldType: values.type,
onTextChanged: (value) {
isFieldNameChanged = true;
_updateOptionValues(name: value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class _QuickEditFieldState extends State<QuickEditField> {
const VSpace(16),
OptionTextField(
controller: controller,
type: state.field.fieldType,
fieldType: state.field.fieldType,
onTextChanged: (text) {
context
.read<FieldEditorBloc>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
import 'package:appflowy/plugins/database/application/field/field_info.dart';
import 'package:appflowy/plugins/database/application/setting/property_bloc.dart';
import 'package:appflowy/plugins/database/grid/presentation/widgets/header/desktop_field_cell.dart';
import 'package:appflowy/plugins/database/widgets/setting/field_visibility_extension.dart';
import 'package:appflowy/util/field_type_extension.dart';
import 'package:appflowy/workspace/application/view/view_bloc.dart';
import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart';
Expand Down Expand Up @@ -168,19 +168,19 @@ class DatabaseFieldListTile extends StatelessWidget {
if (fieldInfo.field.isPrimary) {
return FlowyOptionTile.text(
text: fieldInfo.name,
leftIcon: FlowySvg(
fieldInfo.fieldType.svgData,
size: const Size.square(20),
leftIcon: FieldIcon(
fieldInfo: fieldInfo,
dimension: 20,
),
showTopBorder: showTopBorder,
);
} else {
return FlowyOptionTile.toggle(
isSelected: fieldInfo.visibility?.isVisibleState() ?? false,
text: fieldInfo.name,
leftIcon: FlowySvg(
fieldInfo.fieldType.svgData,
size: const Size.square(20),
leftIcon: FieldIcon(
fieldInfo: fieldInfo,
dimension: 20,
),
showTopBorder: showTopBorder,
onTap: () => showEditFieldScreen(context, viewId, fieldInfo),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:appflowy/plugins/database/application/field/filter_entities.dart
import 'package:appflowy/plugins/database/grid/application/filter/filter_editor_bloc.dart';
import 'package:appflowy/plugins/database/grid/application/filter/select_option_loader.dart';
import 'package:appflowy/plugins/database/grid/presentation/widgets/filter/choicechip/date.dart';
import 'package:appflowy/plugins/database/grid/presentation/widgets/header/desktop_field_cell.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/mobile_select_option_editor.dart';
import 'package:appflowy/util/debounce.dart';
import 'package:appflowy/util/field_type_extension.dart';
Expand Down Expand Up @@ -620,10 +621,10 @@ class _FilterableFieldList extends StatelessWidget {
itemBuilder: (context, index) {
return FlowyOptionTile.checkbox(
text: blocState.fields[index].name,
showTopBorder: false,
leftIcon: FlowySvg(
blocState.fields[index].fieldType.svgData,
leftIcon: FieldIcon(
fieldInfo: blocState.fields[index],
),
showTopBorder: false,
isSelected: _isSelected(context, blocState, index),
onTap: () => onSelectField(blocState.fields[index]),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
import 'package:appflowy/plugins/database/application/field/field_info.dart';
import 'package:appflowy/plugins/database/application/field/sort_entities.dart';
import 'package:appflowy/plugins/database/grid/application/sort/sort_editor_bloc.dart';
import 'package:appflowy/plugins/database/grid/presentation/widgets/header/desktop_field_cell.dart';
import 'package:appflowy/util/field_type_extension.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:collection/collection.dart';
Expand Down Expand Up @@ -523,12 +524,12 @@ class _SortDetailContent extends StatelessWidget {

return FlowyOptionTile.checkbox(
text: fieldInfo.field.name,
leftIcon: FieldIcon(
fieldInfo: fieldInfo,
),
isSelected: isSelected,
textColor: enabled ? null : Theme.of(context).disabledColor,
showTopBorder: false,
leftIcon: FlowySvg(
fieldInfo.fieldType.svgData,
),
onTap: () {
if (isSelected) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
_logIfError(result);
emit(state.copyWith(wasRenameManually: true));
},
updateIcon: (icon) async {
final result = await _fieldService.updateField(icon: icon);
_logIfError(result);
},
updateTypeOption: (typeOptionData) async {
final result = await FieldBackendService.updateFieldTypeOption(
viewId: viewId,
Expand Down Expand Up @@ -165,6 +169,7 @@ class FieldEditorEvent with _$FieldEditorEvent {
final Uint8List typeOptionData,
) = _UpdateTypeOption;
const factory FieldEditorEvent.renameField(final String name) = _RenameField;
const factory FieldEditorEvent.updateIcon(String icon) = _UpdateIcon;
const factory FieldEditorEvent.insertLeft() = _InsertLeft;
const factory FieldEditorEvent.insertRight() = _InsertRight;
const factory FieldEditorEvent.toggleFieldVisibility() =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class FieldInfo with _$FieldInfo {

String get name => field.name;

String get icon => field.icon;

bool get isPrimary => field.isPrimary;

double? get width => fieldSettings?.width.toDouble();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import 'package:flutter/material.dart';

import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/text_cell_bloc.dart';
Expand All @@ -9,18 +7,19 @@ import 'package:appflowy/plugins/database/application/field/field_controller.dar
import 'package:appflowy/plugins/database/application/row/row_controller.dart';
import 'package:appflowy/plugins/database/calendar/application/calendar_bloc.dart';
import 'package:appflowy/plugins/database/calendar/application/calendar_event_editor_bloc.dart';
import 'package:appflowy/plugins/database/grid/presentation/widgets/header/desktop_field_cell.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_builder.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_skeleton/text.dart';
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/row_detail.dart';
import 'package:appflowy/util/field_type_extension.dart';
import 'package:appflowy/workspace/application/view/view_bloc.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class CalendarEventEditor extends StatelessWidget {
Expand Down Expand Up @@ -248,10 +247,9 @@ class _PropertyCellState extends State<PropertyCell> {
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 6),
child: Row(
children: [
FlowySvg(
fieldInfo.fieldType.svgData,
color: Theme.of(context).hintColor,
size: const Size.square(14),
FieldIcon(
fieldInfo: fieldInfo,
dimension: 14,
),
const HSpace(4.0),
Expanded(
Expand Down
Loading

0 comments on commit 70e72d8

Please sign in to comment.