From 18498c04792f4f319dcd873afba5314fef5ab8db Mon Sep 17 00:00:00 2001 From: Richard Shiue <71320345+richardshiue@users.noreply.github.com> Date: Fri, 1 Sep 2023 22:40:17 +0800 Subject: [PATCH] feat: field settings application domain (#3284) * chore: default field settings if not exist * chore: field settings listeners and services * chore: don't need to updateFieldInfos * chore: load default field settings if none found * chore: update collab ref * chore: fix remidner compile errors * fix: fix tests * chore: update tauri project setting --------- Co-authored-by: nathan --- .../application/field/field_controller.dart | 483 ++++++++++-------- .../application/field/field_info.dart | 5 + .../field_settings_listener.dart | 51 ++ .../field_settings_service.dart | 54 ++ .../application/row/row_cache.dart | 3 + .../widgets/filter/filter_info.dart | 4 + .../presentation/widgets/sort/sort_info.dart | 2 + frontend/appflowy_tauri/src-tauri/Cargo.lock | 157 +++--- frontend/appflowy_tauri/src-tauri/Cargo.toml | 18 +- frontend/rust-lib/Cargo.lock | 86 +--- frontend/rust-lib/Cargo.toml | 17 +- .../src/entities/field_settings_entities.rs | 12 +- .../src/entities/setting_entities.rs | 8 +- .../flowy-database2/src/event_handler.rs | 31 +- .../rust-lib/flowy-database2/src/event_map.rs | 6 +- .../rust-lib/flowy-database2/src/manager.rs | 17 +- .../src/services/database/database_editor.rs | 145 ++++-- .../src/services/database/util.rs | 13 +- .../src/services/database_view/view_editor.rs | 22 +- .../services/field_settings/field_settings.rs | 35 -- .../field_settings/field_settings_builder.rs | 91 +++- .../src/services/field_settings/mod.rs | 3 - .../src/services/share/csv/import.rs | 7 +- .../rust-lib/flowy-database2/src/template.rs | 29 +- .../database/field_settings_test/script.rs | 26 +- .../database/field_settings_test/test.rs | 87 +++- .../database/mock_data/board_mock_data.rs | 7 +- .../database/mock_data/calendar_mock_data.rs | 7 +- .../database/mock_data/grid_mock_data.rs | 12 +- frontend/rust-lib/flowy-user-deps/Cargo.toml | 2 +- .../flowy-user/src/entities/reminder.rs | 12 +- .../flowy-user/src/services/user_awareness.rs | 3 +- 32 files changed, 909 insertions(+), 546 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/plugins/database_view/application/field_settings/field_settings_listener.dart create mode 100644 frontend/appflowy_flutter/lib/plugins/database_view/application/field_settings/field_settings_service.dart delete mode 100644 frontend/rust-lib/flowy-database2/src/services/field_settings/field_settings.rs diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_controller.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_controller.dart index b6c8d024f3..0e464e33fe 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_controller.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_controller.dart @@ -1,24 +1,27 @@ -import 'dart:collection'; -import 'package:appflowy_backend/protobuf/flowy-database2/filter_changeset.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/sort_entities.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy/plugins/database_view/application/database_view_service.dart'; +import 'package:appflowy/plugins/database_view/application/field_settings/field_settings_listener.dart'; +import 'package:appflowy/plugins/database_view/application/field_settings/field_settings_service.dart'; +import 'package:appflowy/plugins/database_view/application/filter/filter_listener.dart'; +import 'package:appflowy/plugins/database_view/application/filter/filter_service.dart'; +import 'package:appflowy/plugins/database_view/application/row/row_cache.dart'; +import 'package:appflowy/plugins/database_view/application/setting/setting_listener.dart'; +import 'package:appflowy/plugins/database_view/application/sort/sort_listener.dart'; +import 'package:appflowy/plugins/database_view/application/sort/sort_service.dart'; +import 'package:appflowy/plugins/database_view/grid/presentation/widgets/filter/filter_info.dart'; +import 'package:appflowy/plugins/database_view/grid/presentation/widgets/sort/sort_info.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/field_settings_entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/filter_changeset.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/group.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/sort_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/util.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:collection/collection.dart'; +import 'package:dartz/dartz.dart'; import 'package:flutter/foundation.dart'; -import '../../grid/presentation/widgets/filter/filter_info.dart'; -import '../../grid/presentation/widgets/sort/sort_info.dart'; -import '../database_view_service.dart'; -import '../filter/filter_listener.dart'; -import '../filter/filter_service.dart'; -import '../row/row_cache.dart'; -import '../setting/setting_listener.dart'; -import '../setting/setting_service.dart'; -import '../sort/sort_listener.dart'; -import '../sort/sort_service.dart'; + import 'field_info.dart'; import 'field_listener.dart'; @@ -72,20 +75,23 @@ typedef OnReceiveUpdateFields = void Function(List); typedef OnReceiveFields = void Function(List); typedef OnReceiveFilters = void Function(List); typedef OnReceiveSorts = void Function(List); +typedef OnReceiveFieldSettings = void Function(List); class FieldController { final String viewId; + // Listeners final FieldsListener _fieldListener; final DatabaseSettingListener _settingListener; final FiltersListener _filtersListener; final SortsListener _sortsListener; + final FieldSettingsListener _fieldSettingsListener; // FFI services final DatabaseViewBackendService _databaseViewBackendSvc; - final SettingBackendService _settingBackendSvc; final FilterBackendService _filterBackendSvc; final SortBackendService _sortBackendSvc; + final FieldSettingsBackendService _fieldSettingsBackendSvc; bool _isDisposed = false; @@ -97,18 +103,17 @@ class FieldController { final Map)> _updatedFieldCallbacks = {}; - // Group callbacks - final Map _groupConfigurationByFieldId = {}; - // Filter callbacks final Map _filterCallbacks = {}; _GridFilterNotifier? _filterNotifier = _GridFilterNotifier(); - final Map _filterPBByFieldId = {}; // Sort callbacks final Map _sortCallbacks = {}; _GridSortNotifier? _sortNotifier = _GridSortNotifier(); - final Map _sortPBByFieldId = {}; + + // Database settings temporary storage + final Map _groupConfigurationByFieldId = {}; + final List _fieldSettings = []; // Getters List get fieldInfos => [..._fieldNotifier.fieldInfos]; @@ -116,39 +121,28 @@ class FieldController { List get sortInfos => [..._sortNotifier?.sorts ?? []]; FieldInfo? getField(String fieldId) { - final fields = _fieldNotifier.fieldInfos - .where((element) => element.id == fieldId) - .toList(); - - if (fields.isEmpty) { - return null; - } - assert(fields.length == 1); - return fields.first; + return _fieldNotifier.fieldInfos + .firstWhereOrNull((element) => element.id == fieldId); } - FilterInfo? getFilter(String filterId) { - final filters = _filterNotifier?.filters - .where((element) => element.filter.id == filterId) - .toList() ?? - []; - if (filters.isEmpty) { - return null; - } - assert(filters.length == 1); - return filters.first; + FilterInfo? getFilterByFilterId(String filterId) { + return _filterNotifier?.filters + .firstWhereOrNull((element) => element.filterId == filterId); } - SortInfo? getSort(String sortId) { - final sorts = _sortNotifier?.sorts - .where((element) => element.sortId == sortId) - .toList() ?? - []; - if (sorts.isEmpty) { - return null; - } - assert(sorts.length == 1); - return sorts.first; + FilterInfo? getFilterByFieldId(String fieldId) { + return _filterNotifier?.filters + .firstWhereOrNull((element) => element.fieldId == fieldId); + } + + SortInfo? getSortBySortId(String sortId) { + return _sortNotifier?.sorts + .firstWhereOrNull((element) => element.sortId == sortId); + } + + SortInfo? getSortByFieldId(String fieldId) { + return _sortNotifier?.sorts + .firstWhereOrNull((element) => element.fieldId == fieldId); } FieldController({required this.viewId}) @@ -159,34 +153,18 @@ class FieldController { _databaseViewBackendSvc = DatabaseViewBackendService(viewId: viewId), _sortBackendSvc = SortBackendService(viewId: viewId), _sortsListener = SortsListener(viewId: viewId), - _settingBackendSvc = SettingBackendService(viewId: viewId) { - //Listen on field's changes + _fieldSettingsListener = FieldSettingsListener(viewId: viewId), + _fieldSettingsBackendSvc = FieldSettingsBackendService(viewId: viewId) { + // Start listeners _listenOnFieldChanges(); - - //Listen on setting changes _listenOnSettingChanges(); - - //Listen on the filter changes _listenOnFilterChanges(); - - //Listen on the sort changes _listenOnSortChanged(); - - _settingBackendSvc.getSetting().then((result) { - if (_isDisposed) { - return; - } - - result.fold( - (setting) => _updateSetting(setting), - (err) => Log.error(err), - ); - }); + _listenOnFieldSettingsChanged(); } + /// Listen for filter changes in the backend. void _listenOnFilterChanges() { - //Listen on the filter changes - deleteFilterFromChangeset( List filters, FilterChangesetNotificationPB changeset, @@ -196,9 +174,6 @@ class FieldController { filters.retainWhere( (element) => !deleteFilterIds.contains(element.filter.id), ); - - _filterPBByFieldId - .removeWhere((key, value) => deleteFilterIds.contains(value.id)); } } @@ -216,7 +191,6 @@ class FieldController { fieldType: newFilter.fieldType, ); if (fieldInfo != null) { - _filterPBByFieldId[fieldInfo.id] = newFilter; filters.add(FilterInfo(viewId, newFilter, fieldInfo)); } } @@ -234,8 +208,6 @@ class FieldController { // Remove the old filter if (filterIndex != -1) { filters.removeAt(filterIndex); - _filterPBByFieldId - .removeWhere((key, value) => value.id == updatedFilter.filterId); } // Insert the filter if there is a filter and its field info is @@ -257,7 +229,6 @@ class FieldController { } else { filters.add(filterInfo); } - _filterPBByFieldId[fieldInfo.id] = updatedFilter.filter; } } } @@ -272,16 +243,17 @@ class FieldController { result.fold( (FilterChangesetNotificationPB changeset) { final List filters = filterInfos; - // Deletes the filters + // delete removed filters deleteFilterFromChangeset(filters, changeset); - // Inserts the new filter if it's not exist + // insert new filters insertFilterFromChangeset(filters, changeset); + // edit modified filters updateFilterFromChangeset(filters, changeset); - _updateFieldInfos(); _filterNotifier?.filters = filters; + _updateFieldInfos(); }, (err) => Log.error(err), ); @@ -289,6 +261,7 @@ class FieldController { ); } + /// Listen for sort changes in the backend. void _listenOnSortChanged() { deleteSortFromChangeset( List newSortInfos, @@ -299,9 +272,6 @@ class FieldController { newSortInfos.retainWhere( (element) => !deleteSortIds.contains(element.sortId), ); - - _sortPBByFieldId - .removeWhere((key, value) => deleteSortIds.contains(value.id)); } } @@ -320,7 +290,6 @@ class FieldController { ); if (fieldInfo != null) { - _sortPBByFieldId[newSortPB.fieldId] = newSortPB; newSortInfos.add(SortInfo(sortPB: newSortPB, fieldInfo: fieldInfo)); } } @@ -356,7 +325,6 @@ class FieldController { } else { newSortInfos.add(newSortInfo); } - _sortPBByFieldId[updatedSort.fieldId] = updatedSort; } } } @@ -373,7 +341,6 @@ class FieldController { insertSortFromChangeset(newSortInfos, changeset); updateSortFromChangeset(newSortInfos, changeset); - _updateFieldInfos(); _sortNotifier?.sorts = newSortInfos; }, (err) => Log.error(err), @@ -382,8 +349,8 @@ class FieldController { ); } + /// Listen for databse setting changes in the backend. void _listenOnSettingChanges() { - //Listen on setting changes _settingListener.start( onSettingUpdated: (result) { if (_isDisposed) { @@ -398,8 +365,83 @@ class FieldController { ); } + /// Listen for field changes in the backend. void _listenOnFieldChanges() { - //Listen on field's changes + void deleteFields(List deletedFields) { + if (deletedFields.isEmpty) { + return; + } + final List newFields = fieldInfos; + final Map deletedFieldMap = { + for (var fieldOrder in deletedFields) fieldOrder.fieldId: fieldOrder + }; + + newFields.retainWhere((field) => (deletedFieldMap[field.id] == null)); + _fieldNotifier.fieldInfos = newFields; + } + + Future attachFieldSettings(FieldInfo fieldInfo) async { + return _fieldSettingsBackendSvc + .getFieldSettings(fieldInfo.id) + .then((result) { + final fieldSettings = result.fold( + (fieldSettings) => fieldSettings, + (err) { + return null; + }, + ); + if (fieldSettings == null) { + return fieldInfo; + } + final updatedFieldInfo = + fieldInfo.copyWith(fieldSettings: fieldSettings); + + return updatedFieldInfo; + }); + } + + Future insertFields(List insertedFields) async { + if (insertedFields.isEmpty) { + return; + } + final List newFieldInfos = fieldInfos; + for (final indexField in insertedFields) { + final initial = FieldInfo.initial(indexField.field_1); + final fieldInfo = await attachFieldSettings(initial); + if (newFieldInfos.length > indexField.index) { + newFieldInfos.insert(indexField.index, fieldInfo); + } else { + newFieldInfos.add(fieldInfo); + } + } + _fieldNotifier.fieldInfos = newFieldInfos; + } + + List updateFields(List updatedFieldPBs) { + if (updatedFieldPBs.isEmpty) { + return []; + } + + final List newFields = fieldInfos; + final List updatedFields = []; + for (final updatedFieldPB in updatedFieldPBs) { + final index = + newFields.indexWhere((field) => field.id == updatedFieldPB.id); + if (index != -1) { + newFields.removeAt(index); + final fieldInfo = FieldInfo.initial(updatedFieldPB); + newFields.insert(index, fieldInfo); + updatedFields.add(fieldInfo); + } + } + + if (updatedFields.isNotEmpty) { + _fieldNotifier.fieldInfos = newFields; + } + return updatedFields; + } + + // Listen on field's changes _fieldListener.start( onFieldsChanged: (result) { result.fold( @@ -407,10 +449,10 @@ class FieldController { if (_isDisposed) { return; } - _deleteFields(changeset.deletedFields); - _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) { listener(updatedFields); } @@ -421,31 +463,70 @@ class FieldController { ); } + /// Listen for field setting changes in the backend. + void _listenOnFieldSettingsChanged() { + FieldInfo updateFieldSettings(FieldSettingsPB updatedFieldSettings) { + final List newFields = fieldInfos; + FieldInfo updatedField = newFields[0]; + + final index = newFields + .indexWhere((field) => field.id == updatedFieldSettings.fieldId); + if (index != -1) { + newFields[index] = + newFields[index].copyWith(fieldSettings: updatedFieldSettings); + updatedField = newFields[index]; + } + + _fieldNotifier.fieldInfos = newFields; + return updatedField; + } + + _fieldSettingsListener.start( + onFieldSettingsChanged: (result) { + if (_isDisposed) { + return; + } + result.fold( + (fieldSettings) { + final updatedFieldInfo = updateFieldSettings(fieldSettings); + for (final listener in _updatedFieldCallbacks.values) { + listener([updatedFieldInfo]); + } + }, + (err) => Log.error(err), + ); + }, + ); + } + + /// Updates sort, filter, group and field info from `DatabaseViewSettingPB` void _updateSetting(DatabaseViewSettingPB setting) { _groupConfigurationByFieldId.clear(); for (final configuration in setting.groupSettings.items) { _groupConfigurationByFieldId[configuration.fieldId] = configuration; } - for (final filter in setting.filters.items) { - _filterPBByFieldId[filter.fieldId] = filter; - } + _filterNotifier?.filters = _filterInfoListFromPBs(setting.filters.items); - for (final sort in setting.sorts.items) { - _sortPBByFieldId[sort.fieldId] = sort; - } + _sortNotifier?.sorts = _sortInfoListFromPBs(setting.sorts.items); + + _fieldSettings.clear(); + _fieldSettings.addAll(setting.fieldSettings.items); _updateFieldInfos(); } + /// Attach sort, filter, group information and field settings to `FieldInfo` void _updateFieldInfos() { final List newFieldInfos = []; for (final field in _fieldNotifier.fieldInfos) { newFieldInfos.add( field.copyWith( + fieldSettings: _fieldSettings + .firstWhereOrNull((setting) => setting.fieldId == field.id), isGroupField: _groupConfigurationByFieldId[field.id] != null, - hasFilter: _filterPBByFieldId[field.id] != null, - hasSort: _sortPBByFieldId[field.id] != null, + hasFilter: getFilterByFieldId(field.id) != null, + hasSort: getSortByFieldId(field.id) != null, ), ); } @@ -453,52 +534,27 @@ class FieldController { _fieldNotifier.fieldInfos = newFieldInfos; } - Future dispose() async { - if (_isDisposed) { - Log.warn('FieldController is already disposed'); - return; - } - _isDisposed = true; - await _fieldListener.stop(); - await _filtersListener.stop(); - await _settingListener.stop(); - await _sortsListener.stop(); - - for (final callback in _fieldCallbacks.values) { - _fieldNotifier.removeListener(callback); - } - _fieldNotifier.dispose(); - - for (final callback in _filterCallbacks.values) { - _filterNotifier?.removeListener(callback); - } - for (final callback in _sortCallbacks.values) { - _sortNotifier?.removeListener(callback); - } - - _filterNotifier?.dispose(); - _filterNotifier = null; - - _sortNotifier?.dispose(); - _sortNotifier = null; - } - + /// Load all of the fields. This is required when opening the database Future> loadFields({ required List fieldIds, }) async { final result = await _databaseViewBackendSvc.getFields(fieldIds: fieldIds); return Future( () => result.fold( - (newFields) { + (newFields) async { if (_isDisposed) { return left(unit); } _fieldNotifier.fieldInfos = newFields.map((field) => FieldInfo.initial(field)).toList(); - _loadFilters(); - _loadSorts(); + Future.wait([ + _loadFilters(), + _loadSorts(), + _loadAllFieldSettings(), + ]); _updateFieldInfos(); + return left(unit); }, (err) => right(err), @@ -506,24 +562,12 @@ class FieldController { ); } + /// Load all the filters from the backend. Required by `loadFields` Future> _loadFilters() async { return _filterBackendSvc.getAllFilters().then((result) { return result.fold( (filterPBs) { - final List filters = []; - for (final filterPB in filterPBs) { - final fieldInfo = _findFieldInfo( - fieldInfos: fieldInfos, - fieldId: filterPB.fieldId, - fieldType: filterPB.fieldType, - ); - if (fieldInfo != null) { - final filterInfo = FilterInfo(viewId, filterPB, fieldInfo); - filters.add(filterInfo); - } - } - - _filterNotifier?.filters = filters; + _filterNotifier?.filters = _filterInfoListFromPBs(filterPBs); return left(unit); }, (err) => right(err), @@ -531,26 +575,12 @@ class FieldController { }); } + /// Load all the sorts from the backend. Required by `loadFields` Future> _loadSorts() async { return _sortBackendSvc.getAllSorts().then((result) { return result.fold( (sortPBs) { - final List sortInfos = []; - for (final sortPB in sortPBs) { - final fieldInfo = _findFieldInfo( - fieldInfos: fieldInfos, - fieldId: sortPB.fieldId, - fieldType: sortPB.fieldType, - ); - - if (fieldInfo != null) { - final sortInfo = SortInfo(sortPB: sortPB, fieldInfo: fieldInfo); - sortInfos.add(sortInfo); - } - } - - _updateFieldInfos(); - _sortNotifier?.sorts = sortInfos; + _sortNotifier?.sorts = _sortInfoListFromPBs(sortPBs); return left(unit); }, (err) => right(err), @@ -558,6 +588,56 @@ class FieldController { }); } + /// Load all the field settings from the backend. Required by `loadFields` + Future> _loadAllFieldSettings() async { + return _fieldSettingsBackendSvc.getAllFieldSettings().then((result) { + return result.fold( + (fieldSettingsList) { + _fieldSettings.clear(); + _fieldSettings.addAll(fieldSettingsList); + return left(unit); + }, + (err) => right(err), + ); + }); + } + + /// Attach corresponding `FieldInfo`s to the `FilterPB`s + List _filterInfoListFromPBs(List filterPBs) { + FilterInfo? getFilterInfo(FilterPB filterPB) { + final fieldInfo = _findFieldInfo( + fieldInfos: fieldInfos, + fieldId: filterPB.fieldId, + fieldType: filterPB.fieldType, + ); + return fieldInfo != null ? FilterInfo(viewId, filterPB, fieldInfo) : null; + } + + return filterPBs + .map((filterPB) => getFilterInfo(filterPB)) + .whereType() + .toList(); + } + + /// Attach corresponding `FieldInfo`s to the `SortPB`s + List _sortInfoListFromPBs(List sortPBs) { + SortInfo? getSortInfo(SortPB sortPB) { + final fieldInfo = _findFieldInfo( + fieldInfos: fieldInfos, + fieldId: sortPB.fieldId, + fieldType: sortPB.fieldType, + ); + return fieldInfo != null + ? SortInfo(sortPB: sortPB, fieldInfo: fieldInfo) + : null; + } + + return sortPBs + .map((sortPB) => getSortInfo(sortPB)) + .whereType() + .toList(); + } + void addListener({ OnReceiveFields? onReceiveFields, OnReceiveUpdateFields? onFieldsChanged, @@ -640,57 +720,35 @@ class FieldController { } } - void _deleteFields(List deletedFields) { - if (deletedFields.isEmpty) { + /// Stop listeners, dispose notifiers and clear listener callbacks + Future dispose() async { + if (_isDisposed) { + Log.warn('FieldController is already disposed'); return; } - final List newFields = fieldInfos; - final Map deletedFieldMap = { - for (var fieldOrder in deletedFields) fieldOrder.fieldId: fieldOrder - }; + _isDisposed = true; + await _fieldListener.stop(); + await _filtersListener.stop(); + await _settingListener.stop(); + await _sortsListener.stop(); + await _fieldSettingsListener.stop(); - newFields.retainWhere((field) => (deletedFieldMap[field.id] == null)); - _fieldNotifier.fieldInfos = newFields; - } + for (final callback in _fieldCallbacks.values) { + _fieldNotifier.removeListener(callback); + } + _fieldNotifier.dispose(); - void _insertFields(List insertedFields) { - if (insertedFields.isEmpty) { - return; + for (final callback in _filterCallbacks.values) { + _filterNotifier?.removeListener(callback); } - final List newFieldInfos = fieldInfos; - for (final indexField in insertedFields) { - final fieldInfo = FieldInfo.initial(indexField.field_1); - if (newFieldInfos.length > indexField.index) { - newFieldInfos.insert(indexField.index, fieldInfo); - } else { - newFieldInfos.add(fieldInfo); - } - } - _fieldNotifier.fieldInfos = newFieldInfos; - } + _filterNotifier?.dispose(); + _filterNotifier = null; - List _updateFields(List updatedFieldPBs) { - if (updatedFieldPBs.isEmpty) { - return []; + for (final callback in _sortCallbacks.values) { + _sortNotifier?.removeListener(callback); } - - final List newFields = fieldInfos; - final List updatedFields = []; - for (final updatedFieldPB in updatedFieldPBs) { - final index = - newFields.indexWhere((field) => field.id == updatedFieldPB.id); - if (index != -1) { - newFields.removeAt(index); - final fieldInfo = FieldInfo.initial(updatedFieldPB); - newFields.insert(index, fieldInfo); - updatedFields.add(fieldInfo); - } - } - - if (updatedFields.isNotEmpty) { - _fieldNotifier.fieldInfos = newFields; - } - return updatedFields; + _sortNotifier?.dispose(); + _sortNotifier = null; } } @@ -727,12 +785,7 @@ FieldInfo? _findFieldInfo({ required String fieldId, required FieldType fieldType, }) { - final fieldIndex = fieldInfos.indexWhere((element) { - return element.id == fieldId && element.fieldType == fieldType; - }); - if (fieldIndex != -1) { - return fieldInfos[fieldIndex]; - } else { - return null; - } + return fieldInfos.firstWhereOrNull( + (element) => element.id == fieldId && element.fieldType == fieldType, + ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_info.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_info.dart index 6917a3380f..b20087b1f2 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_info.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_info.dart @@ -1,4 +1,5 @@ import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/field_settings_entities.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'field_info.freezed.dart'; @@ -8,6 +9,7 @@ class FieldInfo with _$FieldInfo { const factory FieldInfo({ required FieldPB field, + required FieldSettingsPB? fieldSettings, required bool isGroupField, required bool hasFilter, required bool hasSort, @@ -21,8 +23,11 @@ class FieldInfo with _$FieldInfo { bool get isPrimary => field.isPrimary; + FieldVisibility? get visibility => fieldSettings?.visibility; + factory FieldInfo.initial(FieldPB field) => FieldInfo( field: field, + fieldSettings: null, hasFilter: false, hasSort: false, isGroupField: false, diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/field_settings/field_settings_listener.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/field_settings/field_settings_listener.dart new file mode 100644 index 0000000000..53ec29d990 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/field_settings/field_settings_listener.dart @@ -0,0 +1,51 @@ +import 'dart:typed_data'; + +import 'package:appflowy/core/notification/grid_notification.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:dartz/dartz.dart'; +import 'package:flowy_infra/notifier.dart'; + +typedef FieldSettingsValue = Either; + +class FieldSettingsListener { + final String viewId; + PublishNotifier? _fieldSettingsNotifier = + PublishNotifier(); + DatabaseNotificationListener? _listener; + + FieldSettingsListener({required this.viewId}); + + void start({ + required void Function(FieldSettingsValue) onFieldSettingsChanged, + }) { + _fieldSettingsNotifier?.addPublishListener(onFieldSettingsChanged); + _listener = DatabaseNotificationListener( + objectId: viewId, + handler: _handler, + ); + } + + void _handler( + DatabaseNotification ty, + Either result, + ) { + switch (ty) { + case DatabaseNotification.DidUpdateFieldSettings: + result.fold( + (payload) => _fieldSettingsNotifier?.value = + left(FieldSettingsPB.fromBuffer(payload)), + (error) => _fieldSettingsNotifier?.value = right(error), + ); + break; + default: + break; + } + } + + Future stop() async { + await _listener?.stop(); + _fieldSettingsNotifier?.dispose(); + _fieldSettingsNotifier = null; + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/field_settings/field_settings_service.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/field_settings/field_settings_service.dart new file mode 100644 index 0000000000..3352ae2a62 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/field_settings/field_settings_service.dart @@ -0,0 +1,54 @@ +import 'package:appflowy_backend/dispatch/dispatch.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/field_settings_entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:dartz/dartz.dart'; + +class FieldSettingsBackendService { + final String viewId; + FieldSettingsBackendService({required this.viewId}); + + Future> getFieldSettings( + String fieldId, + ) { + final id = FieldIdPB(fieldId: fieldId); + final ids = RepeatedFieldIdPB()..items.add(id); + final payload = FieldIdsPB() + ..viewId = viewId + ..fieldIds = ids; + + return DatabaseEventGetFieldSettings(payload).send().then((result) { + return result.fold( + (fieldSettings) => left(fieldSettings.items.first), + (r) => right(r), + ); + }); + } + + Future, FlowyError>> getAllFieldSettings() { + final payload = DatabaseViewIdPB()..value = viewId; + + return DatabaseEventGetAllFieldSettings(payload).send().then((result) { + return result.fold( + (fieldSettings) => left(fieldSettings.items), + (r) => right(r), + ); + }); + } + + Future> updateFieldSettings({ + required String fieldId, + FieldVisibility? fieldVisibility, + }) { + final FieldSettingsChangesetPB payload = FieldSettingsChangesetPB.create() + ..viewId = viewId + ..fieldId = fieldId; + + if (fieldVisibility != null) { + payload.visibility = fieldVisibility; + } + + return DatabaseEventUpdateFieldSettings(payload).send(); + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/row/row_cache.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/row/row_cache.dart index 31a9bc37eb..005252cf71 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/row/row_cache.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/row/row_cache.dart @@ -74,6 +74,7 @@ class RowCache { final rowInfo = buildGridRow(row); _rowList.add(rowInfo); } + _changedNotifier.receive(const ChangedReason.setInitialRows()); } Future dispose() async { @@ -281,6 +282,7 @@ class RowChangesetNotifier extends ChangeNotifier { initial: (_) {}, reorderRows: (_) => notifyListeners(), reorderSingleRow: (_) => notifyListeners(), + setInitialRows: (_) => notifyListeners(), ); } } @@ -313,6 +315,7 @@ class ChangedReason with _$ChangedReason { ReorderSingleRowPB reorderRow, RowInfo rowInfo, ) = _ReorderSingleRow; + const factory ChangedReason.setInitialRows() = _SetInitialRows; } class InsertedIndex { diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/filter_info.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/filter_info.dart index 1059abffed..dbd2e706dc 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/filter_info.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/filter_info.dart @@ -22,6 +22,10 @@ class FilterInfo { ); } + String get filterId => filter.id; + + String get fieldId => filter.fieldId; + DateFilterPB? dateFilter() { if (![ FieldType.DateTime, diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_info.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_info.dart index 21185b3014..4d629e347e 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_info.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_info.dart @@ -8,4 +8,6 @@ class SortInfo { SortInfo({required this.sortPB, required this.fieldInfo}); String get sortId => sortPB.id; + + String get fieldId => sortPB.fieldId; } diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index abe9b5f65b..fbe294462b 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -140,7 +140,7 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "appflowy-integrate" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "anyhow", "collab", @@ -203,18 +203,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -307,7 +307,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -728,7 +728,7 @@ dependencies = [ [[package]] name = "collab" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "anyhow", "bytes", @@ -746,7 +746,7 @@ dependencies = [ [[package]] name = "collab-client-ws" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "bytes", "collab-sync", @@ -764,7 +764,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "anyhow", "async-trait", @@ -793,15 +793,19 @@ dependencies = [ [[package]] name = "collab-define" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ + "anyhow", + "collab", + "serde", + "serde_repr", "uuid", ] [[package]] name = "collab-derive" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "proc-macro2", "quote", @@ -813,7 +817,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "anyhow", "collab", @@ -832,7 +836,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "anyhow", "chrono", @@ -852,7 +856,7 @@ dependencies = [ [[package]] name = "collab-persistence" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "bincode", "chrono", @@ -872,7 +876,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "anyhow", "async-trait", @@ -884,7 +888,6 @@ dependencies = [ "futures-util", "parking_lot 0.12.1", "rand 0.8.5", - "rusoto_credential", "serde", "serde_json", "similar 2.2.1", @@ -901,7 +904,7 @@ dependencies = [ [[package]] name = "collab-sync" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "bytes", "collab", @@ -923,10 +926,11 @@ dependencies = [ [[package]] name = "collab-user" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "anyhow", "collab", + "collab-define", "parking_lot 0.12.1", "serde", "serde_json", @@ -1120,7 +1124,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -1184,7 +1188,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -1195,7 +1199,7 @@ checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" dependencies = [ "darling_core", "quote", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -1808,6 +1812,7 @@ dependencies = [ "flowy-error", "flowy-folder-deps", "flowy-server-config", + "flowy-storage", "flowy-user-deps", "futures", "futures-util", @@ -1815,6 +1820,7 @@ dependencies = [ "hyper", "lazy_static", "lib-infra", + "mime_guess", "parking_lot 0.12.1", "postgrest", "reqwest", @@ -1824,7 +1830,9 @@ dependencies = [ "thiserror", "tokio", "tokio-retry", + "tokio-util", "tracing", + "url", "uuid", ] @@ -1855,6 +1863,18 @@ dependencies = [ "tracing", ] +[[package]] +name = "flowy-storage" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "bytes", + "reqwest", + "serde", + "serde_json", +] + [[package]] name = "flowy-task" version = "0.1.0" @@ -2038,7 +2058,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -3183,6 +3203,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -3460,7 +3490,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -3647,7 +3677,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -3825,7 +3855,7 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -3942,7 +3972,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9825a04601d60621feed79c4e6b56d65db77cdca55cef43b46b0de1096d1c282" dependencies = [ "proc-macro2", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -4121,9 +4151,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "5907a1b7c277254a8b15170f6e7c97cfa60ee7872a3217663bb81151e48184bb" dependencies = [ "proc-macro2", ] @@ -4351,6 +4381,7 @@ dependencies = [ "js-sys", "log", "mime", + "mime_guess", "native-tls", "once_cell", "percent-encoding", @@ -4363,10 +4394,12 @@ dependencies = [ "tokio", "tokio-native-tls", "tokio-rustls", + "tokio-util", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams", "web-sys", "webpki-roots", "winreg 0.10.1", @@ -4425,24 +4458,6 @@ dependencies = [ "librocksdb-sys", ] -[[package]] -name = "rusoto_credential" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee0a6c13db5aad6047b6a44ef023dbbc21a056b6dab5be3b79ce4283d5c02d05" -dependencies = [ - "async-trait", - "chrono", - "dirs-next", - "futures", - "hyper", - "serde", - "serde_json", - "shlex", - "tokio", - "zeroize", -] - [[package]] name = "rust_decimal" version = "1.30.0" @@ -4700,7 +4715,7 @@ checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -4722,7 +4737,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -4771,7 +4786,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -5082,7 +5097,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -5104,9 +5119,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.22" +version = "2.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" +checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" dependencies = [ "proc-macro2", "quote", @@ -5485,7 +5500,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -5588,7 +5603,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -5765,7 +5780,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.29", ] [[package]] @@ -5961,6 +5976,15 @@ dependencies = [ "unic-common", ] +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.13" @@ -6161,7 +6185,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.29", "wasm-bindgen-shared", ] @@ -6195,7 +6219,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.29", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6206,6 +6230,19 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +[[package]] +name = "wasm-streams" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bbae3363c08332cadccd13b67db371814cd214c2524020932f0804b8cf7c078" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" version = "0.3.64" @@ -6709,12 +6746,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "zeroize" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" - [[package]] name = "zstd-sys" version = "2.0.8+zstd.1.5.5" diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 328de68e02..f033d4b4c1 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -34,15 +34,15 @@ default = ["custom-protocol"] custom-protocol = ["tauri/custom-protocol"] [patch.crates-io] -collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } -collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } -collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } -collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } -collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } -appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } -collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } -collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } -collab-define = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } +collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } +collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } +collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } +appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } +collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } +collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } +collab-define = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } #collab = { path = "../../../../AppFlowy-Collab/collab" } #collab-folder = { path = "../../../../AppFlowy-Collab/collab-folder" } diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 1a6edb9f36..96fd4b2eec 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -120,7 +120,7 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "appflowy-integrate" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "anyhow", "collab", @@ -611,7 +611,7 @@ dependencies = [ [[package]] name = "collab" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "anyhow", "bytes", @@ -629,7 +629,7 @@ dependencies = [ [[package]] name = "collab-client-ws" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "bytes", "collab-sync", @@ -647,7 +647,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "anyhow", "async-trait", @@ -676,15 +676,19 @@ dependencies = [ [[package]] name = "collab-define" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ + "anyhow", + "collab", + "serde", + "serde_repr", "uuid", ] [[package]] name = "collab-derive" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "proc-macro2", "quote", @@ -696,7 +700,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "anyhow", "collab", @@ -715,7 +719,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "anyhow", "chrono", @@ -735,7 +739,7 @@ dependencies = [ [[package]] name = "collab-persistence" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "bincode", "chrono", @@ -755,7 +759,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "anyhow", "async-trait", @@ -767,7 +771,6 @@ dependencies = [ "futures-util", "parking_lot 0.12.1", "rand 0.8.5", - "rusoto_credential", "serde", "serde_json", "similar 2.2.1", @@ -784,7 +787,7 @@ dependencies = [ [[package]] name = "collab-sync" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "bytes", "collab", @@ -806,10 +809,11 @@ dependencies = [ [[package]] name = "collab-user" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=1b297c#1b297c2ed75aa33b964f0da546d771b00805be62" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=223011#223011a4340d0d98e7e10ca6bb19b8d622b0f568" dependencies = [ "anyhow", "collab", + "collab-define", "parking_lot 0.12.1", "serde", "serde_json", @@ -1150,27 +1154,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - [[package]] name = "dotenv" version = "0.15.0" @@ -3681,17 +3664,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "redox_users" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" -dependencies = [ - "getrandom 0.2.9", - "redox_syscall 0.2.16", - "thiserror", -] - [[package]] name = "regex" version = "1.7.3" @@ -3831,24 +3803,6 @@ dependencies = [ "librocksdb-sys", ] -[[package]] -name = "rusoto_credential" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee0a6c13db5aad6047b6a44ef023dbbc21a056b6dab5be3b79ce4283d5c02d05" -dependencies = [ - "async-trait", - "chrono", - "dirs-next", - "futures", - "hyper", - "serde", - "serde_json", - "shlex", - "tokio", - "zeroize", -] - [[package]] name = "rust_decimal" version = "1.29.1" @@ -5408,12 +5362,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "zeroize" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" - [[package]] name = "zip" version = "0.6.6" diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index a7f1f6bc2a..149d15b8b0 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -40,14 +40,14 @@ opt-level = 3 incremental = false [patch.crates-io] -collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } -collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } -collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } -collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } -appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } -collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } -collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } -collab-define = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "1b297c" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } +collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } +collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } +appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } +collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } +collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } +collab-define = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "223011" } #collab = { path = "../AppFlowy-Collab/collab" } #collab-folder = { path = "../AppFlowy-Collab/collab-folder" } @@ -57,4 +57,3 @@ collab-define = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = #appflowy-integrate = { path = "../AppFlowy-Collab/appflowy-integrate" } #collab-user = { path = "../AppFlowy-Collab/collab-user" } #collab-define = { path = "../AppFlowy-Collab/collab-define" } - diff --git a/frontend/rust-lib/flowy-database2/src/entities/field_settings_entities.rs b/frontend/rust-lib/flowy-database2/src/entities/field_settings_entities.rs index 5e70a85ffb..d7b828c444 100644 --- a/frontend/rust-lib/flowy-database2/src/entities/field_settings_entities.rs +++ b/frontend/rust-lib/flowy-database2/src/entities/field_settings_entities.rs @@ -8,7 +8,7 @@ use crate::impl_into_field_visibility; use crate::services::field_settings::{FieldSettings, FieldSettingsChangesetParams}; /// Defines the field settings for a field in a view. -#[derive(Debug, Default, Clone, ProtoBuf)] +#[derive(Debug, Default, Clone, ProtoBuf, Eq, PartialEq)] pub struct FieldSettingsPB { #[pb(index = 1)] pub field_id: String, @@ -27,7 +27,7 @@ impl From for FieldSettingsPB { } #[repr(u8)] -#[derive(Debug, Default, Clone, ProtoBuf_Enum, PartialEq)] +#[derive(Debug, Default, Clone, ProtoBuf_Enum, Eq, PartialEq)] pub enum FieldVisibility { #[default] AlwaysShown = 0, @@ -77,12 +77,18 @@ impl TryInto<(String, Vec)> for FieldIdsPB { } } -#[derive(Debug, Default, Clone, ProtoBuf)] +#[derive(Debug, Default, Clone, ProtoBuf, Eq, PartialEq)] pub struct RepeatedFieldSettingsPB { #[pb(index = 1)] pub items: Vec, } +impl std::convert::From> for RepeatedFieldSettingsPB { + fn from(items: Vec) -> Self { + Self { items } + } +} + #[derive(Debug, Default, Clone, ProtoBuf)] pub struct FieldSettingsChangesetPB { #[pb(index = 1)] diff --git a/frontend/rust-lib/flowy-database2/src/entities/setting_entities.rs b/frontend/rust-lib/flowy-database2/src/entities/setting_entities.rs index 623caa652c..4a6f3de1a2 100644 --- a/frontend/rust-lib/flowy-database2/src/entities/setting_entities.rs +++ b/frontend/rust-lib/flowy-database2/src/entities/setting_entities.rs @@ -9,8 +9,9 @@ use flowy_error::ErrorCode; use crate::entities::parser::NotEmptyStr; use crate::entities::{ CalendarLayoutSettingPB, DeleteFilterParams, DeleteFilterPayloadPB, DeleteSortParams, - DeleteSortPayloadPB, RepeatedFilterPB, RepeatedGroupSettingPB, RepeatedSortPB, - UpdateFilterParams, UpdateFilterPayloadPB, UpdateGroupPB, UpdateSortParams, UpdateSortPayloadPB, + DeleteSortPayloadPB, RepeatedFieldSettingsPB, RepeatedFilterPB, RepeatedGroupSettingPB, + RepeatedSortPB, UpdateFilterParams, UpdateFilterPayloadPB, UpdateGroupPB, UpdateSortParams, + UpdateSortPayloadPB, }; use crate::services::setting::CalendarLayoutSetting; @@ -31,6 +32,9 @@ pub struct DatabaseViewSettingPB { #[pb(index = 5)] pub sorts: RepeatedSortPB, + + #[pb(index = 6)] + pub field_settings: RepeatedFieldSettingsPB, } #[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum, EnumIter)] diff --git a/frontend/rust-lib/flowy-database2/src/event_handler.rs b/frontend/rust-lib/flowy-database2/src/event_handler.rs index b7194b6288..ce08fb6a29 100644 --- a/frontend/rust-lib/flowy-database2/src/event_handler.rs +++ b/frontend/rust-lib/flowy-database2/src/event_handler.rs @@ -901,12 +901,39 @@ pub(crate) async fn get_field_settings_handler( let manager = upgrade_manager(manager)?; let (view_id, field_ids) = data.into_inner().try_into()?; let database_editor = manager.get_database_with_view_id(&view_id).await?; + + let layout_ty = database_editor.get_layout_type(view_id.as_ref()).await; + let field_settings = database_editor - .get_field_settings(&view_id, field_ids) + .get_field_settings(&view_id, layout_ty, field_ids.clone()) .await? .into_iter() .map(FieldSettingsPB::from) - .collect::>(); + .collect(); + + data_result_ok(RepeatedFieldSettingsPB { + items: field_settings, + }) +} + +#[tracing::instrument(level = "debug", skip_all, err)] +pub(crate) async fn get_all_field_settings_handler( + data: AFPluginData, + manager: AFPluginState>, +) -> DataResult { + let manager = upgrade_manager(manager)?; + let view_id = data.into_inner(); + let database_editor = manager.get_database_with_view_id(view_id.as_ref()).await?; + + let layout_ty = database_editor.get_layout_type(view_id.as_ref()).await; + + let field_settings = database_editor + .get_all_field_settings(view_id.as_ref(), layout_ty) + .await? + .into_iter() + .map(FieldSettingsPB::from) + .collect(); + data_result_ok(RepeatedFieldSettingsPB { items: field_settings, }) diff --git a/frontend/rust-lib/flowy-database2/src/event_map.rs b/frontend/rust-lib/flowy-database2/src/event_map.rs index c9c49d6633..026d16a8db 100644 --- a/frontend/rust-lib/flowy-database2/src/event_map.rs +++ b/frontend/rust-lib/flowy-database2/src/event_map.rs @@ -77,6 +77,7 @@ pub fn init(database_manager: Weak) -> AFPlugin { .event(DatabaseEvent::GetDatabaseSnapshots, get_snapshots_handler) // Field settings .event(DatabaseEvent::GetFieldSettings, get_field_settings_handler) + .event(DatabaseEvent::GetAllFieldSettings, get_all_field_settings_handler) .event(DatabaseEvent::UpdateFieldSettings, update_field_settings_handler) } @@ -324,7 +325,10 @@ pub enum DatabaseEvent { #[event(input = "FieldIdsPB", output = "RepeatedFieldSettingsPB")] GetFieldSettings = 160, + #[event(input = "DatabaseViewIdPB", output = "RepeatedFieldSettingsPB")] + GetAllFieldSettings = 161, + /// Updates the field settings for a field in the given view #[event(input = "FieldSettingsChangesetPB")] - UpdateFieldSettings = 161, + UpdateFieldSettings = 162, } diff --git a/frontend/rust-lib/flowy-database2/src/manager.rs b/frontend/rust-lib/flowy-database2/src/manager.rs index abae5fa5da..84355b63a9 100644 --- a/frontend/rust-lib/flowy-database2/src/manager.rs +++ b/frontend/rust-lib/flowy-database2/src/manager.rs @@ -25,9 +25,7 @@ use crate::entities::{ use crate::notification::{send_notification, DatabaseNotification}; use crate::services::database::DatabaseEditor; use crate::services::database_view::DatabaseLayoutDepsResolver; -use crate::services::field_settings::{ - default_field_settings_by_layout, default_field_settings_by_layout_map, -}; +use crate::services::field_settings::default_field_settings_by_layout_map; use crate::services::share::csv::{CSVFormat, CSVImporter, ImportResult}; pub trait DatabaseUser: Send + Sync { @@ -252,18 +250,15 @@ impl DatabaseManager { database_view_id: String, ) -> FlowyResult<()> { let wdb = self.get_workspace_database().await?; - let mut params = CreateViewParams::new( - database_id.clone(), - database_view_id, - name, - layout, - default_field_settings_by_layout(layout), - ); + let mut params = CreateViewParams::new(database_id.clone(), database_view_id, name, layout); if let Some(database) = wdb.get_database(&database_id).await { let (field, layout_setting) = DatabaseLayoutDepsResolver::new(database, layout) .resolve_deps_when_create_database_linked_view(); if let Some(field) = field { - params = params.with_deps_fields(vec![field], default_field_settings_by_layout_map()) + params = params.with_deps_fields( + vec![field.clone()], + vec![default_field_settings_by_layout_map()], + ); } if let Some(layout_setting) = layout_setting { params = params.with_layout_setting(layout_setting); diff --git a/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs b/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs index 9d7374752d..fd819fb306 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs @@ -28,8 +28,7 @@ use crate::services::field::{ SelectOptionIds, TypeOptionCellDataHandler, TypeOptionCellExt, }; use crate::services::field_settings::{ - default_field_settings_by_layout, default_field_settings_by_layout_map, FieldSettings, - FieldSettingsChangesetParams, + default_field_settings_by_layout_map, FieldSettings, FieldSettingsChangesetParams, }; use crate::services::filter::Filter; use crate::services::group::{ @@ -109,6 +108,15 @@ impl DatabaseEditor { pub async fn close(&self) {} + pub async fn get_layout_type(&self, view_id: &str) -> DatabaseLayout { + let view = self.database_views.get_view_editor(view_id).await.ok(); + if let Some(editor) = view { + editor.v_get_layout_type().await + } else { + DatabaseLayout::default() + } + } + pub async fn update_view_layout( &self, view_id: &str, @@ -1107,18 +1115,57 @@ impl DatabaseEditor { pub async fn get_field_settings( &self, view_id: &str, + layout_ty: DatabaseLayout, field_ids: Vec, - ) -> Result, anyhow::Error> { + ) -> FlowyResult> { let view = self.database_views.get_view_editor(view_id).await?; - view.v_get_field_settings(field_ids).await + let default_field_settings = default_field_settings_by_layout_map() + .get(&layout_ty) + .unwrap() + .to_owned(); + + let found_field_settings = view.v_get_field_settings(&field_ids).await; + + let field_settings = field_ids + .into_iter() + .map(|field_id| { + if let Some(field_settings) = found_field_settings.get(&field_id) { + field_settings.to_owned() + } else { + FieldSettings::try_from_anymap(field_id, default_field_settings.clone()).unwrap() + } + }) + .collect(); + + Ok(field_settings) } pub async fn get_all_field_settings( &self, view_id: &str, - ) -> Result, anyhow::Error> { + layout_ty: DatabaseLayout, + ) -> FlowyResult> { let view = self.database_views.get_view_editor(view_id).await?; - view.v_get_all_field_settings().await + let default_field_settings = default_field_settings_by_layout_map() + .get(&layout_ty) + .unwrap() + .to_owned(); + let fields = self.get_fields(view_id, None); + + let found_field_settings = view.v_get_all_field_settings().await; + + let field_settings = fields + .into_iter() + .map(|field| { + if let Some(field_settings) = found_field_settings.get(&field.id) { + field_settings.to_owned() + } else { + FieldSettings::try_from_anymap(field.id, default_field_settings.clone()).unwrap() + } + }) + .collect(); + + Ok(field_settings) } pub async fn update_field_settings_with_changeset( @@ -1352,10 +1399,6 @@ impl DatabaseViewData for DatabaseViewDataImpl { .insert_layout_setting(view_id, layout_ty, layout_setting); } - fn get_layout_type(&self, view_id: &str) -> DatabaseLayout { - self.database.lock().views.get_database_view_layout(view_id) - } - fn update_layout_type(&self, view_id: &str, layout_type: &DatabaseLayout) { self .database @@ -1379,30 +1422,40 @@ impl DatabaseViewData for DatabaseViewDataImpl { fn get_field_settings( &self, view_id: &str, - field_ids: Vec, - ) -> Result, anyhow::Error> { + field_ids: &Vec, + ) -> HashMap { let field_settings_map = self .database .lock() - .get_field_settings(view_id, Some(field_ids)); + .get_field_settings(view_id, Some(&field_ids)); - let field_settings: Result, anyhow::Error> = field_settings_map + field_settings_map .into_iter() - .map(|(field_id, field_settings)| FieldSettings::try_from_anymap(field_id, field_settings)) - .collect(); - - field_settings + .filter_map(|(field_id, field_settings)| { + let field_settings = FieldSettings::try_from_anymap(field_id.clone(), field_settings); + if let Ok(settings) = field_settings { + Some((field_id, settings)) + } else { + None + } + }) + .collect() } - fn get_all_field_settings(&self, view_id: &str) -> Result, anyhow::Error> { + fn get_all_field_settings(&self, view_id: &str) -> HashMap { let field_settings_map = self.database.lock().get_field_settings(view_id, None); - let field_settings: Result, anyhow::Error> = field_settings_map + field_settings_map .into_iter() - .map(|(field_id, field_settings)| FieldSettings::try_from_anymap(field_id, field_settings)) - .collect(); - - field_settings + .filter_map(|(field_id, field_settings)| { + let field_settings = FieldSettings::try_from_anymap(field_id.clone(), field_settings); + if let Ok(settings) = field_settings { + Some((field_id, settings)) + } else { + None + } + }) + .collect() } fn update_field_settings( @@ -1411,32 +1464,34 @@ impl DatabaseViewData for DatabaseViewDataImpl { field_id: &str, visibility: Option, ) { - let field_settings = self - .get_field_settings(view_id, vec![field_id.to_string()]) - .ok(); + let field_settings_map = self.get_field_settings(view_id, &vec![field_id.to_string()]); - let new_field_settings = match field_settings { - Some(field_settings) => { - let mut field_settings = field_settings.first().unwrap().clone(); - field_settings.visibility = visibility.unwrap_or(field_settings.visibility); - field_settings - }, - None => { - let layout_ty = self.get_layout_for_view(view_id); - let mut field_settings = FieldSettings::try_from_anymap( - field_id.to_string(), - default_field_settings_by_layout(layout_ty), - ) - .unwrap(); - field_settings.visibility = visibility.unwrap_or(field_settings.visibility); - field_settings - }, + let new_field_settings = if let Some(field_settings) = field_settings_map.get(field_id) { + let mut field_settings = field_settings.to_owned(); + field_settings.visibility = visibility.unwrap_or(field_settings.visibility); + field_settings + } else { + let layout_ty = self.get_layout_for_view(view_id); + let mut field_settings = FieldSettings::try_from_anymap( + field_id.to_string(), + default_field_settings_by_layout_map() + .get(&layout_ty) + .unwrap() + .to_owned(), + ) + .unwrap(); + field_settings.visibility = visibility.unwrap_or(field_settings.visibility); + field_settings }; self.database.lock().update_field_settings( view_id, Some(vec![field_id.to_string()]), - new_field_settings, - ) + new_field_settings.clone(), + ); + + send_notification(view_id, DatabaseNotification::DidUpdateFieldSettings) + .payload(FieldSettingsPB::from(new_field_settings)) + .send() } } diff --git a/frontend/rust-lib/flowy-database2/src/services/database/util.rs b/frontend/rust-lib/flowy-database2/src/services/database/util.rs index 8b73556b7a..393a8f0c1a 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database/util.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database/util.rs @@ -2,8 +2,9 @@ use collab_database::views::DatabaseView; use crate::entities::{ CalendarLayoutSettingPB, DatabaseLayoutPB, DatabaseLayoutSettingPB, DatabaseViewSettingPB, - FilterPB, GroupSettingPB, SortPB, + FieldSettingsPB, FilterPB, GroupSettingPB, SortPB, }; +use crate::services::field_settings::FieldSettings; use crate::services::filter::Filter; use crate::services::group::GroupSetting; use crate::services::setting::CalendarLayoutSetting; @@ -30,6 +31,7 @@ pub(crate) fn database_view_setting_pb_from_view(view: DatabaseView) -> Database Err(_) => None, }) .collect::>(); + let group_settings = view .group_settings .into_iter() @@ -48,11 +50,20 @@ pub(crate) fn database_view_setting_pb_from_view(view: DatabaseView) -> Database }) .collect::>(); + let field_settings = view + .field_settings + .into_inner() + .into_iter() + .flat_map(|(field_id, field_settings)| FieldSettings::try_from_anymap(field_id, field_settings)) + .map(FieldSettingsPB::from) + .collect::>(); + DatabaseViewSettingPB { layout_type, filters: filters.into(), group_settings: group_settings.into(), sorts: sorts.into(), + field_settings: field_settings.into(), layout_setting, } } diff --git a/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs b/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs index f9dffa7392..4ce9de521d 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs @@ -75,6 +75,8 @@ pub trait DatabaseViewData: Send + Sync + 'static { fn get_cell_in_row(&self, field_id: &str, row_id: &RowId) -> Fut>; + /// Return the database layout type for the view with given view_id + /// The default layout type is [DatabaseLayout::Grid] fn get_layout_for_view(&self, view_id: &str) -> DatabaseLayout; fn get_group_setting(&self, view_id: &str) -> Vec; @@ -110,10 +112,6 @@ pub trait DatabaseViewData: Send + Sync + 'static { layout_setting: LayoutSetting, ); - /// Return the database layout type for the view with given view_id - /// The default layout type is [DatabaseLayout::Grid] - fn get_layout_type(&self, view_id: &str) -> DatabaseLayout; - fn update_layout_type(&self, view_id: &str, layout_type: &DatabaseLayout); /// Returns a `TaskDispatcher` used to poll a `Task` @@ -128,10 +126,10 @@ pub trait DatabaseViewData: Send + Sync + 'static { fn get_field_settings( &self, view_id: &str, - field_ids: Vec, - ) -> Result, anyhow::Error>; + field_ids: &Vec, + ) -> HashMap; - fn get_all_field_settings(&self, view_id: &str) -> Result, anyhow::Error>; + fn get_all_field_settings(&self, view_id: &str) -> HashMap; fn update_field_settings( &self, @@ -864,6 +862,10 @@ impl DatabaseViewEditor { Some(events) } + pub async fn v_get_layout_type(&self) -> DatabaseLayout { + self.delegate.get_layout_for_view(&self.view_id) + } + #[tracing::instrument(level = "trace", skip_all)] pub async fn v_update_layout_type(&self, new_layout_type: DatabaseLayout) -> FlowyResult<()> { self @@ -910,12 +912,12 @@ impl DatabaseViewEditor { pub async fn v_get_field_settings( &self, - field_ids: Vec, - ) -> Result, anyhow::Error> { + field_ids: &Vec, + ) -> HashMap { self.delegate.get_field_settings(&self.view_id, field_ids) } - pub async fn v_get_all_field_settings(&self) -> Result, anyhow::Error> { + pub async fn v_get_all_field_settings(&self) -> HashMap { self.delegate.get_all_field_settings(&self.view_id) } diff --git a/frontend/rust-lib/flowy-database2/src/services/field_settings/field_settings.rs b/frontend/rust-lib/flowy-database2/src/services/field_settings/field_settings.rs deleted file mode 100644 index bba1787794..0000000000 --- a/frontend/rust-lib/flowy-database2/src/services/field_settings/field_settings.rs +++ /dev/null @@ -1,35 +0,0 @@ -use std::collections::HashMap; - -use strum::IntoEnumIterator; - -use collab_database::views::{DatabaseLayout, FieldSettingsMap, FieldSettingsMapBuilder}; - -use crate::{entities::FieldVisibility, services::field_settings::VISIBILITY}; - -/// Creates a map of the database layout and the default field settings for fields -/// in a view of that database layout -pub fn default_field_settings_by_layout_map() -> HashMap { - let mut template = HashMap::new(); - for layout_ty in DatabaseLayout::iter() { - template.insert(layout_ty, default_field_settings_by_layout(layout_ty)); - } - - template -} - -/// Returns the default FieldSettingsMap for the given database layout -pub fn default_field_settings_by_layout(layout_ty: DatabaseLayout) -> FieldSettingsMap { - let visibility = default_visibility(layout_ty); - FieldSettingsMapBuilder::new() - .insert_i64_value(VISIBILITY, visibility.into()) - .build() -} - -/// Returns the default visibility of a field for the given database layout -pub fn default_visibility(layout_ty: DatabaseLayout) -> FieldVisibility { - match layout_ty { - DatabaseLayout::Grid => FieldVisibility::AlwaysShown, - DatabaseLayout::Board => FieldVisibility::HideWhenEmpty, - DatabaseLayout::Calendar => FieldVisibility::HideWhenEmpty, - } -} diff --git a/frontend/rust-lib/flowy-database2/src/services/field_settings/field_settings_builder.rs b/frontend/rust-lib/flowy-database2/src/services/field_settings/field_settings_builder.rs index 13b4608992..01c0a6b875 100644 --- a/frontend/rust-lib/flowy-database2/src/services/field_settings/field_settings_builder.rs +++ b/frontend/rust-lib/flowy-database2/src/services/field_settings/field_settings_builder.rs @@ -1,8 +1,16 @@ -use collab_database::views::DatabaseLayout; +use std::collections::HashMap; +use std::sync::Arc; + +use collab_database::database::MutexDatabase; +use collab_database::fields::Field; +use collab_database::views::{ + DatabaseLayout, FieldSettingsByFieldIdMap, FieldSettingsMap, FieldSettingsMapBuilder, +}; +use strum::IntoEnumIterator; use crate::entities::FieldVisibility; -use crate::services::field_settings::{default_visibility, FieldSettings}; +use crate::services::field_settings::{FieldSettings, VISIBILITY}; /// Helper struct to create a new field setting pub struct FieldSettingsBuilder { @@ -18,14 +26,6 @@ impl FieldSettingsBuilder { Self { field_settings } } - pub fn from_layout_type(field_id: &str, layout_ty: DatabaseLayout) -> Self { - let field_settings = FieldSettings { - field_id: field_id.to_string(), - visibility: default_visibility(layout_ty), - }; - Self { field_settings } - } - pub fn field_id(mut self, field_id: &str) -> Self { self.field_settings.field_id = field_id.to_string(); self @@ -40,3 +40,74 @@ impl FieldSettingsBuilder { self.field_settings } } + +pub struct DatabaseFieldSettingsMapBuilder { + pub fields: Vec, + pub database_layout: DatabaseLayout, +} + +impl DatabaseFieldSettingsMapBuilder { + pub fn new(fields: Vec, database_layout: DatabaseLayout) -> Self { + Self { + fields, + database_layout, + } + } + + pub fn from_database(database: Arc, database_layout: DatabaseLayout) -> Self { + let fields = database.lock().get_fields(None); + Self { + fields, + database_layout, + } + } + + pub fn build(self) -> FieldSettingsByFieldIdMap { + self + .fields + .into_iter() + .map(|field| { + let field_settings = field_settings_for_field(self.database_layout, &field); + (field.id, field_settings) + }) + .collect::>() + .into() + } +} + +pub fn field_settings_for_field( + database_layout: DatabaseLayout, + field: &Field, +) -> FieldSettingsMap { + let visibility = if field.is_primary { + FieldVisibility::AlwaysShown + } else { + match database_layout { + DatabaseLayout::Grid => FieldVisibility::AlwaysShown, + DatabaseLayout::Board => FieldVisibility::HideWhenEmpty, + DatabaseLayout::Calendar => FieldVisibility::HideWhenEmpty, + } + }; + + FieldSettingsBuilder::new(&field.id) + .visibility(visibility) + .build() + .into() +} + +pub fn default_field_settings_by_layout_map() -> HashMap { + let mut map = HashMap::new(); + for layout_ty in DatabaseLayout::iter() { + let visibility = match layout_ty { + DatabaseLayout::Grid => FieldVisibility::AlwaysShown, + DatabaseLayout::Board => FieldVisibility::HideWhenEmpty, + DatabaseLayout::Calendar => FieldVisibility::HideWhenEmpty, + }; + let field_settings = FieldSettingsMapBuilder::new() + .insert_i64_value(VISIBILITY, visibility.into()) + .build(); + map.insert(layout_ty, field_settings); + } + + map +} diff --git a/frontend/rust-lib/flowy-database2/src/services/field_settings/mod.rs b/frontend/rust-lib/flowy-database2/src/services/field_settings/mod.rs index 4e84cc3450..4abe6ad07c 100644 --- a/frontend/rust-lib/flowy-database2/src/services/field_settings/mod.rs +++ b/frontend/rust-lib/flowy-database2/src/services/field_settings/mod.rs @@ -1,8 +1,5 @@ pub use entities::*; -pub use field_settings::*; pub use field_settings_builder::*; mod entities; -#[allow(clippy::module_inception)] -mod field_settings; mod field_settings_builder; diff --git a/frontend/rust-lib/flowy-database2/src/services/share/csv/import.rs b/frontend/rust-lib/flowy-database2/src/services/share/csv/import.rs index 4863181123..ee16cdc94d 100644 --- a/frontend/rust-lib/flowy-database2/src/services/share/csv/import.rs +++ b/frontend/rust-lib/flowy-database2/src/services/share/csv/import.rs @@ -9,7 +9,7 @@ use flowy_error::{FlowyError, FlowyResult}; use crate::entities::FieldType; use crate::services::field::{default_type_option_data_from_type, CELL_DATA}; -use crate::services::field_settings::default_field_settings_by_layout; +use crate::services::field_settings::DatabaseFieldSettingsMapBuilder; use crate::services::share::csv::CSVFormat; #[derive(Default)] @@ -97,6 +97,9 @@ fn database_from_fields_and_rows( }) .collect::>(); + let field_settings = + DatabaseFieldSettingsMapBuilder::new(fields.clone(), DatabaseLayout::Grid).build(); + let created_rows = rows .iter() .map(|cells| { @@ -135,7 +138,7 @@ fn database_from_fields_and_rows( sorts: vec![], created_rows, fields, - field_settings: default_field_settings_by_layout(DatabaseLayout::Grid), + field_settings, } } diff --git a/frontend/rust-lib/flowy-database2/src/template.rs b/frontend/rust-lib/flowy-database2/src/template.rs index 07bfb5c4c0..4f819ac43a 100644 --- a/frontend/rust-lib/flowy-database2/src/template.rs +++ b/frontend/rust-lib/flowy-database2/src/template.rs @@ -7,7 +7,7 @@ use crate::services::cell::{insert_select_option_cell, insert_text_cell}; use crate::services::field::{ FieldBuilder, SelectOption, SelectOptionColor, SingleSelectTypeOption, }; -use crate::services::field_settings::default_field_settings_by_layout; +use crate::services::field_settings::DatabaseFieldSettingsMapBuilder; use crate::services::setting::CalendarLayoutSetting; pub fn make_default_grid(view_id: &str, name: &str) -> CreateDatabaseParams { @@ -27,6 +27,11 @@ pub fn make_default_grid(view_id: &str, name: &str) -> CreateDatabaseParams { .visibility(true) .build(); + let fields = vec![text_field, single_select, checkbox_field]; + + let field_settings = + DatabaseFieldSettingsMapBuilder::new(fields.clone(), DatabaseLayout::Grid).build(); + CreateDatabaseParams { database_id: gen_database_id(), view_id: view_id.to_string(), @@ -41,8 +46,8 @@ pub fn make_default_grid(view_id: &str, name: &str) -> CreateDatabaseParams { CreateRowParams::new(gen_row_id()), CreateRowParams::new(gen_row_id()), ], - fields: vec![text_field, single_select, checkbox_field], - field_settings: default_field_settings_by_layout(DatabaseLayout::Grid), + fields, + field_settings, } } @@ -83,6 +88,11 @@ pub fn make_default_board(view_id: &str, name: &str) -> CreateDatabaseParams { rows.push(row); } + let fields = vec![text_field, single_select]; + + let field_settings = + DatabaseFieldSettingsMapBuilder::new(fields.clone(), DatabaseLayout::Board).build(); + CreateDatabaseParams { database_id: gen_database_id(), view_id: view_id.to_string(), @@ -93,8 +103,8 @@ pub fn make_default_board(view_id: &str, name: &str) -> CreateDatabaseParams { groups: vec![], sorts: vec![], created_rows: rows, - fields: vec![text_field, single_select], - field_settings: default_field_settings_by_layout(DatabaseLayout::Board), + fields, + field_settings, } } @@ -119,6 +129,11 @@ pub fn make_default_calendar(view_id: &str, name: &str) -> CreateDatabaseParams .visibility(true) .build(); + let fields = vec![text_field, date_field, multi_select_field]; + + let field_settings = + DatabaseFieldSettingsMapBuilder::new(fields.clone(), DatabaseLayout::Calendar).build(); + let mut layout_settings = LayoutSettings::default(); layout_settings.insert( DatabaseLayout::Calendar, @@ -135,7 +150,7 @@ pub fn make_default_calendar(view_id: &str, name: &str) -> CreateDatabaseParams groups: vec![], sorts: vec![], created_rows: vec![], - fields: vec![text_field, date_field, multi_select_field], - field_settings: default_field_settings_by_layout(DatabaseLayout::Calendar), + fields, + field_settings, } } diff --git a/frontend/rust-lib/flowy-database2/tests/database/field_settings_test/script.rs b/frontend/rust-lib/flowy-database2/tests/database/field_settings_test/script.rs index 4ca25eb89f..492221184a 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/field_settings_test/script.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/field_settings_test/script.rs @@ -1,3 +1,4 @@ +use collab_database::views::DatabaseLayout; use flowy_database2::entities::FieldVisibility; use flowy_database2::services::field_settings::FieldSettingsChangesetParams; @@ -6,10 +7,12 @@ use crate::database::database_editor::DatabaseEditorTest; #[allow(clippy::enum_variant_names)] pub enum FieldSettingsScript { AssertFieldSettings { - field_id: String, + field_ids: Vec, + layout_ty: DatabaseLayout, visibility: FieldVisibility, }, AssertAllFieldSettings { + layout_ty: DatabaseLayout, visibility: FieldVisibility, }, UpdateFieldSettings { @@ -47,24 +50,27 @@ impl FieldSettingsTest { pub async fn run_script(&mut self, script: FieldSettingsScript) { match script { FieldSettingsScript::AssertFieldSettings { - field_id, + field_ids, + layout_ty, visibility, } => { let field_settings = self .editor - .get_field_settings(&self.view_id, vec![field_id]) + .get_field_settings(&self.view_id, layout_ty, field_ids) .await - .unwrap() - .first() - .unwrap() - .to_owned(); + .unwrap(); - assert_eq!(field_settings.visibility, visibility) + for field_settings in field_settings.into_iter() { + assert_eq!(field_settings.visibility, visibility) + } }, - FieldSettingsScript::AssertAllFieldSettings { visibility } => { + FieldSettingsScript::AssertAllFieldSettings { + layout_ty, + visibility, + } => { let field_settings = self .editor - .get_all_field_settings(&self.view_id) + .get_all_field_settings(&self.view_id, layout_ty) .await .unwrap(); diff --git a/frontend/rust-lib/flowy-database2/tests/database/field_settings_test/test.rs b/frontend/rust-lib/flowy-database2/tests/database/field_settings_test/test.rs index 3cd47f8b0e..749f1c9419 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/field_settings_test/test.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/field_settings_test/test.rs @@ -1,7 +1,6 @@ use collab_database::views::DatabaseLayout; use flowy_database2::entities::FieldType; use flowy_database2::entities::FieldVisibility; -use flowy_database2::services::field_settings::default_visibility; use crate::database::field_settings_test::script::FieldSettingsScript::*; use crate::database::field_settings_test::script::FieldSettingsTest; @@ -10,45 +9,87 @@ use crate::database::field_settings_test::script::FieldSettingsTest; #[tokio::test] async fn get_default_field_settings() { let mut test = FieldSettingsTest::new_grid().await; - let visibility = default_visibility(DatabaseLayout::Grid); - let scripts = vec![AssertAllFieldSettings { visibility }]; + let scripts = vec![AssertAllFieldSettings { + layout_ty: DatabaseLayout::Grid, + visibility: FieldVisibility::AlwaysShown, + }]; test.run_scripts(scripts).await; let mut test = FieldSettingsTest::new_board().await; - let visibility = default_visibility(DatabaseLayout::Board); - let scripts = vec![AssertAllFieldSettings { visibility }]; + let non_primary_field_ids: Vec = test + .get_fields() + .into_iter() + .filter(|field| !field.is_primary) + .map(|field| field.id) + .collect(); + let primary_field_id = test.get_first_field(FieldType::RichText).id; + let scripts = vec![ + AssertFieldSettings { + field_ids: non_primary_field_ids.clone(), + layout_ty: DatabaseLayout::Board, + visibility: FieldVisibility::HideWhenEmpty, + }, + AssertFieldSettings { + field_ids: vec![primary_field_id.clone()], + layout_ty: DatabaseLayout::Board, + visibility: FieldVisibility::AlwaysShown, + }, + ]; test.run_scripts(scripts).await; let mut test = FieldSettingsTest::new_calendar().await; - let visibility = default_visibility(DatabaseLayout::Calendar); - let scripts = vec![AssertAllFieldSettings { visibility }]; + let non_primary_field_ids: Vec = test + .get_fields() + .into_iter() + .filter(|field| !field.is_primary) + .map(|field| field.id) + .collect(); + let primary_field_id = test.get_first_field(FieldType::RichText).id; + let scripts = vec![ + AssertFieldSettings { + field_ids: non_primary_field_ids.clone(), + layout_ty: DatabaseLayout::Calendar, + visibility: FieldVisibility::HideWhenEmpty, + }, + AssertFieldSettings { + field_ids: vec![primary_field_id.clone()], + layout_ty: DatabaseLayout::Calendar, + visibility: FieldVisibility::AlwaysShown, + }, + ]; test.run_scripts(scripts).await; } /// Update field settings for a field #[tokio::test] async fn update_field_settings_test() { - let mut test = FieldSettingsTest::new_grid().await; - let checkbox_field = test.get_first_field(FieldType::Checkbox); - let text_field = test.get_first_field(FieldType::RichText); - let visibility = default_visibility(DatabaseLayout::Grid); - let new_visibility = FieldVisibility::AlwaysHidden; + let mut test = FieldSettingsTest::new_board().await; + let non_primary_field_ids: Vec = test + .get_fields() + .into_iter() + .filter(|field| !field.is_primary) + .map(|field| field.id) + .collect(); + let primary_field_id = test.get_first_field(FieldType::RichText).id; let scripts = vec![ - AssertAllFieldSettings { - visibility: visibility.clone(), + AssertFieldSettings { + field_ids: non_primary_field_ids, + layout_ty: DatabaseLayout::Board, + visibility: FieldVisibility::HideWhenEmpty, + }, + AssertFieldSettings { + field_ids: vec![primary_field_id.clone()], + layout_ty: DatabaseLayout::Board, + visibility: FieldVisibility::AlwaysShown, }, UpdateFieldSettings { - field_id: checkbox_field.id.clone(), - visibility: Some(new_visibility.clone()), + field_id: primary_field_id, + visibility: Some(FieldVisibility::HideWhenEmpty), }, - AssertFieldSettings { - field_id: checkbox_field.id, - visibility: new_visibility, - }, - AssertFieldSettings { - field_id: text_field.id, - visibility, + AssertAllFieldSettings { + layout_ty: DatabaseLayout::Board, + visibility: FieldVisibility::HideWhenEmpty, }, ]; test.run_scripts(scripts).await; diff --git a/frontend/rust-lib/flowy-database2/tests/database/mock_data/board_mock_data.rs b/frontend/rust-lib/flowy-database2/tests/database/mock_data/board_mock_data.rs index 10a0665a20..83cbf31130 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/mock_data/board_mock_data.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/mock_data/board_mock_data.rs @@ -1,6 +1,6 @@ use collab_database::database::{gen_database_id, gen_database_view_id, gen_row_id, DatabaseData}; use collab_database::views::{DatabaseLayout, DatabaseView}; -use flowy_database2::services::field_settings::default_field_settings_by_layout; +use flowy_database2::services::field_settings::DatabaseFieldSettingsMapBuilder; use strum::IntoEnumIterator; use flowy_database2::entities::FieldType; @@ -17,8 +17,8 @@ use crate::database::mock_data::{COMPLETED, FACEBOOK, GOOGLE, PAUSED, PLANNED, T pub fn make_test_board() -> DatabaseData { let mut fields = vec![]; let mut rows = vec![]; + // Iterate through the FieldType to create the corresponding Field. - let field_settings = default_field_settings_by_layout(DatabaseLayout::Board); for field_type in FieldType::iter() { match field_type { FieldType::RichText => { @@ -116,6 +116,9 @@ pub fn make_test_board() -> DatabaseData { } } + let field_settings = + DatabaseFieldSettingsMapBuilder::new(fields.clone(), DatabaseLayout::Board).build(); + // We have many assumptions base on the number of the rows, so do not change the number of the loop. for i in 0..5 { let mut row_builder = TestRowBuilder::new(gen_row_id(), &fields); diff --git a/frontend/rust-lib/flowy-database2/tests/database/mock_data/calendar_mock_data.rs b/frontend/rust-lib/flowy-database2/tests/database/mock_data/calendar_mock_data.rs index 0a931f42f6..41d4a86cc2 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/mock_data/calendar_mock_data.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/mock_data/calendar_mock_data.rs @@ -1,6 +1,6 @@ use collab_database::database::{gen_database_id, gen_database_view_id, gen_row_id, DatabaseData}; use collab_database::views::{DatabaseLayout, DatabaseView, LayoutSetting, LayoutSettings}; -use flowy_database2::services::field_settings::default_field_settings_by_layout; +use flowy_database2::services::field_settings::DatabaseFieldSettingsMapBuilder; use strum::IntoEnumIterator; use flowy_database2::entities::FieldType; @@ -13,7 +13,6 @@ use crate::database::database_editor::TestRowBuilder; pub fn make_test_calendar() -> DatabaseData { let mut fields = vec![]; let mut rows = vec![]; - let field_settings = default_field_settings_by_layout(DatabaseLayout::Calendar); // text let text_field = FieldBuilder::from_field_type(FieldType::RichText) @@ -32,7 +31,6 @@ pub fn make_test_calendar() -> DatabaseData { fields.push(date_field); // multi select - let type_option = MultiSelectTypeOption::default(); let multi_select_field = FieldBuilder::new(FieldType::MultiSelect, type_option) .name("Tags") @@ -42,6 +40,9 @@ pub fn make_test_calendar() -> DatabaseData { let calendar_setting: LayoutSetting = CalendarLayoutSetting::new(date_field_id).into(); + let field_settings = + DatabaseFieldSettingsMapBuilder::new(fields.clone(), DatabaseLayout::Calendar).build(); + for i in 0..5 { let mut row_builder = TestRowBuilder::new(gen_row_id(), &fields); match i { diff --git a/frontend/rust-lib/flowy-database2/tests/database/mock_data/grid_mock_data.rs b/frontend/rust-lib/flowy-database2/tests/database/mock_data/grid_mock_data.rs index 1040c84678..5852496811 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/mock_data/grid_mock_data.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/mock_data/grid_mock_data.rs @@ -1,6 +1,6 @@ use collab_database::database::{gen_database_id, gen_database_view_id, gen_row_id, DatabaseData}; use collab_database::views::{DatabaseLayout, DatabaseView}; -use flowy_database2::services::field_settings::default_field_settings_by_layout; +use flowy_database2::services::field_settings::DatabaseFieldSettingsMapBuilder; use strum::IntoEnumIterator; use flowy_database2::entities::FieldType; @@ -16,7 +16,7 @@ use crate::database::mock_data::{COMPLETED, FACEBOOK, GOOGLE, PAUSED, PLANNED, T pub fn make_test_grid() -> DatabaseData { let mut fields = vec![]; let mut rows = vec![]; - let field_settings = default_field_settings_by_layout(DatabaseLayout::Grid); + // Iterate through the FieldType to create the corresponding Field. for field_type in FieldType::iter() { match field_type { @@ -118,6 +118,9 @@ pub fn make_test_grid() -> DatabaseData { } } + let field_settings = + DatabaseFieldSettingsMapBuilder::new(fields.clone(), DatabaseLayout::Grid).build(); + for i in 0..7 { let mut row_builder = TestRowBuilder::new(gen_row_id(), &fields); match i { @@ -254,7 +257,7 @@ pub fn make_test_grid() -> DatabaseData { pub fn make_no_date_test_grid() -> DatabaseData { let mut fields = vec![]; let mut rows = vec![]; - let field_settings = default_field_settings_by_layout(DatabaseLayout::Grid); + // Iterate through the FieldType to create the corresponding Field. for field_type in FieldType::iter() { match field_type { @@ -281,6 +284,9 @@ pub fn make_no_date_test_grid() -> DatabaseData { } } + let field_settings = + DatabaseFieldSettingsMapBuilder::new(fields.clone(), DatabaseLayout::Grid).build(); + for i in 0..3 { let mut row_builder = TestRowBuilder::new(gen_row_id(), &fields); match i { diff --git a/frontend/rust-lib/flowy-user-deps/Cargo.toml b/frontend/rust-lib/flowy-user-deps/Cargo.toml index 86cb572c86..e61c66e24d 100644 --- a/frontend/rust-lib/flowy-user-deps/Cargo.toml +++ b/frontend/rust-lib/flowy-user-deps/Cargo.toml @@ -13,6 +13,6 @@ serde = { version = "1.0", features = ["derive"] } collab-define = { version = "0.1.0" } serde_json = {version = "1.0"} serde_repr = "0.1" -chrono = { version = "0.4.22", default-features = false, features = ["clock"] } +chrono = { version = "0.4.22", default-features = false, features = ["clock", "serde"] } anyhow = "1.0.71" tokio = { version = "1.26", features = ["sync"] } diff --git a/frontend/rust-lib/flowy-user/src/entities/reminder.rs b/frontend/rust-lib/flowy-user/src/entities/reminder.rs index 33248e0c47..5539c4f495 100644 --- a/frontend/rust-lib/flowy-user/src/entities/reminder.rs +++ b/frontend/rust-lib/flowy-user/src/entities/reminder.rs @@ -1,5 +1,4 @@ -use collab_user::core::Reminder; - +use appflowy_integrate::reminder::{ObjectType, Reminder}; use flowy_derive::ProtoBuf; #[derive(ProtoBuf, Default, Clone)] @@ -38,10 +37,11 @@ impl From for Reminder { id: value.id, scheduled_at: value.scheduled_at, is_ack: value.is_ack, - ty: value.ty, + ty: ObjectType::Document, title: value.title, message: value.message, - reminder_object_id: value.reminder_object_id, + meta: Default::default(), + object_id: value.reminder_object_id, } } } @@ -52,10 +52,10 @@ impl From for ReminderPB { id: value.id, scheduled_at: value.scheduled_at, is_ack: value.is_ack, - ty: value.ty, + ty: value.ty as i64, title: value.title, message: value.message, - reminder_object_id: value.reminder_object_id, + reminder_object_id: value.object_id, } } } diff --git a/frontend/rust-lib/flowy-user/src/services/user_awareness.rs b/frontend/rust-lib/flowy-user/src/services/user_awareness.rs index 0d82721a2a..1c31831dcf 100644 --- a/frontend/rust-lib/flowy-user/src/services/user_awareness.rs +++ b/frontend/rust-lib/flowy-user/src/services/user_awareness.rs @@ -1,8 +1,9 @@ use std::sync::{Arc, Weak}; +use appflowy_integrate::reminder::Reminder; use appflowy_integrate::{CollabType, RocksCollabDB}; use collab::core::collab::{CollabRawData, MutexCollab}; -use collab_user::core::{MutexUserAwareness, Reminder, UserAwareness}; +use collab_user::core::{MutexUserAwareness, UserAwareness}; use flowy_error::{ErrorCode, FlowyError, FlowyResult};