feat: add require_trailing_commas to analysis_options.ymal. ()

This commit is contained in:
Lucas.Xu 2023-04-10 15:10:42 +08:00 committed by GitHub
parent 4d56b42b83
commit aac5c2a4da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
210 changed files with 2927 additions and 1984 deletions
.github/workflows
frontend/appflowy_flutter
analysis_options.yaml
integration_test
lib
core
plugins/database_view
application
board/application
calendar
grid
widgets

@ -99,7 +99,8 @@ jobs:
- name: Flutter Analyzer - name: Flutter Analyzer
working-directory: frontend/appflowy_flutter working-directory: frontend/appflowy_flutter
run: flutter analyze run: |
flutter analyze .
- name: Run Flutter unit tests - name: Run Flutter unit tests
working-directory: frontend working-directory: frontend

@ -14,9 +14,7 @@ analyzer:
exclude: exclude:
- "**/*.g.dart" - "**/*.g.dart"
- "**/*.freezed.dart" - "**/*.freezed.dart"
- "packages/appflowy_editor/**"
- "packages/editor/**"
# - "packages/flowy_infra_ui/**"
linter: linter:
# The lint rules applied to this project can be customized in the # The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml` # section below to disable rules from the `package:flutter_lints/flutter.yaml`
@ -30,8 +28,7 @@ linter:
# `// ignore_for_file: name_of_lint` syntax on the line or in the file # `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint. # producing the lint.
rules: rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule - require_trailing_commas
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at # Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options # https://dart.dev/guides/language/analysis-options

@ -35,7 +35,9 @@ void main() {
setUpAll(() async => await service.setUpAll()); setUpAll(() async => await service.setUpAll());
setUp(() async => await service.setUp()); setUp(() async => await service.setUp());
testWidgets('integration test unzips the proper workspace and loads it correctly.', (tester) async { testWidgets(
'integration test unzips the proper workspace and loads it correctly.',
(tester) async {
await tester.initializeAppFlowy(); await tester.initializeAppFlowy();
expect(find.byType(AppFlowyBoard), findsOneWidget); expect(find.byType(AppFlowyBoard), findsOneWidget);
}); });

@ -31,7 +31,8 @@ void main() {
setUpAll(() async => await service.setUpAll()); setUpAll(() async => await service.setUpAll());
setUp(() async => await service.setUp()); setUp(() async => await service.setUp());
testWidgets('/board shortcut creates a new board and view of the board', (tester) async { testWidgets('/board shortcut creates a new board and view of the board',
(tester) async {
await tester.initializeAppFlowy(); await tester.initializeAppFlowy();
// Needs tab to obtain focus for the app flowy editor. // Needs tab to obtain focus for the app flowy editor.
@ -44,24 +45,30 @@ void main() {
// does not contain any EditableText widgets. // does not contain any EditableText widgets.
// to interact with the app during an integration test, // to interact with the app during an integration test,
// simulate physical keyboard events. // simulate physical keyboard events.
await FlowyTestKeyboard.simulateKeyDownEvent([ await FlowyTestKeyboard.simulateKeyDownEvent(
LogicalKeyboardKey.slash, [
LogicalKeyboardKey.keyB, LogicalKeyboardKey.slash,
LogicalKeyboardKey.keyO, LogicalKeyboardKey.keyB,
LogicalKeyboardKey.keyA, LogicalKeyboardKey.keyO,
LogicalKeyboardKey.keyR, LogicalKeyboardKey.keyA,
LogicalKeyboardKey.keyD, LogicalKeyboardKey.keyR,
LogicalKeyboardKey.arrowDown, LogicalKeyboardKey.keyD,
], tester: tester); LogicalKeyboardKey.arrowDown,
],
tester: tester,
);
// Checks whether the options in the selection menu // Checks whether the options in the selection menu
// for /board exist. // for /board exist.
expect(find.byType(SelectionMenuItemWidget), findsAtLeastNWidgets(2)); expect(find.byType(SelectionMenuItemWidget), findsAtLeastNWidgets(2));
// Finalizes the slash command that creates the board. // Finalizes the slash command that creates the board.
await FlowyTestKeyboard.simulateKeyDownEvent([ await FlowyTestKeyboard.simulateKeyDownEvent(
LogicalKeyboardKey.enter, [
], tester: tester); LogicalKeyboardKey.enter,
],
tester: tester,
);
// Checks whether new board is referenced and properly on the page. // Checks whether new board is referenced and properly on the page.
expect(find.byType(BuiltInPageWidget), findsOneWidget); expect(find.byType(BuiltInPageWidget), findsOneWidget);
@ -75,7 +82,8 @@ void main() {
expect(find.text(viewOfBoardLabel), findsNWidgets(2)); expect(find.text(viewOfBoardLabel), findsNWidgets(2));
}); });
testWidgets('/grid shortcut creates a new grid and view of the grid', (tester) async { testWidgets('/grid shortcut creates a new grid and view of the grid',
(tester) async {
await tester.initializeAppFlowy(); await tester.initializeAppFlowy();
// Needs tab to obtain focus for the app flowy editor. // Needs tab to obtain focus for the app flowy editor.
@ -88,14 +96,17 @@ void main() {
// does not contain any EditableText widgets. // does not contain any EditableText widgets.
// to interact with the app during an integration test, // to interact with the app during an integration test,
// simulate physical keyboard events. // simulate physical keyboard events.
await FlowyTestKeyboard.simulateKeyDownEvent([ await FlowyTestKeyboard.simulateKeyDownEvent(
LogicalKeyboardKey.slash, [
LogicalKeyboardKey.keyG, LogicalKeyboardKey.slash,
LogicalKeyboardKey.keyR, LogicalKeyboardKey.keyG,
LogicalKeyboardKey.keyI, LogicalKeyboardKey.keyR,
LogicalKeyboardKey.keyD, LogicalKeyboardKey.keyI,
LogicalKeyboardKey.arrowDown, LogicalKeyboardKey.keyD,
], tester: tester); LogicalKeyboardKey.arrowDown,
],
tester: tester,
);
// Checks whether the options in the selection menu // Checks whether the options in the selection menu
// for /grid exist. // for /grid exist.

@ -61,6 +61,8 @@ class TestWorkspaceService {
InputFileStream(await workspace.zip.then((value) => value.path)); InputFileStream(await workspace.zip.then((value) => value.path));
final archive = ZipDecoder().decodeBuffer(inputStream); final archive = ZipDecoder().decodeBuffer(inputStream);
extractArchiveToDisk( extractArchiveToDisk(
archive, await TestWorkspace._parent.then((value) => value.path)); archive,
await TestWorkspace._parent.then((value) => value.path),
);
} }
} }

@ -2,8 +2,10 @@ import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart' as flutter_test; import 'package:flutter_test/flutter_test.dart' as flutter_test;
class FlowyTestKeyboard { class FlowyTestKeyboard {
static Future<void> simulateKeyDownEvent(List<LogicalKeyboardKey> keys, static Future<void> simulateKeyDownEvent(
{required flutter_test.WidgetTester tester}) async { List<LogicalKeyboardKey> keys, {
required flutter_test.WidgetTester tester,
}) async {
for (final LogicalKeyboardKey key in keys) { for (final LogicalKeyboardKey key in keys) {
await flutter_test.simulateKeyDownEvent(key); await flutter_test.simulateKeyDownEvent(key);
await tester.pumpAndSettle(); await tester.pumpAndSettle();

@ -16,9 +16,10 @@ typedef FolderNotificationCallback = void Function(
class FolderNotificationParser class FolderNotificationParser
extends NotificationParser<FolderNotification, FlowyError> { extends NotificationParser<FolderNotification, FlowyError> {
FolderNotificationParser( FolderNotificationParser({
{String? id, required FolderNotificationCallback callback}) String? id,
: super( required FolderNotificationCallback callback,
}) : super(
id: id, id: id,
callback: callback, callback: callback,
tyParser: (ty) => FolderNotification.valueOf(ty), tyParser: (ty) => FolderNotification.valueOf(ty),

@ -16,9 +16,10 @@ typedef DatabaseNotificationCallback = void Function(
class DatabaseNotificationParser class DatabaseNotificationParser
extends NotificationParser<DatabaseNotification, FlowyError> { extends NotificationParser<DatabaseNotification, FlowyError> {
DatabaseNotificationParser( DatabaseNotificationParser({
{String? id, required DatabaseNotificationCallback callback}) String? id,
: super( required DatabaseNotificationCallback callback,
}) : super(
id: id, id: id,
callback: callback, callback: callback,
tyParser: (ty) => DatabaseNotification.valueOf(ty), tyParser: (ty) => DatabaseNotification.valueOf(ty),
@ -27,7 +28,9 @@ class DatabaseNotificationParser
} }
typedef DatabaseNotificationHandler = Function( typedef DatabaseNotificationHandler = Function(
DatabaseNotification ty, Either<Uint8List, FlowyError> result); DatabaseNotification ty,
Either<Uint8List, FlowyError> result,
);
class DatabaseNotificationListener { class DatabaseNotificationListener {
StreamSubscription<SubscribeObject>? _subscription; StreamSubscription<SubscribeObject>? _subscription;

@ -9,11 +9,12 @@ class NotificationParser<T, E> {
T? Function(int) tyParser; T? Function(int) tyParser;
E Function(Uint8List) errorParser; E Function(Uint8List) errorParser;
NotificationParser( NotificationParser({
{this.id, this.id,
required this.callback, required this.callback,
required this.errorParser, required this.errorParser,
required this.tyParser}); required this.tyParser,
});
void parse(SubscribeObject subject) { void parse(SubscribeObject subject) {
if (id != null) { if (id != null) {
if (subject.id != id) { if (subject.id != id) {

@ -16,9 +16,10 @@ typedef UserNotificationCallback = void Function(
class UserNotificationParser class UserNotificationParser
extends NotificationParser<UserNotification, FlowyError> { extends NotificationParser<UserNotification, FlowyError> {
UserNotificationParser( UserNotificationParser({
{required String id, required UserNotificationCallback callback}) required String id,
: super( required UserNotificationCallback callback,
}) : super(
id: id, id: id,
callback: callback, callback: callback,
tyParser: (ty) => UserNotification.valueOf(ty), tyParser: (ty) => UserNotification.valueOf(ty),
@ -27,7 +28,9 @@ class UserNotificationParser
} }
typedef UserNotificationHandler = Function( typedef UserNotificationHandler = Function(
UserNotification ty, Either<Uint8List, FlowyError> result); UserNotification ty,
Either<Uint8List, FlowyError> result,
);
class UserNotificationListener { class UserNotificationListener {
StreamSubscription<SubscribeObject>? _subscription; StreamSubscription<SubscribeObject>? _subscription;

@ -73,28 +73,35 @@ class CellController<T, D> extends Equatable {
/// For example: /// For example:
/// user input: 12 /// user input: 12
/// cell display: $12 /// cell display: $12
_cellListener?.start(onCellChanged: (result) { _cellListener?.start(
result.fold( onCellChanged: (result) {
(_) { result.fold(
_cellCache.remove(_cacheKey); (_) {
_loadData(); _cellCache.remove(_cacheKey);
}, _loadData();
(err) => Log.error(err), },
); (err) => Log.error(err),
}); );
},
);
/// 2.Listen on the field event and load the cell data if needed. /// 2.Listen on the field event and load the cell data if needed.
_fieldListener.start(onFieldChanged: (result) { _fieldListener.start(
result.fold((fieldPB) { onFieldChanged: (result) {
/// reloadOnFieldChanged should be true if you need to load the data when the corresponding field is changed result.fold(
/// For example: (fieldPB) {
/// 12 -> $12 /// reloadOnFieldChanged should be true if you need to load the data when the corresponding field is changed
if (_cellDataLoader.reloadOnFieldChanged) { /// For example:
_loadData(); /// 12 -> $12
} if (_cellDataLoader.reloadOnFieldChanged) {
_onCellFieldChanged?.call(); _loadData();
}, (err) => Log.error(err)); }
}); _onCellFieldChanged?.call();
},
(err) => Log.error(err),
);
},
);
} }
/// Listen on the cell content or field changes /// Listen on the cell content or field changes
@ -130,7 +137,8 @@ class CellController<T, D> extends Equatable {
/// Return the TypeOptionPB that can be parsed into corresponding class using the [parser]. /// Return the TypeOptionPB that can be parsed into corresponding class using the [parser].
/// [PD] is the type that the parser return. /// [PD] is the type that the parser return.
Future<Either<PD, FlowyError>> getTypeOption<PD, P extends TypeOptionParser>( Future<Either<PD, FlowyError>> getTypeOption<PD, P extends TypeOptionParser>(
P parser) { P parser,
) {
return _fieldBackendSvc return _fieldBackendSvc
.getFieldTypeOptionData(fieldType: fieldType) .getFieldTypeOptionData(fieldType: fieldType)
.then((result) { .then((result) {

@ -19,7 +19,9 @@ class CellListener {
void start({required void Function(UpdateFieldNotifiedValue) onCellChanged}) { void start({required void Function(UpdateFieldNotifiedValue) onCellChanged}) {
_updateCellNotifier?.addPublishListener(onCellChanged); _updateCellNotifier?.addPublishListener(onCellChanged);
_listener = DatabaseNotificationListener( _listener = DatabaseNotificationListener(
objectId: "$rowId:$fieldId", handler: _handler); objectId: "$rowId:$fieldId",
handler: _handler,
);
} }
void _handler(DatabaseNotification ty, Either<Uint8List, FlowyError> result) { void _handler(DatabaseNotification ty, Either<Uint8List, FlowyError> result) {

@ -187,8 +187,10 @@ class DatabaseController {
); );
} }
Future<Either<Unit, FlowyError>> moveGroup( Future<Either<Unit, FlowyError>> moveGroup({
{required String fromGroupId, required String toGroupId}) { required String fromGroupId,
required String toGroupId,
}) {
return _databaseViewBackendSvc.moveGroup( return _databaseViewBackendSvc.moveGroup(
fromGroupId: fromGroupId, fromGroupId: fromGroupId,
toGroupId: toGroupId, toGroupId: toGroupId,
@ -196,7 +198,8 @@ class DatabaseController {
} }
Future<void> updateCalenderLayoutSetting( Future<void> updateCalenderLayoutSetting(
CalendarLayoutSettingsPB layoutSetting) async { CalendarLayoutSettingsPB layoutSetting,
) async {
await _databaseViewBackendSvc await _databaseViewBackendSvc
.updateLayoutSetting(calendarLayoutSetting: layoutSetting) .updateLayoutSetting(calendarLayoutSetting: layoutSetting)
.then((result) { .then((result) {
@ -234,16 +237,20 @@ class DatabaseController {
} }
void _listenOnRowsChanged() { void _listenOnRowsChanged() {
final callbacks = final callbacks = DatabaseViewCallbacks(
DatabaseViewCallbacks(onRowsChanged: (rows, rowByRowId, reason) { onRowsChanged: (rows, rowByRowId, reason) {
_databaseCallbacks?.onRowsChanged?.call(rows, rowByRowId, reason); _databaseCallbacks?.onRowsChanged?.call(rows, rowByRowId, reason);
}, onRowsDeleted: (ids) { },
_databaseCallbacks?.onRowsDeleted?.call(ids); onRowsDeleted: (ids) {
}, onRowsUpdated: (ids) { _databaseCallbacks?.onRowsDeleted?.call(ids);
_databaseCallbacks?.onRowsUpdated?.call(ids); },
}, onRowsCreated: (ids) { onRowsUpdated: (ids) {
_databaseCallbacks?.onRowsCreated?.call(ids); _databaseCallbacks?.onRowsUpdated?.call(ids);
}); },
onRowsCreated: (ids) {
_databaseCallbacks?.onRowsCreated?.call(ids);
},
);
_viewCache.addListener(callbacks); _viewCache.addListener(callbacks);
} }
@ -261,42 +268,58 @@ class DatabaseController {
void _listenOnGroupChanged() { void _listenOnGroupChanged() {
groupListener.start( groupListener.start(
onNumOfGroupsChanged: (result) { onNumOfGroupsChanged: (result) {
result.fold((changeset) { result.fold(
if (changeset.updateGroups.isNotEmpty) { (changeset) {
_groupCallbacks?.onUpdateGroup?.call(changeset.updateGroups); if (changeset.updateGroups.isNotEmpty) {
} _groupCallbacks?.onUpdateGroup?.call(changeset.updateGroups);
}
if (changeset.deletedGroups.isNotEmpty) { if (changeset.deletedGroups.isNotEmpty) {
_groupCallbacks?.onDeleteGroup?.call(changeset.deletedGroups); _groupCallbacks?.onDeleteGroup?.call(changeset.deletedGroups);
} }
for (final insertedGroup in changeset.insertedGroups) { for (final insertedGroup in changeset.insertedGroups) {
_groupCallbacks?.onInsertGroup?.call(insertedGroup); _groupCallbacks?.onInsertGroup?.call(insertedGroup);
} }
}, (r) => Log.error(r)); },
(r) => Log.error(r),
);
}, },
onGroupByNewField: (result) { onGroupByNewField: (result) {
result.fold((groups) { result.fold(
_groupCallbacks?.onGroupByField?.call(groups); (groups) {
}, (r) => Log.error(r)); _groupCallbacks?.onGroupByField?.call(groups);
},
(r) => Log.error(r),
);
}, },
); );
} }
void _listenOnLayoutChanged() { void _listenOnLayoutChanged() {
layoutListener.start(onLayoutChanged: (result) { layoutListener.start(
result.fold((l) { onLayoutChanged: (result) {
_layoutCallbacks?.onLayoutChanged(l); result.fold(
}, (r) => Log.error(r)); (l) {
}); _layoutCallbacks?.onLayoutChanged(l);
},
(r) => Log.error(r),
);
},
);
} }
void _listenOnCalendarLayoutChanged() { void _listenOnCalendarLayoutChanged() {
calendarLayoutListener.start(onCalendarLayoutChanged: (result) { calendarLayoutListener.start(
result.fold((l) { onCalendarLayoutChanged: (result) {
_calendarLayoutCallbacks?.onCalendarLayoutChanged(l); result.fold(
}, (r) => Log.error(r)); (l) {
}); _calendarLayoutCallbacks?.onCalendarLayoutChanged(l);
},
(r) => Log.error(r),
);
},
);
} }
} }

@ -73,8 +73,9 @@ class DatabaseViewBackendService {
return DatabaseEventMoveGroup(payload).send(); return DatabaseEventMoveGroup(payload).send();
} }
Future<Either<List<FieldPB>, FlowyError>> getFields( Future<Either<List<FieldPB>, FlowyError>> getFields({
{List<FieldIdPB>? fieldIds}) { List<FieldIdPB>? fieldIds,
}) {
var payload = GetFieldPayloadPB.create()..viewId = viewId; var payload = GetFieldPayloadPB.create()..viewId = viewId;
if (fieldIds != null) { if (fieldIds != null) {
@ -86,15 +87,17 @@ class DatabaseViewBackendService {
} }
Future<Either<LayoutSettingPB, FlowyError>> getLayoutSetting( Future<Either<LayoutSettingPB, FlowyError>> getLayoutSetting(
LayoutTypePB layoutType) { LayoutTypePB layoutType,
) {
final payload = DatabaseLayoutIdPB.create() final payload = DatabaseLayoutIdPB.create()
..viewId = viewId ..viewId = viewId
..layout = layoutType; ..layout = layoutType;
return DatabaseEventGetLayoutSetting(payload).send(); return DatabaseEventGetLayoutSetting(payload).send();
} }
Future<Either<Unit, FlowyError>> updateLayoutSetting( Future<Either<Unit, FlowyError>> updateLayoutSetting({
{CalendarLayoutSettingsPB? calendarLayoutSetting}) { CalendarLayoutSettingsPB? calendarLayoutSetting,
}) {
final layoutSetting = LayoutSettingPB.create(); final layoutSetting = LayoutSettingPB.create();
if (calendarLayoutSetting != null) { if (calendarLayoutSetting != null) {
layoutSetting.calendar = calendarLayoutSetting; layoutSetting.calendar = calendarLayoutSetting;

@ -17,7 +17,9 @@ class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
required FieldCellContext cellContext, required FieldCellContext cellContext,
}) : _fieldListener = SingleFieldListener(fieldId: cellContext.field.id), }) : _fieldListener = SingleFieldListener(fieldId: cellContext.field.id),
_fieldBackendSvc = FieldBackendService( _fieldBackendSvc = FieldBackendService(
viewId: cellContext.viewId, fieldId: cellContext.field.id), viewId: cellContext.viewId,
fieldId: cellContext.field.id,
),
super(FieldCellState.initial(cellContext)) { super(FieldCellState.initial(cellContext)) {
on<FieldCellEvent>( on<FieldCellEvent>(
(event, emit) async { (event, emit) async {
@ -49,15 +51,17 @@ class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
} }
void _startListening() { void _startListening() {
_fieldListener.start(onFieldChanged: (result) { _fieldListener.start(
if (isClosed) { onFieldChanged: (result) {
return; if (isClosed) {
} return;
result.fold( }
(field) => add(FieldCellEvent.didReceiveFieldUpdate(field)), result.fold(
(err) => Log.error(err), (field) => add(FieldCellEvent.didReceiveFieldUpdate(field)),
); (err) => Log.error(err),
}); );
},
);
} }
} }

@ -255,24 +255,26 @@ class FieldController {
} }
} }
_filtersListener.start(onFilterChanged: (result) { _filtersListener.start(
result.fold( onFilterChanged: (result) {
(FilterChangesetNotificationPB changeset) { result.fold(
final List<FilterInfo> filters = filterInfos; (FilterChangesetNotificationPB changeset) {
// Deletes the filters final List<FilterInfo> filters = filterInfos;
deleteFilterFromChangeset(filters, changeset); // Deletes the filters
deleteFilterFromChangeset(filters, changeset);
// Inserts the new filter if it's not exist // Inserts the new filter if it's not exist
insertFilterFromChangeset(filters, changeset); insertFilterFromChangeset(filters, changeset);
updateFilterFromChangeset(filters, changeset); updateFilterFromChangeset(filters, changeset);
_updateFieldInfos(); _updateFieldInfos();
_filterNotifier?.filters = filters; _filterNotifier?.filters = filters;
}, },
(err) => Log.error(err), (err) => Log.error(err),
); );
}); },
);
} }
void _listenOnSortChanged() { void _listenOnSortChanged() {
@ -347,48 +349,54 @@ class FieldController {
} }
} }
_sortsListener.start(onSortChanged: (result) { _sortsListener.start(
result.fold( onSortChanged: (result) {
(SortChangesetNotificationPB changeset) { result.fold(
final List<SortInfo> newSortInfos = sortInfos; (SortChangesetNotificationPB changeset) {
deleteSortFromChangeset(newSortInfos, changeset); final List<SortInfo> newSortInfos = sortInfos;
insertSortFromChangeset(newSortInfos, changeset); deleteSortFromChangeset(newSortInfos, changeset);
updateSortFromChangeset(newSortInfos, changeset); insertSortFromChangeset(newSortInfos, changeset);
updateSortFromChangeset(newSortInfos, changeset);
_updateFieldInfos(); _updateFieldInfos();
_sortNotifier?.sorts = newSortInfos; _sortNotifier?.sorts = newSortInfos;
}, },
(err) => Log.error(err), (err) => Log.error(err),
); );
}); },
);
} }
void _listenOnSettingChanges() { void _listenOnSettingChanges() {
//Listen on setting changes //Listen on setting changes
_settingListener.start(onSettingUpdated: (result) { _settingListener.start(
result.fold( onSettingUpdated: (result) {
(setting) => _updateSetting(setting), result.fold(
(r) => Log.error(r), (setting) => _updateSetting(setting),
); (r) => Log.error(r),
}); );
},
);
} }
void _listenOnFieldChanges() { void _listenOnFieldChanges() {
//Listen on field's changes //Listen on field's changes
_fieldListener.start(onFieldsChanged: (result) { _fieldListener.start(
result.fold( onFieldsChanged: (result) {
(changeset) { result.fold(
_deleteFields(changeset.deletedFields); (changeset) {
_insertFields(changeset.insertedFields); _deleteFields(changeset.deletedFields);
_insertFields(changeset.insertedFields);
final updatedFields = _updateFields(changeset.updatedFields); final updatedFields = _updateFields(changeset.updatedFields);
for (final listener in _updatedFieldCallbacks.values) { for (final listener in _updatedFieldCallbacks.values) {
listener(updatedFields); listener(updatedFields);
} }
}, },
(err) => Log.error(err), (err) => Log.error(err),
); );
}); },
);
} }
void _updateSetting(DatabaseViewSettingPB setting) { void _updateSetting(DatabaseViewSettingPB setting) {

@ -36,11 +36,13 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
} }
}, },
didReceiveFieldChanged: (FieldPB field) { didReceiveFieldChanged: (FieldPB field) {
emit(state.copyWith( emit(
field: Some(field), state.copyWith(
name: field.name, field: Some(field),
canDelete: field.isPrimary, name: field.name,
)); canDelete: field.isPrimary,
),
);
}, },
deleteField: () { deleteField: () {
state.field.fold( state.field.fold(

@ -17,8 +17,9 @@ class SingleFieldListener {
SingleFieldListener({required this.fieldId}); SingleFieldListener({required this.fieldId});
void start( void start({
{required void Function(UpdateFieldNotifiedValue) onFieldChanged}) { required void Function(UpdateFieldNotifiedValue) onFieldChanged,
}) {
_updateFieldNotifier?.addPublishListener(onFieldChanged); _updateFieldNotifier?.addPublishListener(onFieldChanged);
_listener = DatabaseNotificationListener( _listener = DatabaseNotificationListener(
objectId: fieldId, objectId: fieldId,
@ -60,8 +61,9 @@ class FieldsListener {
DatabaseNotificationListener? _listener; DatabaseNotificationListener? _listener;
FieldsListener({required this.viewId}); FieldsListener({required this.viewId});
void start( void start({
{required void Function(UpdateFieldsNotifiedValue) onFieldsChanged}) { required void Function(UpdateFieldsNotifiedValue) onFieldsChanged,
}) {
updateFieldsNotifier?.addPublishListener(onFieldsChanged); updateFieldsNotifier?.addPublishListener(onFieldsChanged);
_listener = DatabaseNotificationListener( _listener = DatabaseNotificationListener(
objectId: viewId, objectId: viewId,

@ -15,16 +15,25 @@ class DateTypeOptionBloc
(event, emit) async { (event, emit) async {
event.map( event.map(
didSelectDateFormat: (_DidSelectDateFormat value) { didSelectDateFormat: (_DidSelectDateFormat value) {
emit(state.copyWith( emit(
typeOption: _updateTypeOption(dateFormat: value.format))); state.copyWith(
typeOption: _updateTypeOption(dateFormat: value.format),
),
);
}, },
didSelectTimeFormat: (_DidSelectTimeFormat value) { didSelectTimeFormat: (_DidSelectTimeFormat value) {
emit(state.copyWith( emit(
typeOption: _updateTypeOption(timeFormat: value.format))); state.copyWith(
typeOption: _updateTypeOption(timeFormat: value.format),
),
);
}, },
includeTime: (_IncludeTime value) { includeTime: (_IncludeTime value) {
emit(state.copyWith( emit(
typeOption: _updateTypeOption(includeTime: value.includeTime))); state.copyWith(
typeOption: _updateTypeOption(includeTime: value.includeTime),
),
);
}, },
); );
}, },

@ -7,16 +7,20 @@ class NumberFormatBloc extends Bloc<NumberFormatEvent, NumberFormatState> {
NumberFormatBloc() : super(NumberFormatState.initial()) { NumberFormatBloc() : super(NumberFormatState.initial()) {
on<NumberFormatEvent>( on<NumberFormatEvent>(
(event, emit) async { (event, emit) async {
event.map(setFilter: (_SetFilter value) { event.map(
final List<NumberFormat> formats = List.from(NumberFormat.values); setFilter: (_SetFilter value) {
if (value.filter.isNotEmpty) { final List<NumberFormat> formats = List.from(NumberFormat.values);
formats.retainWhere((element) => element if (value.filter.isNotEmpty) {
.title() formats.retainWhere(
.toLowerCase() (element) => element
.contains(value.filter.toLowerCase())); .title()
} .toLowerCase()
emit(state.copyWith(formats: formats, filter: value.filter)); .contains(value.filter.toLowerCase()),
}); );
}
emit(state.copyWith(formats: formats, filter: value.filter));
},
);
}, },
); );
} }

@ -59,9 +59,11 @@ class SelectOptionTypeOptionEvent with _$SelectOptionTypeOptionEvent {
const factory SelectOptionTypeOptionEvent.endAddingOption() = const factory SelectOptionTypeOptionEvent.endAddingOption() =
_EndAddingOption; _EndAddingOption;
const factory SelectOptionTypeOptionEvent.updateOption( const factory SelectOptionTypeOptionEvent.updateOption(
SelectOptionPB option) = _UpdateOption; SelectOptionPB option,
) = _UpdateOption;
const factory SelectOptionTypeOptionEvent.deleteOption( const factory SelectOptionTypeOptionEvent.deleteOption(
SelectOptionPB option) = _DeleteOption; SelectOptionPB option,
) = _DeleteOption;
} }
@freezed @freezed

@ -158,7 +158,9 @@ abstract class IFieldTypeOptionLoader {
Future<Either<TypeOptionPB, FlowyError>> load(); Future<Either<TypeOptionPB, FlowyError>> load();
Future<Either<Unit, FlowyError>> switchToField( Future<Either<Unit, FlowyError>> switchToField(
String fieldId, FieldType fieldType) { String fieldId,
FieldType fieldType,
) {
final payload = UpdateFieldTypePayloadPB.create() final payload = UpdateFieldTypePayloadPB.create()
..viewId = viewId ..viewId = viewId
..fieldId = fieldId ..fieldId = fieldId

@ -107,7 +107,8 @@ class FilterListener {
case DatabaseNotification.DidUpdateFilter: case DatabaseNotification.DidUpdateFilter:
result.fold( result.fold(
(payload) => handleChangeset( (payload) => handleChangeset(
FilterChangesetNotificationPB.fromBuffer(payload)), FilterChangesetNotificationPB.fromBuffer(payload),
),
(error) {}, (error) {},
); );
break; break;

@ -97,7 +97,8 @@ class FilterBackendService {
filter.end = $fixnum.Int64(end); filter.end = $fixnum.Int64(end);
} else { } else {
throw Exception( throw Exception(
"Start and end should not be null if the timestamp is null"); "Start and end should not be null if the timestamp is null",
);
} }
} }

@ -15,8 +15,9 @@ class DatabaseCalendarLayoutListener {
DatabaseNotificationListener? _listener; DatabaseNotificationListener? _listener;
DatabaseCalendarLayoutListener(this.viewId); DatabaseCalendarLayoutListener(this.viewId);
void start( void start({
{required void Function(NewLayoutFieldValue) onCalendarLayoutChanged}) { required void Function(NewLayoutFieldValue) onCalendarLayoutChanged,
}) {
_newLayoutFieldNotifier?.addPublishListener(onCalendarLayoutChanged); _newLayoutFieldNotifier?.addPublishListener(onCalendarLayoutChanged);
_listener = DatabaseNotificationListener( _listener = DatabaseNotificationListener(
objectId: viewId, objectId: viewId,

@ -102,11 +102,16 @@ class RowCache {
final rowInfo = _rowList.get(reorderRow.rowId); final rowInfo = _rowList.get(reorderRow.rowId);
if (rowInfo != null) { if (rowInfo != null) {
_rowList.moveRow( _rowList.moveRow(
reorderRow.rowId, reorderRow.oldIndex, reorderRow.newIndex); reorderRow.rowId,
_rowChangeReasonNotifier.receive(RowsChangedReason.reorderSingleRow( reorderRow.oldIndex,
reorderRow, reorderRow.newIndex,
rowInfo, );
)); _rowChangeReasonNotifier.receive(
RowsChangedReason.reorderSingleRow(
reorderRow,
rowInfo,
),
);
} }
} }
@ -325,7 +330,9 @@ class RowsChangedReason with _$RowsChangedReason {
const factory RowsChangedReason.initial() = InitialListState; const factory RowsChangedReason.initial() = InitialListState;
const factory RowsChangedReason.reorderRows() = _ReorderRows; const factory RowsChangedReason.reorderRows() = _ReorderRows;
const factory RowsChangedReason.reorderSingleRow( const factory RowsChangedReason.reorderSingleRow(
ReorderSingleRowPB reorderRow, RowInfo rowInfo) = _ReorderSingleRow; ReorderSingleRowPB reorderRow,
RowInfo rowInfo,
) = _ReorderSingleRow;
} }
class InsertedIndex { class InsertedIndex {

@ -23,10 +23,12 @@ class RowController {
} }
void addListener({OnRowChanged? onRowChanged}) { void addListener({OnRowChanged? onRowChanged}) {
_onRowChangedListeners.add(_rowCache.addListener( _onRowChangedListeners.add(
rowId: rowId, _rowCache.addListener(
onCellUpdated: onRowChanged, rowId: rowId,
)); onCellUpdated: onRowChanged,
),
);
} }
void dispose() { void dispose() {

@ -85,10 +85,12 @@ class RowList {
insert(index, builder(insertRow.row)); insert(index, builder(insertRow.row));
if (!isContains) { if (!isContains) {
insertIndexs.add(InsertedIndex( insertIndexs.add(
index: index, InsertedIndex(
rowId: insertRow.row.id, index: index,
)); rowId: insertRow.row.id,
),
);
} }
} }
return insertIndexs; return insertIndexs;

@ -67,7 +67,8 @@ class DatabaseGroupEvent with _$DatabaseGroupEvent {
FieldType fieldType, FieldType fieldType,
) = _DatabaseGroupEvent; ) = _DatabaseGroupEvent;
const factory DatabaseGroupEvent.didReceiveFieldUpdate( const factory DatabaseGroupEvent.didReceiveFieldUpdate(
List<FieldInfo> fields) = _DidReceiveFieldUpdate; List<FieldInfo> fields,
) = _DidReceiveFieldUpdate;
} }
@freezed @freezed
@ -78,7 +79,9 @@ class DatabaseGroupState with _$DatabaseGroupState {
}) = _DatabaseGroupState; }) = _DatabaseGroupState;
factory DatabaseGroupState.initial( factory DatabaseGroupState.initial(
String viewId, List<FieldInfo> fieldContexts) => String viewId,
List<FieldInfo> fieldContexts,
) =>
DatabaseGroupState( DatabaseGroupState(
viewId: viewId, viewId: viewId,
fieldContexts: fieldContexts, fieldContexts: fieldContexts,

@ -13,11 +13,13 @@ class DatabasePropertyBloc
final FieldController _fieldController; final FieldController _fieldController;
Function(List<FieldInfo>)? _onFieldsFn; Function(List<FieldInfo>)? _onFieldsFn;
DatabasePropertyBloc( DatabasePropertyBloc({
{required String viewId, required FieldController fieldController}) required String viewId,
: _fieldController = fieldController, required FieldController fieldController,
}) : _fieldController = fieldController,
super( super(
DatabasePropertyState.initial(viewId, fieldController.fieldInfos)) { DatabasePropertyState.initial(viewId, fieldController.fieldInfos),
) {
on<DatabasePropertyEvent>( on<DatabasePropertyEvent>(
(event, emit) async { (event, emit) async {
await event.map( await event.map(
@ -68,9 +70,12 @@ class DatabasePropertyBloc
class DatabasePropertyEvent with _$DatabasePropertyEvent { class DatabasePropertyEvent with _$DatabasePropertyEvent {
const factory DatabasePropertyEvent.initial() = _Initial; const factory DatabasePropertyEvent.initial() = _Initial;
const factory DatabasePropertyEvent.setFieldVisibility( const factory DatabasePropertyEvent.setFieldVisibility(
String fieldId, bool visibility) = _SetFieldVisibility; String fieldId,
bool visibility,
) = _SetFieldVisibility;
const factory DatabasePropertyEvent.didReceiveFieldUpdate( const factory DatabasePropertyEvent.didReceiveFieldUpdate(
List<FieldInfo> fields) = _DidReceiveFieldUpdate; List<FieldInfo> fields,
) = _DidReceiveFieldUpdate;
const factory DatabasePropertyEvent.moveField(int fromIndex, int toIndex) = const factory DatabasePropertyEvent.moveField(int fromIndex, int toIndex) =
_MoveField; _MoveField;
} }

@ -11,9 +11,11 @@ class DatabaseSettingBloc
: super(DatabaseSettingState.initial()) { : super(DatabaseSettingState.initial()) {
on<DatabaseSettingEvent>( on<DatabaseSettingEvent>(
(event, emit) async { (event, emit) async {
event.map(performAction: (_PerformAction value) { event.map(
emit(state.copyWith(selectedAction: Some(value.action))); performAction: (_PerformAction value) {
}); emit(state.copyWith(selectedAction: Some(value.action)));
},
);
}, },
); );
} }
@ -22,7 +24,8 @@ class DatabaseSettingBloc
@freezed @freezed
class DatabaseSettingEvent with _$DatabaseSettingEvent { class DatabaseSettingEvent with _$DatabaseSettingEvent {
const factory DatabaseSettingEvent.performAction( const factory DatabaseSettingEvent.performAction(
DatabaseSettingAction action) = _PerformAction; DatabaseSettingAction action,
) = _PerformAction;
} }
@freezed @freezed

@ -28,12 +28,14 @@ class SettingController {
}); });
// Listen on the setting changes // Listen on the setting changes
_listener.start(onSettingUpdated: (result) { _listener.start(
result.fold( onSettingUpdated: (result) {
(newSetting) => updateSetting(newSetting), result.fold(
(err) => _onError?.call(err), (newSetting) => updateSetting(newSetting),
); (err) => _onError?.call(err),
}); );
},
);
} }
void startListening({ void startListening({

@ -69,9 +69,11 @@ class DatabaseViewCache {
} }
if (changeset.insertedRows.isNotEmpty) { if (changeset.insertedRows.isNotEmpty) {
_callbacks?.onRowsCreated?.call(changeset.insertedRows _callbacks?.onRowsCreated?.call(
.map((insertedRow) => insertedRow.row.id) changeset.insertedRows
.toList()); .map((insertedRow) => insertedRow.row.id)
.toList(),
);
} }
}, },
(err) => Log.error(err), (err) => Log.error(err),

@ -105,23 +105,31 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
); );
}, },
didCreateRow: (group, row, int? index) { didCreateRow: (group, row, int? index) {
emit(state.copyWith( emit(
editingRow: Some(BoardEditingRow( state.copyWith(
group: group, editingRow: Some(
row: row, BoardEditingRow(
index: index, group: group,
)), row: row,
)); index: index,
),
),
),
);
_groupItemStartEditing(group, row, true); _groupItemStartEditing(group, row, true);
}, },
startEditingRow: (group, row) { startEditingRow: (group, row) {
emit(state.copyWith( emit(
editingRow: Some(BoardEditingRow( state.copyWith(
group: group, editingRow: Some(
row: row, BoardEditingRow(
index: null, group: group,
)), row: row,
)); index: null,
),
),
),
);
_groupItemStartEditing(group, row, true); _groupItemStartEditing(group, row, true);
}, },
endEditingRow: (rowId) { endEditingRow: (rowId) {
@ -175,10 +183,12 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
groupControllers.clear(); groupControllers.clear();
boardController.clear(); boardController.clear();
boardController.addGroups(groups boardController.addGroups(
.where((group) => fieldController.getField(group.fieldId) != null) groups
.map((group) => initializeGroupData(group)) .where((group) => fieldController.getField(group.fieldId) != null)
.toList()); .map((group) => initializeGroupData(group))
.toList(),
);
for (final group in groups) { for (final group in groups) {
final controller = initializeGroupController(group); final controller = initializeGroupController(group);
@ -334,7 +344,8 @@ class BoardState with _$BoardState {
class GridLoadingState with _$GridLoadingState { class GridLoadingState with _$GridLoadingState {
const factory GridLoadingState.loading() = _Loading; const factory GridLoadingState.loading() = _Loading;
const factory GridLoadingState.finish( const factory GridLoadingState.finish(
Either<Unit, FlowyError> successOrFail) = _Finish; Either<Unit, FlowyError> successOrFail,
) = _Finish;
} }
class GridFieldEquatable extends Equatable { class GridFieldEquatable extends Equatable {

@ -41,44 +41,46 @@ class GroupController {
} }
void startListening() { void startListening() {
_listener.start(onGroupChanged: (result) { _listener.start(
result.fold( onGroupChanged: (result) {
(GroupRowsNotificationPB changeset) { result.fold(
for (final deletedRow in changeset.deletedRows) { (GroupRowsNotificationPB changeset) {
group.rows.removeWhere((rowPB) => rowPB.id == deletedRow); for (final deletedRow in changeset.deletedRows) {
delegate.removeRow(group, deletedRow); group.rows.removeWhere((rowPB) => rowPB.id == deletedRow);
} delegate.removeRow(group, deletedRow);
for (final insertedRow in changeset.insertedRows) {
final index = insertedRow.hasIndex() ? insertedRow.index : null;
if (insertedRow.hasIndex() &&
group.rows.length > insertedRow.index) {
group.rows.insert(insertedRow.index, insertedRow.row);
} else {
group.rows.add(insertedRow.row);
} }
if (insertedRow.isNew) { for (final insertedRow in changeset.insertedRows) {
delegate.addNewRow(group, insertedRow.row, index); final index = insertedRow.hasIndex() ? insertedRow.index : null;
} else { if (insertedRow.hasIndex() &&
delegate.insertRow(group, insertedRow.row, index); group.rows.length > insertedRow.index) {
} group.rows.insert(insertedRow.index, insertedRow.row);
} } else {
group.rows.add(insertedRow.row);
}
for (final updatedRow in changeset.updatedRows) { if (insertedRow.isNew) {
final index = group.rows.indexWhere( delegate.addNewRow(group, insertedRow.row, index);
(rowPB) => rowPB.id == updatedRow.id, } else {
); delegate.insertRow(group, insertedRow.row, index);
}
if (index != -1) {
group.rows[index] = updatedRow;
delegate.updateRow(group, updatedRow);
} }
}
}, for (final updatedRow in changeset.updatedRows) {
(err) => Log.error(err), final index = group.rows.indexWhere(
); (rowPB) => rowPB.id == updatedRow.id,
}); );
if (index != -1) {
group.rows[index] = updatedRow;
delegate.updateRow(group, updatedRow);
}
}
},
(err) => Log.error(err),
);
},
);
} }
Future<void> dispose() async { Future<void> dispose() async {

@ -10,9 +10,11 @@ class BoardSettingBloc extends Bloc<BoardSettingEvent, BoardSettingState> {
: super(BoardSettingState.initial()) { : super(BoardSettingState.initial()) {
on<BoardSettingEvent>( on<BoardSettingEvent>(
(event, emit) async { (event, emit) async {
event.when(performAction: (action) { event.when(
emit(state.copyWith(selectedAction: Some(action))); performAction: (action) {
}); emit(state.copyWith(selectedAction: Some(action)));
},
);
}, },
); );
} }

@ -67,16 +67,20 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
if (index != -1) { if (index != -1) {
allEvents[index] = eventData; allEvents[index] = eventData;
} }
emit(state.copyWith( emit(
allEvents: allEvents, state.copyWith(
updateEvent: eventData, allEvents: allEvents,
)); updateEvent: eventData,
),
);
}, },
didReceiveNewEvent: (CalendarEventData<CalendarDayEvent> event) { didReceiveNewEvent: (CalendarEventData<CalendarDayEvent> event) {
emit(state.copyWith( emit(
allEvents: [...state.allEvents, event], state.copyWith(
newEvent: event, allEvents: [...state.allEvents, event],
)); newEvent: event,
),
);
}, },
didDeleteEvents: (List<String> deletedRowIds) { didDeleteEvents: (List<String> deletedRowIds) {
var events = [...state.allEvents]; var events = [...state.allEvents];
@ -155,7 +159,8 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
} }
Future<void> _updateCalendarLayoutSetting( Future<void> _updateCalendarLayoutSetting(
CalendarLayoutSettingsPB layoutSetting) async { CalendarLayoutSettingsPB layoutSetting,
) async {
return _databaseController.updateCalenderLayoutSetting(layoutSetting); return _databaseController.updateCalenderLayoutSetting(layoutSetting);
} }
@ -198,7 +203,8 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
} }
CalendarEventData<CalendarDayEvent>? _calendarEventDataFromEventPB( CalendarEventData<CalendarDayEvent>? _calendarEventDataFromEventPB(
CalendarEventPB eventPB) { CalendarEventPB eventPB,
) {
final fieldInfo = fieldInfoByFieldId[eventPB.titleFieldId]; final fieldInfo = fieldInfoByFieldId[eventPB.titleFieldId];
if (fieldInfo != null) { if (fieldInfo != null) {
final cellId = CellIdentifier( final cellId = CellIdentifier(
@ -267,7 +273,8 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
); );
final onCalendarLayoutFieldChanged = CalendarLayoutCallbacks( final onCalendarLayoutFieldChanged = CalendarLayoutCallbacks(
onCalendarLayoutChanged: _didReceiveNewLayoutField); onCalendarLayoutChanged: _didReceiveNewLayoutField,
);
_databaseController.addListener( _databaseController.addListener(
onDatabaseChanged: onDatabaseChanged, onDatabaseChanged: onDatabaseChanged,
@ -299,7 +306,8 @@ class CalendarEvent with _$CalendarEvent {
// Called after loading the calendar layout setting from the backend // Called after loading the calendar layout setting from the backend
const factory CalendarEvent.didReceiveCalendarSettings( const factory CalendarEvent.didReceiveCalendarSettings(
CalendarLayoutSettingsPB settings) = _ReceiveCalendarSettings; CalendarLayoutSettingsPB settings,
) = _ReceiveCalendarSettings;
// Called after loading all the current evnets // Called after loading all the current evnets
const factory CalendarEvent.didLoadAllEvents(Events events) = const factory CalendarEvent.didLoadAllEvents(Events events) =
@ -307,11 +315,13 @@ class CalendarEvent with _$CalendarEvent {
// Called when specific event was updated // Called when specific event was updated
const factory CalendarEvent.didUpdateEvent( const factory CalendarEvent.didUpdateEvent(
CalendarEventData<CalendarDayEvent> event) = _DidUpdateEvent; CalendarEventData<CalendarDayEvent> event,
) = _DidUpdateEvent;
// Called after creating a new event // Called after creating a new event
const factory CalendarEvent.didReceiveNewEvent( const factory CalendarEvent.didReceiveNewEvent(
CalendarEventData<CalendarDayEvent> event) = _DidReceiveNewEvent; CalendarEventData<CalendarDayEvent> event,
) = _DidReceiveNewEvent;
// Called when deleting events // Called when deleting events
const factory CalendarEvent.didDeleteEvents(List<String> rowIds) = const factory CalendarEvent.didDeleteEvents(List<String> rowIds) =
@ -323,13 +333,15 @@ class CalendarEvent with _$CalendarEvent {
// Called when updating the calendar's layout settings // Called when updating the calendar's layout settings
const factory CalendarEvent.updateCalendarLayoutSetting( const factory CalendarEvent.updateCalendarLayoutSetting(
CalendarLayoutSettingsPB layoutSetting) = _UpdateCalendarLayoutSetting; CalendarLayoutSettingsPB layoutSetting,
) = _UpdateCalendarLayoutSetting;
const factory CalendarEvent.didReceiveDatabaseUpdate(DatabasePB database) = const factory CalendarEvent.didReceiveDatabaseUpdate(DatabasePB database) =
_ReceiveDatabaseUpdate; _ReceiveDatabaseUpdate;
const factory CalendarEvent.didReceiveNewLayoutField( const factory CalendarEvent.didReceiveNewLayoutField(
CalendarLayoutSettingsPB layoutSettings) = _DidReceiveNewLayoutField; CalendarLayoutSettingsPB layoutSettings,
) = _DidReceiveNewLayoutField;
} }
@freezed @freezed
@ -361,7 +373,8 @@ class CalendarState with _$CalendarState {
class DatabaseLoadingState with _$DatabaseLoadingState { class DatabaseLoadingState with _$DatabaseLoadingState {
const factory DatabaseLoadingState.loading() = _Loading; const factory DatabaseLoadingState.loading() = _Loading;
const factory DatabaseLoadingState.finish( const factory DatabaseLoadingState.finish(
Either<Unit, FlowyError> successOrFail) = _Finish; Either<Unit, FlowyError> successOrFail,
) = _Finish;
} }
class CalendarEditingRow { class CalendarEditingRow {

@ -22,7 +22,6 @@ class CalendarSettingBloc
); );
}); });
} }
} }
@freezed @freezed
@ -33,7 +32,8 @@ class CalendarSettingState with _$CalendarSettingState {
}) = _CalendarSettingState; }) = _CalendarSettingState;
factory CalendarSettingState.initial( factory CalendarSettingState.initial(
CalendarLayoutSettingsPB? layoutSettings) => CalendarLayoutSettingsPB? layoutSettings,
) =>
CalendarSettingState( CalendarSettingState(
selectedAction: none(), selectedAction: none(),
layoutSetting: layoutSettings == null ? none() : Some(layoutSettings), layoutSetting: layoutSettings == null ? none() : Some(layoutSettings),
@ -43,9 +43,11 @@ class CalendarSettingState with _$CalendarSettingState {
@freezed @freezed
class CalendarSettingEvent with _$CalendarSettingEvent { class CalendarSettingEvent with _$CalendarSettingEvent {
const factory CalendarSettingEvent.performAction( const factory CalendarSettingEvent.performAction(
CalendarSettingAction action) = _PerformAction; CalendarSettingAction action,
) = _PerformAction;
const factory CalendarSettingEvent.updateLayoutSetting( const factory CalendarSettingEvent.updateLayoutSetting(
CalendarLayoutSettingsPB setting) = _UpdateLayoutSetting; CalendarLayoutSettingsPB setting,
) = _UpdateLayoutSetting;
} }
enum CalendarSettingAction { enum CalendarSettingAction {

@ -63,29 +63,30 @@ class CalendarDayCard extends StatelessWidget {
}).toList(); }).toList();
final child = Padding( final child = Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
_Header( _Header(
date: date, date: date,
isInMonth: isInMonth, isInMonth: isInMonth,
isToday: isToday, isToday: isToday,
onCreate: () => onCreateEvent(date), onCreate: () => onCreateEvent(date),
),
VSpace(GridSize.typeOptionSeparatorHeight),
Flexible(
child: ListView.separated(
itemBuilder: (BuildContext context, int index) {
return children[index];
},
itemCount: children.length,
separatorBuilder: (BuildContext context, int index) =>
VSpace(GridSize.typeOptionSeparatorHeight),
), ),
VSpace(GridSize.typeOptionSeparatorHeight), ),
Flexible( ],
child: ListView.separated( ),
itemBuilder: (BuildContext context, int index) { );
return children[index];
},
itemCount: children.length,
separatorBuilder: (BuildContext context, int index) =>
VSpace(GridSize.typeOptionSeparatorHeight),
),
),
],
));
return Container( return Container(
color: backgroundColor, color: backgroundColor,

@ -73,9 +73,11 @@ class _CalendarPageState extends State<CalendarPage> {
listenWhen: (p, c) => p.updateEvent != c.updateEvent, listenWhen: (p, c) => p.updateEvent != c.updateEvent,
listener: (context, state) { listener: (context, state) {
if (state.updateEvent != null) { if (state.updateEvent != null) {
_eventController.removeWhere((element) => _eventController.removeWhere(
state.updateEvent!.event!.eventId == (element) =>
element.event!.eventId); state.updateEvent!.event!.eventId ==
element.event!.eventId,
);
_eventController.add(state.updateEvent!); _eventController.add(state.updateEvent!);
} }
}, },

@ -96,16 +96,22 @@ class _CalendarLayoutSettingState extends State<CalendarLayoutSetting> {
fieldId: settings.layoutFieldId, fieldId: settings.layoutFieldId,
popoverMutex: popoverMutex, popoverMutex: popoverMutex,
onUpdated: (fieldId) { onUpdated: (fieldId) {
_updateLayoutSettings(context, _updateLayoutSettings(
onUpdated: widget.onUpdated, layoutFieldId: fieldId); context,
onUpdated: widget.onUpdated,
layoutFieldId: fieldId,
);
}, },
); );
default: default:
return ShowWeekends( return ShowWeekends(
showWeekends: settings.showWeekends, showWeekends: settings.showWeekends,
onUpdated: (showWeekends) { onUpdated: (showWeekends) {
_updateLayoutSettings(context, _updateLayoutSettings(
onUpdated: widget.onUpdated, showWeekends: showWeekends); context,
onUpdated: widget.onUpdated,
showWeekends: showWeekends,
);
}, },
); );
} }
@ -129,7 +135,8 @@ class _CalendarLayoutSettingState extends State<CalendarLayoutSetting> {
} }
List<CalendarLayoutSettingAction> _availableCalendarSettings( List<CalendarLayoutSettingAction> _availableCalendarSettings(
CalendarLayoutSettingsPB layoutSettings) { CalendarLayoutSettingsPB layoutSettings,
) {
List<CalendarLayoutSettingAction> settings = [ List<CalendarLayoutSettingAction> settings = [
CalendarLayoutSettingAction.layoutField, CalendarLayoutSettingAction.layoutField,
// CalendarLayoutSettingAction.layoutType, // CalendarLayoutSettingAction.layoutType,
@ -220,8 +227,9 @@ class LayoutDateField extends StatelessWidget {
popupBuilder: (context) { popupBuilder: (context) {
return BlocProvider( return BlocProvider(
create: (context) => getIt<DatabasePropertyBloc>( create: (context) => getIt<DatabasePropertyBloc>(
param1: viewId, param2: fieldController) param1: viewId,
..add(const DatabasePropertyEvent.initial()), param2: fieldController,
)..add(const DatabasePropertyEvent.initial()),
child: BlocBuilder<DatabasePropertyBloc, DatabasePropertyState>( child: BlocBuilder<DatabasePropertyBloc, DatabasePropertyState>(
builder: (context, state) { builder: (context, state) {
final items = state.fieldContexts final items = state.fieldContexts
@ -264,7 +272,8 @@ class LayoutDateField extends StatelessWidget {
child: FlowyButton( child: FlowyButton(
margin: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 10.0), margin: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 10.0),
text: FlowyText.medium( text: FlowyText.medium(
LocaleKeys.calendar_settings_layoutDateField.tr()), LocaleKeys.calendar_settings_layoutDateField.tr(),
),
), ),
), ),
); );
@ -368,7 +377,8 @@ class FirstDayOfWeek extends StatelessWidget {
child: FlowyButton( child: FlowyButton(
margin: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 10.0), margin: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 10.0),
text: FlowyText.medium( text: FlowyText.medium(
LocaleKeys.calendar_settings_firstDayOfWeek.tr()), LocaleKeys.calendar_settings_firstDayOfWeek.tr(),
),
), ),
), ),
); );

@ -45,10 +45,12 @@ class CheckboxFilterEditorBloc
didReceiveFilter: (FilterPB filter) { didReceiveFilter: (FilterPB filter) {
final filterInfo = state.filterInfo.copyWith(filter: filter); final filterInfo = state.filterInfo.copyWith(filter: filter);
final checkboxFilter = filterInfo.checkboxFilter()!; final checkboxFilter = filterInfo.checkboxFilter()!;
emit(state.copyWith( emit(
filterInfo: filterInfo, state.copyWith(
filter: checkboxFilter, filterInfo: filterInfo,
)); filter: checkboxFilter,
),
);
}, },
); );
}, },
@ -79,7 +81,8 @@ class CheckboxFilterEditorEvent with _$CheckboxFilterEditorEvent {
const factory CheckboxFilterEditorEvent.didReceiveFilter(FilterPB filter) = const factory CheckboxFilterEditorEvent.didReceiveFilter(FilterPB filter) =
_DidReceiveFilter; _DidReceiveFilter;
const factory CheckboxFilterEditorEvent.updateCondition( const factory CheckboxFilterEditorEvent.updateCondition(
CheckboxFilterConditionPB condition) = _UpdateCondition; CheckboxFilterConditionPB condition,
) = _UpdateCondition;
const factory CheckboxFilterEditorEvent.delete() = _Delete; const factory CheckboxFilterEditorEvent.delete() = _Delete;
} }

@ -46,10 +46,12 @@ class ChecklistFilterEditorBloc
didReceiveFilter: (FilterPB filter) { didReceiveFilter: (FilterPB filter) {
final filterInfo = state.filterInfo.copyWith(filter: filter); final filterInfo = state.filterInfo.copyWith(filter: filter);
final checklistFilter = filterInfo.checklistFilter()!; final checklistFilter = filterInfo.checklistFilter()!;
emit(state.copyWith( emit(
filterInfo: filterInfo, state.copyWith(
filter: checklistFilter, filterInfo: filterInfo,
)); filter: checklistFilter,
),
);
}, },
); );
}, },
@ -82,7 +84,8 @@ class ChecklistFilterEditorEvent with _$ChecklistFilterEditorEvent {
const factory ChecklistFilterEditorEvent.didReceiveFilter(FilterPB filter) = const factory ChecklistFilterEditorEvent.didReceiveFilter(FilterPB filter) =
_DidReceiveFilter; _DidReceiveFilter;
const factory ChecklistFilterEditorEvent.updateCondition( const factory ChecklistFilterEditorEvent.updateCondition(
ChecklistFilterConditionPB condition) = _UpdateCondition; ChecklistFilterConditionPB condition,
) = _UpdateCondition;
const factory ChecklistFilterEditorEvent.delete() = _Delete; const factory ChecklistFilterEditorEvent.delete() = _Delete;
} }

@ -14,11 +14,13 @@ class GridFilterMenuBloc
void Function(List<FieldInfo>)? _onFieldFn; void Function(List<FieldInfo>)? _onFieldFn;
GridFilterMenuBloc({required this.viewId, required this.fieldController}) GridFilterMenuBloc({required this.viewId, required this.fieldController})
: super(GridFilterMenuState.initial( : super(
viewId, GridFilterMenuState.initial(
fieldController.filterInfos, viewId,
fieldController.fieldInfos, fieldController.filterInfos,
)) { fieldController.fieldInfos,
),
) {
on<GridFilterMenuEvent>( on<GridFilterMenuEvent>(
(event, emit) async { (event, emit) async {
event.when( event.when(
@ -82,7 +84,8 @@ class GridFilterMenuBloc
class GridFilterMenuEvent with _$GridFilterMenuEvent { class GridFilterMenuEvent with _$GridFilterMenuEvent {
const factory GridFilterMenuEvent.initial() = _Initial; const factory GridFilterMenuEvent.initial() = _Initial;
const factory GridFilterMenuEvent.didReceiveFilters( const factory GridFilterMenuEvent.didReceiveFilters(
List<FilterInfo> filters) = _DidReceiveFilters; List<FilterInfo> filters,
) = _DidReceiveFilters;
const factory GridFilterMenuEvent.didReceiveFields(List<FieldInfo> fields) = const factory GridFilterMenuEvent.didReceiveFields(List<FieldInfo> fields) =
_DidReceiveFields; _DidReceiveFields;
const factory GridFilterMenuEvent.toggleMenu() = _SetMenuVisibility; const factory GridFilterMenuEvent.toggleMenu() = _SetMenuVisibility;

@ -61,10 +61,12 @@ class SelectOptionFilterEditorBloc
didReceiveFilter: (FilterPB filter) { didReceiveFilter: (FilterPB filter) {
final filterInfo = state.filterInfo.copyWith(filter: filter); final filterInfo = state.filterInfo.copyWith(filter: filter);
final selectOptionFilter = filterInfo.selectOptionFilter()!; final selectOptionFilter = filterInfo.selectOptionFilter()!;
emit(state.copyWith( emit(
filterInfo: filterInfo, state.copyWith(
filter: selectOptionFilter, filterInfo: filterInfo,
)); filter: selectOptionFilter,
),
);
}, },
updateFilterDescription: (String desc) { updateFilterDescription: (String desc) {
emit(state.copyWith(filterDesc: desc)); emit(state.copyWith(filterDesc: desc));
@ -112,13 +114,17 @@ class SelectOptionFilterEditorBloc
class SelectOptionFilterEditorEvent with _$SelectOptionFilterEditorEvent { class SelectOptionFilterEditorEvent with _$SelectOptionFilterEditorEvent {
const factory SelectOptionFilterEditorEvent.initial() = _Initial; const factory SelectOptionFilterEditorEvent.initial() = _Initial;
const factory SelectOptionFilterEditorEvent.didReceiveFilter( const factory SelectOptionFilterEditorEvent.didReceiveFilter(
FilterPB filter) = _DidReceiveFilter; FilterPB filter,
) = _DidReceiveFilter;
const factory SelectOptionFilterEditorEvent.updateCondition( const factory SelectOptionFilterEditorEvent.updateCondition(
SelectOptionConditionPB condition) = _UpdateCondition; SelectOptionConditionPB condition,
) = _UpdateCondition;
const factory SelectOptionFilterEditorEvent.updateContent( const factory SelectOptionFilterEditorEvent.updateContent(
List<String> optionIds) = _UpdateContent; List<String> optionIds,
) = _UpdateContent;
const factory SelectOptionFilterEditorEvent.updateFilterDescription( const factory SelectOptionFilterEditorEvent.updateFilterDescription(
String desc) = _UpdateDesc; String desc,
) = _UpdateDesc;
const factory SelectOptionFilterEditorEvent.delete() = _Delete; const factory SelectOptionFilterEditorEvent.delete() = _Delete;
} }

@ -43,15 +43,22 @@ class SelectOptionFilterListBloc<T>
didReceiveOptions: (newOptions) { didReceiveOptions: (newOptions) {
List<SelectOptionPB> options = List.from(newOptions); List<SelectOptionPB> options = List.from(newOptions);
options.retainWhere( options.retainWhere(
(element) => element.name.contains(state.predicate)); (element) => element.name.contains(state.predicate),
);
final visibleOptions = options.map((option) { final visibleOptions = options.map((option) {
return VisibleSelectOption( return VisibleSelectOption(
option, state.selectedOptionIds.contains(option.id)); option,
state.selectedOptionIds.contains(option.id),
);
}).toList(); }).toList();
emit(state.copyWith( emit(
options: options, visibleOptions: visibleOptions)); state.copyWith(
options: options,
visibleOptions: visibleOptions,
),
);
}, },
filterOption: (optionName) { filterOption: (optionName) {
_updateSelectOptions(predicate: optionName, emit: emit); _updateSelectOptions(predicate: optionName, emit: emit);
@ -71,11 +78,13 @@ class SelectOptionFilterListBloc<T>
selectedOptionIds ?? state.selectedOptionIds, selectedOptionIds ?? state.selectedOptionIds,
); );
emit(state.copyWith( emit(
predicate: predicate ?? state.predicate, state.copyWith(
visibleOptions: visibleOptions, predicate: predicate ?? state.predicate,
selectedOptionIds: selectedOptionIds ?? state.selectedOptionIds, visibleOptions: visibleOptions,
)); selectedOptionIds: selectedOptionIds ?? state.selectedOptionIds,
),
);
} }
List<VisibleSelectOption> _makeVisibleOptions( List<VisibleSelectOption> _makeVisibleOptions(
@ -105,11 +114,14 @@ class SelectOptionFilterListBloc<T>
class SelectOptionFilterListEvent with _$SelectOptionFilterListEvent { class SelectOptionFilterListEvent with _$SelectOptionFilterListEvent {
const factory SelectOptionFilterListEvent.initial() = _Initial; const factory SelectOptionFilterListEvent.initial() = _Initial;
const factory SelectOptionFilterListEvent.selectOption( const factory SelectOptionFilterListEvent.selectOption(
SelectOptionPB option) = _SelectOption; SelectOptionPB option,
) = _SelectOption;
const factory SelectOptionFilterListEvent.unselectOption( const factory SelectOptionFilterListEvent.unselectOption(
SelectOptionPB option) = _UnSelectOption; SelectOptionPB option,
) = _UnSelectOption;
const factory SelectOptionFilterListEvent.didReceiveOptions( const factory SelectOptionFilterListEvent.didReceiveOptions(
List<SelectOptionPB> options) = _DidReceiveOptions; List<SelectOptionPB> options,
) = _DidReceiveOptions;
const factory SelectOptionFilterListEvent.filterOption(String optionName) = const factory SelectOptionFilterListEvent.filterOption(String optionName) =
_SelectOptionFilter; _SelectOptionFilter;
} }

@ -54,10 +54,12 @@ class TextFilterEditorBloc
didReceiveFilter: (FilterPB filter) { didReceiveFilter: (FilterPB filter) {
final filterInfo = state.filterInfo.copyWith(filter: filter); final filterInfo = state.filterInfo.copyWith(filter: filter);
final textFilter = filterInfo.textFilter()!; final textFilter = filterInfo.textFilter()!;
emit(state.copyWith( emit(
filterInfo: filterInfo, state.copyWith(
filter: textFilter, filterInfo: filterInfo,
)); filter: textFilter,
),
);
}, },
); );
}, },
@ -88,7 +90,8 @@ class TextFilterEditorEvent with _$TextFilterEditorEvent {
const factory TextFilterEditorEvent.didReceiveFilter(FilterPB filter) = const factory TextFilterEditorEvent.didReceiveFilter(FilterPB filter) =
_DidReceiveFilter; _DidReceiveFilter;
const factory TextFilterEditorEvent.updateCondition( const factory TextFilterEditorEvent.updateCondition(
TextFilterConditionPB condition) = _UpdateCondition; TextFilterConditionPB condition,
) = _UpdateCondition;
const factory TextFilterEditorEvent.updateContent(String content) = const factory TextFilterEditorEvent.updateContent(String content) =
_UpdateContent; _UpdateContent;
const factory TextFilterEditorEvent.delete() = _Delete; const factory TextFilterEditorEvent.delete() = _Delete;

@ -8,9 +8,11 @@ class GridAccessoryMenuBloc
final String viewId; final String viewId;
GridAccessoryMenuBloc({required this.viewId}) GridAccessoryMenuBloc({required this.viewId})
: super(GridAccessoryMenuState.initial( : super(
viewId, GridAccessoryMenuState.initial(
)) { viewId,
),
) {
on<GridAccessoryMenuEvent>( on<GridAccessoryMenuEvent>(
(event, emit) async { (event, emit) async {
event.when( event.when(

@ -39,16 +39,20 @@ class GridBloc extends Bloc<GridEvent, GridState> {
emit(state.copyWith(grid: Some(grid))); emit(state.copyWith(grid: Some(grid)));
}, },
didReceiveFieldUpdate: (fields) { didReceiveFieldUpdate: (fields) {
emit(state.copyWith( emit(
fields: GridFieldEquatable(fields), state.copyWith(
)); fields: GridFieldEquatable(fields),
),
);
}, },
didReceiveRowUpdate: (newRowInfos, reason) { didReceiveRowUpdate: (newRowInfos, reason) {
emit(state.copyWith( emit(
rowInfos: newRowInfos, state.copyWith(
rowCount: newRowInfos.length, rowInfos: newRowInfos,
reason: reason, rowCount: newRowInfos.length,
)); reason: reason,
),
);
}, },
); );
}, },
@ -146,7 +150,8 @@ class GridState with _$GridState {
class GridLoadingState with _$GridLoadingState { class GridLoadingState with _$GridLoadingState {
const factory GridLoadingState.loading() = _Loading; const factory GridLoadingState.loading() = _Loading;
const factory GridLoadingState.finish( const factory GridLoadingState.finish(
Either<Unit, FlowyError> successOrFail) = _Finish; Either<Unit, FlowyError> successOrFail,
) = _Finish;
} }
class GridFieldEquatable extends Equatable { class GridFieldEquatable extends Equatable {

@ -40,7 +40,9 @@ class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
} }
Future<void> _moveField( Future<void> _moveField(
_MoveField value, Emitter<GridHeaderState> emit) async { _MoveField value,
Emitter<GridHeaderState> emit,
) async {
final fields = List<FieldInfo>.from(state.fields); final fields = List<FieldInfo>.from(state.fields);
fields.insert(value.toIndex, fields.removeAt(value.fromIndex)); fields.insert(value.toIndex, fields.removeAt(value.fromIndex));
emit(state.copyWith(fields: fields)); emit(state.copyWith(fields: fields));
@ -69,7 +71,10 @@ class GridHeaderEvent with _$GridHeaderEvent {
const factory GridHeaderEvent.didReceiveFieldUpdate(List<FieldInfo> fields) = const factory GridHeaderEvent.didReceiveFieldUpdate(List<FieldInfo> fields) =
_DidReceiveFieldUpdate; _DidReceiveFieldUpdate;
const factory GridHeaderEvent.moveField( const factory GridHeaderEvent.moveField(
FieldPB field, int fromIndex, int toIndex) = _MoveField; FieldPB field,
int fromIndex,
int toIndex,
) = _MoveField;
} }
@freezed @freezed

@ -35,11 +35,13 @@ class RowBloc extends Bloc<RowEvent, RowState> {
final cells = cellByFieldId.values final cells = cellByFieldId.values
.map((e) => GridCellEquatable(e.fieldInfo)) .map((e) => GridCellEquatable(e.fieldInfo))
.toList(); .toList();
emit(state.copyWith( emit(
cellByFieldId: cellByFieldId, state.copyWith(
cells: UnmodifiableListView(cells), cellByFieldId: cellByFieldId,
changeReason: reason, cells: UnmodifiableListView(cells),
)); changeReason: reason,
),
);
}, },
); );
}, },
@ -68,8 +70,9 @@ class RowEvent with _$RowEvent {
const factory RowEvent.initial() = _InitialRow; const factory RowEvent.initial() = _InitialRow;
const factory RowEvent.createRow() = _CreateRow; const factory RowEvent.createRow() = _CreateRow;
const factory RowEvent.didReceiveCells( const factory RowEvent.didReceiveCells(
CellByFieldId cellsByFieldId, RowsChangedReason reason) = CellByFieldId cellsByFieldId,
_DidReceiveCells; RowsChangedReason reason,
) = _DidReceiveCells;
} }
@freezed @freezed

@ -59,7 +59,8 @@ class RowDetailEvent with _$RowDetailEvent {
const factory RowDetailEvent.initial() = _Initial; const factory RowDetailEvent.initial() = _Initial;
const factory RowDetailEvent.deleteField(String fieldId) = _DeleteField; const factory RowDetailEvent.deleteField(String fieldId) = _DeleteField;
const factory RowDetailEvent.didReceiveCellDatas( const factory RowDetailEvent.didReceiveCellDatas(
List<CellIdentifier> gridCells) = _DidReceiveCellDatas; List<CellIdentifier> gridCells,
) = _DidReceiveCellDatas;
} }
@freezed @freezed

@ -82,9 +82,10 @@ class CreateSortBloc extends Bloc<CreateSortEvent, CreateSortState> {
Future<Either<Unit, FlowyError>> _createDefaultSort(FieldInfo field) async { Future<Either<Unit, FlowyError>> _createDefaultSort(FieldInfo field) async {
final result = await _sortBackendSvc.insertSort( final result = await _sortBackendSvc.insertSort(
fieldId: field.id, fieldId: field.id,
fieldType: field.fieldType, fieldType: field.fieldType,
condition: SortConditionPB.Ascending); condition: SortConditionPB.Ascending,
);
return result; return result;
} }

@ -100,7 +100,9 @@ class SortEditorEvent with _$SortEditorEvent {
const factory SortEditorEvent.didReceiveSorts(List<SortInfo> sortInfos) = const factory SortEditorEvent.didReceiveSorts(List<SortInfo> sortInfos) =
_DidReceiveSorts; _DidReceiveSorts;
const factory SortEditorEvent.setCondition( const factory SortEditorEvent.setCondition(
SortInfo sortInfo, SortConditionPB condition) = _SetCondition; SortInfo sortInfo,
SortConditionPB condition,
) = _SetCondition;
const factory SortEditorEvent.deleteSort(SortInfo sortInfo) = _DeleteSort; const factory SortEditorEvent.deleteSort(SortInfo sortInfo) = _DeleteSort;
const factory SortEditorEvent.deleteAllSorts() = _DeleteAllSorts; const factory SortEditorEvent.deleteAllSorts() = _DeleteAllSorts;
} }

@ -14,11 +14,13 @@ class SortMenuBloc extends Bloc<SortMenuEvent, SortMenuState> {
void Function(List<FieldInfo>)? _onFieldFn; void Function(List<FieldInfo>)? _onFieldFn;
SortMenuBloc({required this.viewId, required this.fieldController}) SortMenuBloc({required this.viewId, required this.fieldController})
: super(SortMenuState.initial( : super(
viewId, SortMenuState.initial(
fieldController.sortInfos, viewId,
fieldController.fieldInfos, fieldController.sortInfos,
)) { fieldController.fieldInfos,
),
) {
on<SortMenuEvent>( on<SortMenuEvent>(
(event, emit) async { (event, emit) async {
event.when( event.when(

@ -117,7 +117,8 @@ class FlowyGrid extends StatefulWidget {
class _FlowyGridState extends State<FlowyGrid> { class _FlowyGridState extends State<FlowyGrid> {
final _scrollController = GridScrollController( final _scrollController = GridScrollController(
scrollGroupController: LinkedScrollControllerGroup()); scrollGroupController: LinkedScrollControllerGroup(),
);
late ScrollController headerScrollController; late ScrollController headerScrollController;
@override @override
@ -319,13 +320,14 @@ class _GridRowsState extends State<_GridRows> {
); );
FlowyOverlay.show( FlowyOverlay.show(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return RowDetailPage( return RowDetailPage(
cellBuilder: cellBuilder, cellBuilder: cellBuilder,
dataController: dataController, dataController: dataController,
); );
}); },
);
} }
} }

@ -8,9 +8,9 @@ class GridScrollController {
final List<ScrollController> _linkHorizontalControllers = []; final List<ScrollController> _linkHorizontalControllers = [];
GridScrollController( GridScrollController({
{required LinkedScrollControllerGroup scrollGroupController}) required LinkedScrollControllerGroup scrollGroupController,
: _scrollGroupController = scrollGroupController, }) : _scrollGroupController = scrollGroupController,
verticalController = ScrollController(), verticalController = ScrollController(),
horizontalController = scrollGroupController.addAndGet(); horizontalController = scrollGroupController.addAndGet();

@ -21,10 +21,11 @@ class GridAccessoryMenu extends StatelessWidget {
child: MultiBlocListener( child: MultiBlocListener(
listeners: [ listeners: [
BlocListener<GridFilterMenuBloc, GridFilterMenuState>( BlocListener<GridFilterMenuBloc, GridFilterMenuState>(
listenWhen: (p, c) => p.isVisible != c.isVisible, listenWhen: (p, c) => p.isVisible != c.isVisible,
listener: (context, state) => context listener: (context, state) => context
.read<GridAccessoryMenuBloc>() .read<GridAccessoryMenuBloc>()
.add(const GridAccessoryMenuEvent.toggleMenu())), .add(const GridAccessoryMenuEvent.toggleMenu()),
),
BlocListener<SortMenuBloc, SortMenuState>( BlocListener<SortMenuBloc, SortMenuState>(
listenWhen: (p, c) => p.isVisible != c.isVisible, listenWhen: (p, c) => p.isVisible != c.isVisible,
listener: (context, state) => context listener: (context, state) => context

@ -100,7 +100,9 @@ class _CheckboxFilterEditorState extends State<CheckboxFilterEditor> {
} }
Widget _buildFilterPanel( Widget _buildFilterPanel(
BuildContext context, CheckboxFilterEditorState state) { BuildContext context,
CheckboxFilterEditorState state,
) {
return SizedBox( return SizedBox(
height: 20, height: 20,
child: Row( child: Row(

@ -70,9 +70,11 @@ class _ChecklistFilterChoicechipState extends State<ChecklistFilterChoicechip> {
class ChecklistFilterEditor extends StatefulWidget { class ChecklistFilterEditor extends StatefulWidget {
final ChecklistFilterEditorBloc bloc; final ChecklistFilterEditorBloc bloc;
final PopoverMutex popoverMutex; final PopoverMutex popoverMutex;
const ChecklistFilterEditor( const ChecklistFilterEditor({
{required this.bloc, required this.popoverMutex, Key? key}) required this.bloc,
: super(key: key); required this.popoverMutex,
Key? key,
}) : super(key: key);
@override @override
ChecklistState createState() => ChecklistState(); ChecklistState createState() => ChecklistState();

@ -65,8 +65,10 @@ class _ChoicechipFilterDesc extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final arrow = Transform.rotate( final arrow = Transform.rotate(
angle: -math.pi / 2, angle: -math.pi / 2,
child: svgWidget("home/arrow_left", child: svgWidget(
color: AFThemeExtension.of(context).textColor), "home/arrow_left",
color: AFThemeExtension.of(context).textColor,
),
); );
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 2), padding: const EdgeInsets.symmetric(horizontal: 2),

@ -110,7 +110,10 @@ class _SelectOptionFilterEditorState extends State<SelectOptionFilterEditor> {
selectedOptionIds: state.filter.optionIds, selectedOptionIds: state.filter.optionIds,
onSelectedOptions: (optionIds) { onSelectedOptions: (optionIds) {
context.read<SelectOptionFilterEditorBloc>().add( context.read<SelectOptionFilterEditorBloc>().add(
SelectOptionFilterEditorEvent.updateContent(optionIds)); SelectOptionFilterEditorEvent.updateContent(
optionIds,
),
);
}, },
), ),
), ),
@ -132,7 +135,9 @@ class _SelectOptionFilterEditorState extends State<SelectOptionFilterEditor> {
} }
Widget _buildFilterPanel( Widget _buildFilterPanel(
BuildContext context, SelectOptionFilterEditorState state) { BuildContext context,
SelectOptionFilterEditorState state,
) {
return SizedBox( return SizedBox(
height: 20, height: 20,
child: Row( child: Row(
@ -144,7 +149,8 @@ class _SelectOptionFilterEditorState extends State<SelectOptionFilterEditor> {
popoverMutex: popoverMutex, popoverMutex: popoverMutex,
onCondition: (condition) { onCondition: (condition) {
context.read<SelectOptionFilterEditorBloc>().add( context.read<SelectOptionFilterEditorBloc>().add(
SelectOptionFilterEditorEvent.updateCondition(condition)); SelectOptionFilterEditorEvent.updateCondition(condition),
);
}, },
), ),
const Spacer(), const Spacer(),

@ -147,7 +147,9 @@ class _TextFilterEditorState extends State<TextFilterEditor> {
} }
Widget _buildFilterTextField( Widget _buildFilterTextField(
BuildContext context, TextFilterEditorState state) { BuildContext context,
TextFilterEditorState state,
) {
return FlowyTextField( return FlowyTextField(
text: state.filter.content, text: state.filter.content,
hintText: LocaleKeys.grid_settings_typeAValue.tr(), hintText: LocaleKeys.grid_settings_typeAValue.tr(),

@ -18,8 +18,10 @@ class ConditionButton extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final arrow = Transform.rotate( final arrow = Transform.rotate(
angle: -math.pi / 2, angle: -math.pi / 2,
child: svgWidget("home/arrow_left", child: svgWidget(
color: AFThemeExtension.of(context).textColor), "home/arrow_left",
color: AFThemeExtension.of(context).textColor,
),
); );
return SizedBox( return SizedBox(

@ -117,7 +117,10 @@ class _FilterTextFieldDelegate extends SliverPersistentHeaderDelegate {
@override @override
Widget build( Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) { BuildContext context,
double shrinkOffset,
bool overlapsContent,
) {
return Container( return Container(
padding: const EdgeInsets.only(top: 4), padding: const EdgeInsets.only(top: 4),
height: fixHeight, height: fixHeight,

@ -95,17 +95,20 @@ class _GridHeaderCellContainer extends StatelessWidget {
width: 1.0, width: 1.0,
); );
final decoration = BoxDecoration( final decoration = BoxDecoration(
border: Border( border: Border(
top: borderSide, top: borderSide,
right: borderSide, right: borderSide,
bottom: borderSide, bottom: borderSide,
)); ),
);
return Container( return Container(
width: width, width: width,
decoration: decoration, decoration: decoration,
child: ConstrainedBox( child: ConstrainedBox(
constraints: const BoxConstraints.expand(), child: child), constraints: const BoxConstraints.expand(),
child: child,
),
); );
} }
} }

@ -101,25 +101,27 @@ class _FieldOperationList extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column(children: [ return Column(
Flex( children: [
direction: Axis.horizontal, Flex(
children: [ direction: Axis.horizontal,
_actionCell(FieldAction.hide), children: [
HSpace(GridSize.typeOptionSeparatorHeight), _actionCell(FieldAction.hide),
_actionCell(FieldAction.duplicate), HSpace(GridSize.typeOptionSeparatorHeight),
], _actionCell(FieldAction.duplicate),
), ],
VSpace(GridSize.typeOptionSeparatorHeight), ),
Flex( VSpace(GridSize.typeOptionSeparatorHeight),
direction: Axis.horizontal, Flex(
children: [ direction: Axis.horizontal,
_actionCell(FieldAction.delete), children: [
HSpace(GridSize.typeOptionSeparatorHeight), _actionCell(FieldAction.delete),
const Spacer(), HSpace(GridSize.typeOptionSeparatorHeight),
], const Spacer(),
), ],
]); ),
],
);
} }
Widget _actionCell(FieldAction action) { Widget _actionCell(FieldAction action) {

@ -90,11 +90,13 @@ class _SwitchFieldButton extends StatelessWidget {
mutex: popoverMutex, mutex: popoverMutex,
offset: const Offset(8, 0), offset: const Offset(8, 0),
popupBuilder: (popOverContext) { popupBuilder: (popOverContext) {
return FieldTypeList(onSelectField: (newFieldType) { return FieldTypeList(
context onSelectField: (newFieldType) {
.read<FieldTypeOptionEditBloc>() context
.add(FieldTypeOptionEditEvent.switchToField(newFieldType)); .read<FieldTypeOptionEditBloc>()
}); .add(FieldTypeOptionEditEvent.switchToField(newFieldType));
},
);
}, },
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0), padding: const EdgeInsets.symmetric(horizontal: 12.0),

@ -39,7 +39,9 @@ class _GridHeaderSliverAdaptorState extends State<GridHeaderSliverAdaptor> {
return BlocProvider( return BlocProvider(
create: (context) { create: (context) {
final bloc = getIt<GridHeaderBloc>( final bloc = getIt<GridHeaderBloc>(
param1: widget.viewId, param2: widget.fieldController); param1: widget.viewId,
param2: widget.fieldController,
);
bloc.add(const GridHeaderEvent.initial()); bloc.add(const GridHeaderEvent.initial());
return bloc; return bloc;
}, },
@ -98,10 +100,16 @@ class _GridHeaderState extends State<_GridHeader> {
builder: (context, state) { builder: (context, state) {
final cells = state.fields final cells = state.fields
.where((field) => field.visibility) .where((field) => field.visibility)
.map((field) => .map(
FieldCellContext(viewId: widget.viewId, field: field.field)) (field) =>
.map((ctx) => FieldCellContext(viewId: widget.viewId, field: field.field),
GridFieldCell(key: _getKeyById(ctx.field.id), cellContext: ctx)) )
.map(
(ctx) => GridFieldCell(
key: _getKeyById(ctx.field.id),
cellContext: ctx,
),
)
.toList(); .toList();
return Container( return Container(
@ -124,8 +132,12 @@ class _GridHeaderState extends State<_GridHeader> {
); );
} }
void _onReorder(List<GridFieldCell> cells, int oldIndex, BuildContext context, void _onReorder(
int newIndex) { List<GridFieldCell> cells,
int oldIndex,
BuildContext context,
int newIndex,
) {
if (cells.length > oldIndex) { if (cells.length > oldIndex) {
final field = cells[oldIndex].cellContext.field; final field = cells[oldIndex].cellContext.field;
context context
@ -197,12 +209,17 @@ class SliverHeaderDelegateImplementation
final String gridId; final String gridId;
final List<FieldPB> fields; final List<FieldPB> fields;
SliverHeaderDelegateImplementation( SliverHeaderDelegateImplementation({
{required this.gridId, required this.fields}); required this.gridId,
required this.fields,
});
@override @override
Widget build( Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) { BuildContext context,
double shrinkOffset,
bool overlapsContent,
) {
return _GridHeader(viewId: gridId); return _GridHeader(viewId: gridId);
} }

@ -76,12 +76,13 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
); );
case FieldType.DateTime: case FieldType.DateTime:
return DateTypeOptionWidgetBuilder( return DateTypeOptionWidgetBuilder(
makeTypeOptionContextWithDataController<DateTypeOptionPB>( makeTypeOptionContextWithDataController<DateTypeOptionPB>(
viewId: viewId, viewId: viewId,
fieldType: fieldType, fieldType: fieldType,
dataController: dataController, dataController: dataController,
), ),
popoverMutex); popoverMutex,
);
case FieldType.SingleSelect: case FieldType.SingleSelect:
return SingleSelectTypeOptionWidgetBuilder( return SingleSelectTypeOptionWidgetBuilder(
makeTypeOptionContextWithDataController<SingleSelectTypeOptionPB>( makeTypeOptionContextWithDataController<SingleSelectTypeOptionPB>(

@ -4,7 +4,8 @@ import 'builder.dart';
class ChecklistTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder { class ChecklistTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder {
ChecklistTypeOptionWidgetBuilder( ChecklistTypeOptionWidgetBuilder(
ChecklistTypeOptionContext typeOptionContext); ChecklistTypeOptionContext typeOptionContext,
);
@override @override
Widget? build(BuildContext context) => null; Widget? build(BuildContext context) => null;

@ -28,10 +28,12 @@ class NumberTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder {
@override @override
Widget? build(BuildContext context) { Widget? build(BuildContext context) {
return Column(children: [ return Column(
VSpace(GridSize.typeOptionSeparatorHeight), children: [
_widget, VSpace(GridSize.typeOptionSeparatorHeight),
]); _widget,
],
);
} }
} }
@ -108,9 +110,11 @@ typedef SelectNumberFormatCallback = Function(NumberFormat format);
class NumberFormatList extends StatelessWidget { class NumberFormatList extends StatelessWidget {
final SelectNumberFormatCallback onSelected; final SelectNumberFormatCallback onSelected;
final NumberFormat selectedFormat; final NumberFormat selectedFormat;
const NumberFormatList( const NumberFormatList({
{required this.selectedFormat, required this.onSelected, Key? key}) required this.selectedFormat,
: super(key: key); required this.onSelected,
Key? key,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -127,11 +131,12 @@ class NumberFormatList extends StatelessWidget {
builder: (context, state) { builder: (context, state) {
final cells = state.formats.map((format) { final cells = state.formats.map((format) {
return NumberFormatCell( return NumberFormatCell(
isSelected: format == selectedFormat, isSelected: format == selectedFormat,
format: format, format: format,
onSelected: (format) { onSelected: (format) {
onSelected(format); onSelected(format);
}); },
);
}).toList(); }).toList();
final list = ListView.separated( final list = ListView.separated(

@ -66,7 +66,8 @@ class SelectOptionTypeOptionEditor extends StatelessWidget {
if (showOptions) { if (showOptions) {
cells.add(const TypeOptionSeparator()); cells.add(const TypeOptionSeparator());
cells.add( cells.add(
SelectOptionColorList(selectedColor: state.option.color)); SelectOptionColorList(selectedColor: state.option.color),
);
} }
return SizedBox( return SizedBox(
@ -126,9 +127,11 @@ class _DeleteTag extends StatelessWidget {
class _OptionNameTextField extends StatelessWidget { class _OptionNameTextField extends StatelessWidget {
final String name; final String name;
final bool autoFocus; final bool autoFocus;
const _OptionNameTextField( const _OptionNameTextField({
{required this.name, required this.autoFocus, Key? key}) required this.name,
: super(key: key); required this.autoFocus,
Key? key,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -157,7 +160,9 @@ class SelectOptionColorList extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final cells = SelectOptionColorPB.values.map((color) { final cells = SelectOptionColorPB.values.map((color) {
return _SelectOptionColorCell( return _SelectOptionColorCell(
color: color, isSelected: selectedColor == color); color: color,
isSelected: selectedColor == color,
);
}).toList(); }).toList();
return Column( return Column(
@ -195,9 +200,11 @@ class SelectOptionColorList extends StatelessWidget {
class _SelectOptionColorCell extends StatelessWidget { class _SelectOptionColorCell extends StatelessWidget {
final SelectOptionColorPB color; final SelectOptionColorPB color;
final bool isSelected; final bool isSelected;
const _SelectOptionColorCell( const _SelectOptionColorCell({
{required this.color, required this.isSelected, Key? key}) required this.color,
: super(key: key); required this.isSelected,
Key? key,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

@ -68,11 +68,13 @@ class _GridRowState extends State<GridRow> {
), ),
); );
return Row(children: [ return Row(
const _RowLeading(), children: [
content, const _RowLeading(),
const _RowTrailing(), content,
]); const _RowTrailing(),
],
);
}, },
), ),
), ),
@ -129,9 +131,11 @@ class _RowLeadingState extends State<_RowLeading> {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const _InsertButton(), const _InsertButton(),
_MenuButton(openMenu: () { _MenuButton(
popoverController.show(); openMenu: () {
}), popoverController.show();
},
),
], ],
); );
} }
@ -216,12 +220,13 @@ class RowContent extends StatelessWidget {
!listEquals(previous.cells, current.cells), !listEquals(previous.cells, current.cells),
builder: (context, state) { builder: (context, state) {
return IntrinsicHeight( return IntrinsicHeight(
child: Row( child: Row(
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: _makeCells(context, state.cellByFieldId), children: _makeCells(context, state.cellByFieldId),
)); ),
);
}, },
); );
} }

@ -116,7 +116,10 @@ class _FilterTextFieldDelegate extends SliverPersistentHeaderDelegate {
@override @override
Widget build( Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) { BuildContext context,
double shrinkOffset,
bool overlapsContent,
) {
return Container( return Container(
padding: const EdgeInsets.only(top: 4), padding: const EdgeInsets.only(top: 4),
height: fixHeight, height: fixHeight,

@ -76,13 +76,15 @@ class _SortList extends StatelessWidget {
return BlocBuilder<SortEditorBloc, SortEditorState>( return BlocBuilder<SortEditorBloc, SortEditorState>(
builder: (context, state) { builder: (context, state) {
final List<Widget> children = state.sortInfos final List<Widget> children = state.sortInfos
.map((info) => Padding( .map(
padding: const EdgeInsets.symmetric(vertical: 6), (info) => Padding(
child: _SortItem( padding: const EdgeInsets.symmetric(vertical: 6),
sortInfo: info, child: _SortItem(
popoverMutex: popoverMutex, sortInfo: info,
), popoverMutex: popoverMutex,
)) ),
),
)
.toList(); .toList();
return Column( return Column(

@ -40,8 +40,9 @@ class _GridPropertyListState extends State<GridPropertyList> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => getIt<DatabasePropertyBloc>( create: (context) => getIt<DatabasePropertyBloc>(
param1: widget.viewId, param2: widget.fieldController) param1: widget.viewId,
..add(const DatabasePropertyEvent.initial()), param2: widget.fieldController,
)..add(const DatabasePropertyEvent.initial()),
child: BlocBuilder<DatabasePropertyBloc, DatabasePropertyState>( child: BlocBuilder<DatabasePropertyBloc, DatabasePropertyState>(
builder: (context, state) { builder: (context, state) {
final cells = state.fieldContexts.map((field) { final cells = state.fieldContexts.map((field) {
@ -129,8 +130,11 @@ class _GridPropertyCellState extends State<_GridPropertyCell> {
hoverColor: Colors.transparent, hoverColor: Colors.transparent,
onPressed: () { onPressed: () {
context.read<DatabasePropertyBloc>().add( context.read<DatabasePropertyBloc>().add(
DatabasePropertyEvent.setFieldVisibility( DatabasePropertyEvent.setFieldVisibility(
widget.fieldInfo.id, !widget.fieldInfo.visibility)); widget.fieldInfo.id,
!widget.fieldInfo.visibility,
),
);
}, },
icon: checkmark.padding(all: 6.0), icon: checkmark.padding(all: 6.0),
), ),

@ -25,9 +25,11 @@ class GridSettingContext {
class GridSettingList extends StatelessWidget { class GridSettingList extends StatelessWidget {
final GridSettingContext settingContext; final GridSettingContext settingContext;
final Function(DatabaseSettingAction, GridSettingContext) onAction; final Function(DatabaseSettingAction, GridSettingContext) onAction;
const GridSettingList( const GridSettingList({
{required this.settingContext, required this.onAction, Key? key}) required this.settingContext,
: super(key: key); required this.onAction,
Key? key,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -35,8 +37,9 @@ class GridSettingList extends StatelessWidget {
.where((value) => value.enable()) .where((value) => value.enable())
.map((action) { .map((action) {
return _SettingItem( return _SettingItem(
action: action, action: action,
onAction: (action) => onAction(action, settingContext)); onAction: (action) => onAction(action, settingContext),
);
}).toList(); }).toList();
return SizedBox( return SizedBox(

@ -66,7 +66,8 @@ class CheckboxCardCellState with _$CheckboxCardCellState {
factory CheckboxCardCellState.initial(TextCellController context) { factory CheckboxCardCellState.initial(TextCellController context) {
return CheckboxCardCellState( return CheckboxCardCellState(
isSelected: _isSelected(context.getCellData())); isSelected: _isSelected(context.getCellData()),
);
} }
} }

@ -18,8 +18,12 @@ class DateCardCellBloc extends Bloc<DateCardCellEvent, DateCardCellState> {
event.when( event.when(
initial: () => _startListening(), initial: () => _startListening(),
didReceiveCellUpdate: (DateCellDataPB? cellData) { didReceiveCellUpdate: (DateCellDataPB? cellData) {
emit(state.copyWith( emit(
data: cellData, dateStr: _dateStrFromCellData(cellData))); state.copyWith(
data: cellData,
dateStr: _dateStrFromCellData(cellData),
),
);
}, },
); );
}, },

@ -42,9 +42,11 @@ class SelectOptionCardCellBloc
_onCellChangedFn = cellController.startListening( _onCellChangedFn = cellController.startListening(
onCellChanged: ((selectOptionContext) { onCellChanged: ((selectOptionContext) {
if (!isClosed) { if (!isClosed) {
add(SelectOptionCardCellEvent.didReceiveOptions( add(
selectOptionContext?.selectOptions ?? [], SelectOptionCardCellEvent.didReceiveOptions(
)); selectOptionContext?.selectOptions ?? [],
),
);
} }
}), }),
); );
@ -66,7 +68,8 @@ class SelectOptionCardCellState with _$SelectOptionCardCellState {
}) = _SelectOptionCardCellState; }) = _SelectOptionCardCellState;
factory SelectOptionCardCellState.initial( factory SelectOptionCardCellState.initial(
SelectOptionCellController context) { SelectOptionCellController context,
) {
final data = context.getCellData(); final data = context.getCellData();
return SelectOptionCardCellState( return SelectOptionCardCellState(
selectedOptions: data?.selectOptions ?? [], selectedOptions: data?.selectOptions ?? [],

@ -19,10 +19,12 @@ class URLCardCellBloc extends Bloc<URLCardCellEvent, URLCardCellState> {
_startListening(); _startListening();
}, },
didReceiveCellUpdate: (cellData) { didReceiveCellUpdate: (cellData) {
emit(state.copyWith( emit(
content: cellData?.content ?? "", state.copyWith(
url: cellData?.url ?? "", content: cellData?.content ?? "",
)); url: cellData?.url ?? "",
),
);
}, },
updateURL: (String url) { updateURL: (String url) {
cellController.saveCellData(url, deduplicate: true); cellController.saveCellData(url, deduplicate: true);

@ -41,10 +41,12 @@ class CardBloc extends Bloc<BoardCardEvent, BoardCardState> {
await _startListening(); await _startListening();
}, },
didReceiveCells: (cells, reason) async { didReceiveCells: (cells, reason) async {
emit(state.copyWith( emit(
cells: cells, state.copyWith(
changeReason: reason, cells: cells,
)); changeReason: reason,
),
);
}, },
setIsEditing: (bool isEditing) { setIsEditing: (bool isEditing) {
emit(state.copyWith(isEditing: isEditing)); emit(state.copyWith(isEditing: isEditing));
@ -87,7 +89,9 @@ class CardBloc extends Bloc<BoardCardEvent, BoardCardState> {
} }
List<BoardCellEquatable> _makeCells( List<BoardCellEquatable> _makeCells(
String groupFieldId, CellByFieldId originalCellMap) { String groupFieldId,
CellByFieldId originalCellMap,
) {
List<BoardCellEquatable> cells = []; List<BoardCellEquatable> cells = [];
for (final entry in originalCellMap.entries) { for (final entry in originalCellMap.entries) {
// Filter out the cell if it's fieldId equal to the groupFieldId // Filter out the cell if it's fieldId equal to the groupFieldId

@ -50,45 +50,49 @@ class _SelectOptionCardCellState extends State<SelectOptionCardCell> {
return BlocProvider.value( return BlocProvider.value(
value: _cellBloc, value: _cellBloc,
child: BlocBuilder<SelectOptionCardCellBloc, SelectOptionCardCellState>( child: BlocBuilder<SelectOptionCardCellBloc, SelectOptionCardCellState>(
buildWhen: (previous, current) { buildWhen: (previous, current) {
return previous.selectedOptions != current.selectedOptions; return previous.selectedOptions != current.selectedOptions;
}, builder: (context, state) { },
Widget? custom = widget.renderHook?.call( builder: (context, state) {
state.selectedOptions, Widget? custom = widget.renderHook?.call(
widget.cardData, state.selectedOptions,
); widget.cardData,
if (custom != null) { );
return custom; if (custom != null) {
} return custom;
}
final children = state.selectedOptions.map( final children = state.selectedOptions.map(
(option) { (option) {
final tag = SelectOptionTag.fromOption( final tag = SelectOptionTag.fromOption(
context: context, context: context,
option: option, option: option,
onSelected: () => _popover.show(), onSelected: () => _popover.show(),
); );
return _wrapPopover(tag); return _wrapPopover(tag);
}, },
).toList(); ).toList();
return IntrinsicHeight( return IntrinsicHeight(
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 6), padding: const EdgeInsets.symmetric(vertical: 6),
child: SizedBox.expand( child: SizedBox.expand(
child: Wrap(spacing: 4, runSpacing: 2, children: children), child: Wrap(spacing: 4, runSpacing: 2, children: children),
),
), ),
), );
); },
}), ),
); );
} }
Widget _wrapPopover(Widget child) { Widget _wrapPopover(Widget child) {
final constraints = BoxConstraints.loose(Size( final constraints = BoxConstraints.loose(
SelectOptionCellEditor.editorPanelWidth, Size(
300, SelectOptionCellEditor.editorPanelWidth,
)); 300,
),
);
return AppFlowyPopover( return AppFlowyPopover(
controller: _popover, controller: _popover,
constraints: constraints, constraints: constraints,

@ -93,11 +93,12 @@ class _CardEnterRegion extends StatelessWidget {
Provider.of<_CardContainerNotifier>(context, listen: false) Provider.of<_CardContainerNotifier>(context, listen: false)
.onEnter = false, .onEnter = false,
child: IntrinsicHeight( child: IntrinsicHeight(
child: Stack( child: Stack(
alignment: AlignmentDirectional.topEnd, alignment: AlignmentDirectional.topEnd,
fit: StackFit.expand, fit: StackFit.expand,
children: children, children: children,
)), ),
),
); );
}, },
); );

@ -127,10 +127,12 @@ class _AccessoryHoverState extends State<AccessoryHover> {
final accessoryBuilder = widget.child.accessoryBuilder; final accessoryBuilder = widget.child.accessoryBuilder;
if (accessoryBuilder != null) { if (accessoryBuilder != null) {
final accessories = accessoryBuilder((GridCellAccessoryBuildContext( final accessories = accessoryBuilder(
anchorContext: context, (GridCellAccessoryBuildContext(
isCellEditing: false, anchorContext: context,
))); isCellEditing: false,
)),
);
children.add( children.add(
Padding( Padding(
padding: const EdgeInsets.only(right: 6), padding: const EdgeInsets.only(right: 6),

@ -96,7 +96,8 @@ abstract class CellEditable {
} }
typedef AccessoryBuilder = List<GridCellAccessoryBuilder> Function( typedef AccessoryBuilder = List<GridCellAccessoryBuilder> Function(
GridCellAccessoryBuildContext buildContext); GridCellAccessoryBuildContext buildContext,
);
abstract class CellAccessory extends Widget { abstract class CellAccessory extends Widget {
const CellAccessory({Key? key}) : super(key: key); const CellAccessory({Key? key}) : super(key: key);
@ -127,7 +128,8 @@ abstract class GridCellWidget extends StatefulWidget
@override @override
List<GridCellAccessoryBuilder> Function( List<GridCellAccessoryBuilder> Function(
GridCellAccessoryBuildContext buildContext)? get accessoryBuilder => null; GridCellAccessoryBuildContext buildContext,
)? get accessoryBuilder => null;
@override @override
final GridCellFocusListener beginFocus = GridCellFocusListener(); final GridCellFocusListener beginFocus = GridCellFocusListener();

@ -77,7 +77,8 @@ class CellContainer extends StatelessWidget {
width: 1.0, width: 1.0,
); );
return BoxDecoration( return BoxDecoration(
border: Border(right: borderSide, bottom: borderSide)); border: Border(right: borderSide, bottom: borderSide),
);
} }
} }
} }

@ -27,8 +27,9 @@ class _CheckboxCellState extends GridCellState<GridCheckboxCell> {
final cellController = final cellController =
widget.cellControllerBuilder.build() as CheckboxCellController; widget.cellControllerBuilder.build() as CheckboxCellController;
_cellBloc = CheckboxCellBloc( _cellBloc = CheckboxCellBloc(
service: CellBackendService(), cellController: cellController) service: CellBackendService(),
..add(const CheckboxCellEvent.initial()); cellController: cellController,
)..add(const CheckboxCellEvent.initial());
super.initState(); super.initState();
} }

@ -43,12 +43,13 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
} }
void _startListening() { void _startListening() {
_onCellChangedFn = _onCellChangedFn = cellController.startListening(
cellController.startListening(onCellChanged: ((cellData) { onCellChanged: ((cellData) {
if (!isClosed) { if (!isClosed) {
add(CheckboxCellEvent.didReceiveCellUpdate(cellData)); add(CheckboxCellEvent.didReceiveCellUpdate(cellData));
} }
})); }),
);
} }
} }

@ -26,11 +26,13 @@ class ChecklistCardCellBloc
_loadOptions(); _loadOptions();
}, },
didReceiveOptions: (data) { didReceiveOptions: (data) {
emit(state.copyWith( emit(
allOptions: data.options, state.copyWith(
selectedOptions: data.selectOptions, allOptions: data.options,
percent: percentFromSelectOptionCellData(data), selectedOptions: data.selectOptions,
)); percent: percentFromSelectOptionCellData(data),
),
);
}, },
); );
}, },
@ -76,7 +78,8 @@ class ChecklistCardCellBloc
class ChecklistCellEvent with _$ChecklistCellEvent { class ChecklistCellEvent with _$ChecklistCellEvent {
const factory ChecklistCellEvent.initial() = _InitialCell; const factory ChecklistCellEvent.initial() = _InitialCell;
const factory ChecklistCellEvent.didReceiveOptions( const factory ChecklistCellEvent.didReceiveOptions(
SelectOptionCellDataPB data) = _DidReceiveCellUpdate; SelectOptionCellDataPB data,
) = _DidReceiveCellUpdate;
} }
@freezed @freezed

@ -28,16 +28,20 @@ class ChecklistCellEditorBloc
_loadOptions(); _loadOptions();
}, },
didReceiveOptions: (data) { didReceiveOptions: (data) {
emit(state.copyWith( emit(
allOptions: _makeChecklistSelectOptions(data, state.predicate), state.copyWith(
percent: percentFromSelectOptionCellData(data), allOptions: _makeChecklistSelectOptions(data, state.predicate),
)); percent: percentFromSelectOptionCellData(data),
),
);
}, },
newOption: (optionName) { newOption: (optionName) {
_createOption(optionName); _createOption(optionName);
emit(state.copyWith( emit(
predicate: '', state.copyWith(
)); predicate: '',
),
);
}, },
deleteOption: (option) { deleteOption: (option) {
_deleteOption([option]); _deleteOption([option]);
@ -114,11 +118,13 @@ class ChecklistCellEditorBloc
class ChecklistCellEditorEvent with _$ChecklistCellEditorEvent { class ChecklistCellEditorEvent with _$ChecklistCellEditorEvent {
const factory ChecklistCellEditorEvent.initial() = _Initial; const factory ChecklistCellEditorEvent.initial() = _Initial;
const factory ChecklistCellEditorEvent.didReceiveOptions( const factory ChecklistCellEditorEvent.didReceiveOptions(
SelectOptionCellDataPB data) = _DidReceiveOptions; SelectOptionCellDataPB data,
) = _DidReceiveOptions;
const factory ChecklistCellEditorEvent.newOption(String optionName) = const factory ChecklistCellEditorEvent.newOption(String optionName) =
_NewOption; _NewOption;
const factory ChecklistCellEditorEvent.selectOption( const factory ChecklistCellEditorEvent.selectOption(
ChecklistSelectOption option) = _SelectOption; ChecklistSelectOption option,
) = _SelectOption;
const factory ChecklistCellEditorEvent.updateOption(SelectOptionPB option) = const factory ChecklistCellEditorEvent.updateOption(SelectOptionPB option) =
_UpdateOption; _UpdateOption;
const factory ChecklistCellEditorEvent.deleteOption(SelectOptionPB option) = const factory ChecklistCellEditorEvent.deleteOption(SelectOptionPB option) =
@ -163,7 +169,9 @@ double percentFromSelectOptionCellData(SelectOptionCellDataPB? data) {
} }
List<ChecklistSelectOption> _makeChecklistSelectOptions( List<ChecklistSelectOption> _makeChecklistSelectOptions(
SelectOptionCellDataPB? data, String predicate) { SelectOptionCellDataPB? data,
String predicate,
) {
if (data == null) { if (data == null) {
return []; return [];
} }

@ -46,7 +46,10 @@ class _SliverChecklistProgressBarDelegate
@override @override
Widget build( Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) { BuildContext context,
double shrinkOffset,
bool overlapsContent,
) {
return BlocBuilder<ChecklistCellEditorBloc, ChecklistCellEditorState>( return BlocBuilder<ChecklistCellEditorBloc, ChecklistCellEditorState>(
builder: (context, state) { builder: (context, state) {
return Container( return Container(

@ -44,7 +44,9 @@ class DateCellCalendarBloc
didReceiveCellUpdate: (DateCellDataPB? cellData) { didReceiveCellUpdate: (DateCellDataPB? cellData) {
final dateCellData = calDataFromCellData(cellData); final dateCellData = calDataFromCellData(cellData);
final time = dateCellData.foldRight( final time = dateCellData.foldRight(
"", (dateData, previous) => dateData.time ?? ''); "",
(dateData, previous) => dateData.time ?? '',
);
emit(state.copyWith(dateCellData: dateCellData, time: time)); emit(state.copyWith(dateCellData: dateCellData, time: time));
}, },
setIncludeTime: (includeTime) async { setIncludeTime: (includeTime) async {
@ -63,16 +65,24 @@ class DateCellCalendarBloc
}, },
didUpdateCalData: didUpdateCalData:
(Option<DateCellData> data, Option<String> timeFormatError) { (Option<DateCellData> data, Option<String> timeFormatError) {
emit(state.copyWith( emit(
dateCellData: data, timeFormatError: timeFormatError)); state.copyWith(
dateCellData: data,
timeFormatError: timeFormatError,
),
);
}, },
); );
}, },
); );
} }
Future<void> _updateDateData(Emitter<DateCellCalendarState> emit, Future<void> _updateDateData(
{DateTime? date, String? time, bool? includeTime}) { Emitter<DateCellCalendarState> emit, {
DateTime? date,
String? time,
bool? includeTime,
}) {
final DateCellData newDateData = state.dateCellData.fold( final DateCellData newDateData = state.dateCellData.fold(
() => DateCellData( () => DateCellData(
date: date ?? DateTime.now(), date: date ?? DateTime.now(),
@ -101,33 +111,44 @@ class DateCellCalendarBloc
} }
Future<void> _saveDateData( Future<void> _saveDateData(
Emitter<DateCellCalendarState> emit, DateCellData newCalData) async { Emitter<DateCellCalendarState> emit,
DateCellData newCalData,
) async {
if (state.dateCellData == Some(newCalData)) { if (state.dateCellData == Some(newCalData)) {
return; return;
} }
updateCalData( updateCalData(
Option<DateCellData> dateCellData, Option<String> timeFormatError) { Option<DateCellData> dateCellData,
Option<String> timeFormatError,
) {
if (!isClosed) { if (!isClosed) {
add(DateCellCalendarEvent.didUpdateCalData( add(
dateCellData, timeFormatError)); DateCellCalendarEvent.didUpdateCalData(
dateCellData,
timeFormatError,
),
);
} }
} }
cellController.saveCellData(newCalData, onFinish: (result) { cellController.saveCellData(
result.fold( newCalData,
() => updateCalData(Some(newCalData), none()), onFinish: (result) {
(err) { result.fold(
switch (ErrorCode.valueOf(err.code)!) { () => updateCalData(Some(newCalData), none()),
case ErrorCode.InvalidDateTimeFormat: (err) {
updateCalData(state.dateCellData, Some(timeFormatPrompt(err))); switch (ErrorCode.valueOf(err.code)!) {
break; case ErrorCode.InvalidDateTimeFormat:
default: updateCalData(state.dateCellData, Some(timeFormatPrompt(err)));
Log.error(err); break;
} default:
}, Log.error(err);
); }
}); },
);
},
);
} }
String timeFormatPrompt(FlowyError error) { String timeFormatPrompt(FlowyError error) {
@ -188,9 +209,12 @@ class DateCellCalendarBloc
); );
result.fold( result.fold(
(l) => emit(state.copyWith( (l) => emit(
state.copyWith(
dateTypeOptionPB: newDateTypeOption, dateTypeOptionPB: newDateTypeOption,
timeHintText: _timeHintText(newDateTypeOption))), timeHintText: _timeHintText(newDateTypeOption),
),
),
(err) => Log.error(err), (err) => Log.error(err),
); );
} }
@ -211,10 +235,12 @@ class DateCellCalendarEvent with _$DateCellCalendarEvent {
_IncludeTime; _IncludeTime;
const factory DateCellCalendarEvent.setTime(String time) = _Time; const factory DateCellCalendarEvent.setTime(String time) = _Time;
const factory DateCellCalendarEvent.didReceiveCellUpdate( const factory DateCellCalendarEvent.didReceiveCellUpdate(
DateCellDataPB? data) = _DidReceiveCellUpdate; DateCellDataPB? data,
) = _DidReceiveCellUpdate;
const factory DateCellCalendarEvent.didUpdateCalData( const factory DateCellCalendarEvent.didUpdateCalData(
Option<DateCellData> data, Option<String> timeFormatError) = Option<DateCellData> data,
_DidUpdateCalData; Option<String> timeFormatError,
) = _DidUpdateCalData;
} }
@freezed @freezed
@ -268,11 +294,13 @@ Option<DateCellData> calDataFromCellData(DateCellDataPB? cellData) {
timestamp.toInt(), timestamp.toInt(),
isUtc: true, isUtc: true,
); );
dateData = Some(DateCellData( dateData = Some(
date: date, DateCellData(
time: time, date: date,
includeTime: cellData.includeTime, time: time,
)); includeTime: cellData.includeTime,
),
);
} }
return dateData; return dateData;
} }

@ -17,8 +17,12 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
event.when( event.when(
initial: () => _startListening(), initial: () => _startListening(),
didReceiveCellUpdate: (DateCellDataPB? cellData) { didReceiveCellUpdate: (DateCellDataPB? cellData) {
emit(state.copyWith( emit(
data: cellData, dateStr: _dateStrFromCellData(cellData))); state.copyWith(
data: cellData,
dateStr: _dateStrFromCellData(cellData),
),
);
}, },
); );
}, },

@ -193,9 +193,11 @@ class _CellCalendarWidgetState extends State<_CellCalendarWidget> {
cellMargin: const EdgeInsets.all(3), cellMargin: const EdgeInsets.all(3),
defaultDecoration: boxDecoration, defaultDecoration: boxDecoration,
selectedDecoration: boxDecoration.copyWith( selectedDecoration: boxDecoration.copyWith(
color: Theme.of(context).colorScheme.primary), color: Theme.of(context).colorScheme.primary,
),
todayDecoration: boxDecoration.copyWith( todayDecoration: boxDecoration.copyWith(
color: AFThemeExtension.of(context).lightGreyHover), color: AFThemeExtension.of(context).lightGreyHover,
),
weekendDecoration: boxDecoration, weekendDecoration: boxDecoration,
outsideDecoration: boxDecoration, outsideDecoration: boxDecoration,
defaultTextStyle: textStyle, defaultTextStyle: textStyle,
@ -448,11 +450,12 @@ class _CalDateTimeSettingState extends State<_CalDateTimeSetting> {
offset: const Offset(8, 0), offset: const Offset(8, 0),
popupBuilder: (BuildContext context) { popupBuilder: (BuildContext context) {
return TimeFormatList( return TimeFormatList(
selectedFormat: widget.dateTypeOptionPB.timeFormat, selectedFormat: widget.dateTypeOptionPB.timeFormat,
onSelected: (format) { onSelected: (format) {
widget.onEvent(DateCellCalendarEvent.setTimeFormat(format)); widget.onEvent(DateCellCalendarEvent.setTimeFormat(format));
timeSettingPopoverMutex.close(); timeSettingPopoverMutex.close();
}); },
);
}, },
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 6.0), padding: const EdgeInsets.symmetric(horizontal: 6.0),

@ -25,12 +25,15 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
updateCell: (text) { updateCell: (text) {
if (state.cellContent != text) { if (state.cellContent != text) {
emit(state.copyWith(cellContent: text)); emit(state.copyWith(cellContent: text));
cellController.saveCellData(text, onFinish: (result) { cellController.saveCellData(
result.fold( text,
() {}, onFinish: (result) {
(err) => Log.error(err), result.fold(
); () {},
}); (err) => Log.error(err),
);
},
);
} }
}, },
); );

@ -169,10 +169,12 @@ class _SelectOptionWrapState extends State<SelectOptionWrap> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget child = _buildOptions(context); Widget child = _buildOptions(context);
final constraints = BoxConstraints.loose(Size( final constraints = BoxConstraints.loose(
SelectOptionCellEditor.editorPanelWidth, Size(
300, SelectOptionCellEditor.editorPanelWidth,
)); 300,
),
);
return AppFlowyPopover( return AppFlowyPopover(
controller: widget.popoverController, controller: widget.popoverController,
constraints: constraints, constraints: constraints,

@ -21,9 +21,11 @@ class SelectOptionCellBloc
_startListening(); _startListening();
}, },
didReceiveOptions: (_DidReceiveOptions value) { didReceiveOptions: (_DidReceiveOptions value) {
emit(state.copyWith( emit(
selectedOptions: value.selectedOptions, state.copyWith(
)); selectedOptions: value.selectedOptions,
),
);
}, },
); );
}, },
@ -44,9 +46,11 @@ class SelectOptionCellBloc
_onCellChangedFn = cellController.startListening( _onCellChangedFn = cellController.startListening(
onCellChanged: ((selectOptionContext) { onCellChanged: ((selectOptionContext) {
if (!isClosed) { if (!isClosed) {
add(SelectOptionCellEvent.didReceiveOptions( add(
selectOptionContext?.selectOptions ?? [], SelectOptionCellEvent.didReceiveOptions(
)); selectOptionContext?.selectOptions ?? [],
),
);
} }
}), }),
); );

@ -77,13 +77,15 @@ class _OptionList extends StatelessWidget {
builder: (context, state) { builder: (context, state) {
List<Widget> cells = []; List<Widget> cells = [];
cells.add(const _Title()); cells.add(const _Title());
cells.addAll(state.options.map((option) { cells.addAll(
return _SelectOptionCell( state.options.map((option) {
option: option, return _SelectOptionCell(
isSelected: state.selectedOptions.contains(option), option: option,
popoverMutex: popoverMutex, isSelected: state.selectedOptions.contains(option),
); popoverMutex: popoverMutex,
}).toList()); );
}).toList(),
);
state.createOption.fold( state.createOption.fold(
() => null, () => null,
@ -124,9 +126,10 @@ class _TextField extends StatelessWidget {
return BlocBuilder<SelectOptionCellEditorBloc, SelectOptionEditorState>( return BlocBuilder<SelectOptionCellEditorBloc, SelectOptionEditorState>(
builder: (context, state) { builder: (context, state) {
final optionMap = LinkedHashMap<String, SelectOptionPB>.fromIterable( final optionMap = LinkedHashMap<String, SelectOptionPB>.fromIterable(
state.selectedOptions, state.selectedOptions,
key: (option) => option.name, key: (option) => option.name,
value: (option) => option); value: (option) => option,
);
return Padding( return Padding(
padding: const EdgeInsets.all(_padding), padding: const EdgeInsets.all(_padding),
@ -149,19 +152,19 @@ class _TextField extends StatelessWidget {
.add(SelectOptionEditorEvent.trySelectOption(tagName)); .add(SelectOptionEditorEvent.trySelectOption(tagName));
}, },
onPaste: (tagNames, remainder) { onPaste: (tagNames, remainder) {
context context.read<SelectOptionCellEditorBloc>().add(
.read<SelectOptionCellEditorBloc>() SelectOptionEditorEvent.selectMultipleOptions(
.add(SelectOptionEditorEvent.selectMultipleOptions( tagNames,
tagNames, remainder,
remainder, ),
)); );
}, },
onRemove: (optionName) { onRemove: (optionName) {
context context.read<SelectOptionCellEditorBloc>().add(
.read<SelectOptionCellEditorBloc>() SelectOptionEditorEvent.unSelectOption(
.add(SelectOptionEditorEvent.unSelectOption( optionMap[optionName]!.id,
optionMap[optionName]!.id, ),
)); );
}, },
), ),
); );

Some files were not shown because too many files have changed in this diff Show More