diff --git a/.gitignore b/.gitignore index ab5f64486f..c956a0ad13 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,8 @@ frontend/.vscode/* !frontend/.vscode/tasks.json !frontend/.vscode/launch.json !frontend/.vscode/extensions.json -!frontend/.vscode/*.code-snippets \ No newline at end of file +!frontend/.vscode/*.code-snippets + +# Commit the highest level pubspec.lock, but ignore the others +pubspec.lock +!frontend/app_flowy/pubspec.lock diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 0cf248e7e4..bd9c259575 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -153,31 +153,31 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (context, _) => TextCellBloc( cellContext: context, ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (context, _) => SelectOptionCellBloc( cellContext: context, ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (context, _) => NumberCellBloc( cellContext: context, ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (context, _) => DateCellBloc( cellContext: context, ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (cellData, _) => CheckboxCellBloc( service: CellService(), cellContext: cellData, diff --git a/frontend/app_flowy/lib/workspace/application/grid/block/block_service.dart b/frontend/app_flowy/lib/workspace/application/grid/block/block_cache.dart similarity index 77% rename from frontend/app_flowy/lib/workspace/application/grid/block/block_service.dart rename to frontend/app_flowy/lib/workspace/application/grid/block/block_cache.dart index 3fb734db70..caf61e64b3 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/block/block_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/block/block_cache.dart @@ -6,24 +6,25 @@ import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; import 'block_listener.dart'; -class GridBlockCacheService { +/// Read https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid for more information +class GridBlockCache { final String gridId; final GridBlock block; - late GridRowCacheService _rowCache; + late GridRowCache _rowCache; late GridBlockListener _listener; List get rows => _rowCache.rows; - GridRowCacheService get rowCache => _rowCache; + GridRowCache get rowCache => _rowCache; - GridBlockCacheService({ + GridBlockCache({ required this.gridId, required this.block, required GridFieldCache fieldCache, }) { - _rowCache = GridRowCacheService( + _rowCache = GridRowCache( gridId: gridId, block: block, - delegate: GridRowCacheDelegateImpl(fieldCache), + notifier: GridRowCacheFieldNotifierImpl(fieldCache), ); _listener = GridBlockListener(blockId: block.id); diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cache.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cache.dart deleted file mode 100644 index ccf47fddb3..0000000000 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cache.dart +++ /dev/null @@ -1,109 +0,0 @@ -part of 'cell_service.dart'; - -typedef GridCellMap = LinkedHashMap; - -class _GridCellCacheObject { - _GridCellCacheKey key; - dynamic object; - _GridCellCacheObject({ - required this.key, - required this.object, - }); -} - -class _GridCellCacheKey { - final String fieldId; - final String rowId; - _GridCellCacheKey({ - required this.fieldId, - required this.rowId, - }); -} - -abstract class GridCellCacheDelegate { - void onFieldUpdated(void Function(Field) callback); -} - -class GridCellCacheService { - final String gridId; - final GridCellCacheDelegate delegate; - - /// fieldId: {objectId: callback} - final Map>> _fieldListenerByFieldId = {}; - - /// fieldId: {cacheKey: cacheData} - final Map> _cellDataByFieldId = {}; - GridCellCacheService({ - required this.gridId, - required this.delegate, - }) { - delegate.onFieldUpdated((field) { - _cellDataByFieldId.remove(field.id); - final map = _fieldListenerByFieldId[field.id]; - if (map != null) { - for (final callbacks in map.values) { - for (final callback in callbacks) { - callback(); - } - } - } - }); - } - - void addFieldListener(_GridCellCacheKey cacheKey, VoidCallback onFieldChanged) { - var map = _fieldListenerByFieldId[cacheKey.fieldId]; - if (map == null) { - _fieldListenerByFieldId[cacheKey.fieldId] = {}; - map = _fieldListenerByFieldId[cacheKey.fieldId]; - map![cacheKey.rowId] = [onFieldChanged]; - } else { - var objects = map[cacheKey.rowId]; - if (objects == null) { - map[cacheKey.rowId] = [onFieldChanged]; - } else { - objects.add(onFieldChanged); - } - } - } - - void removeFieldListener(_GridCellCacheKey cacheKey, VoidCallback fn) { - var callbacks = _fieldListenerByFieldId[cacheKey.fieldId]?[cacheKey.rowId]; - final index = callbacks?.indexWhere((callback) => callback == fn); - if (index != null && index != -1) { - callbacks?.removeAt(index); - } - } - - void insert(T item) { - var map = _cellDataByFieldId[item.key.fieldId]; - if (map == null) { - _cellDataByFieldId[item.key.fieldId] = {}; - map = _cellDataByFieldId[item.key.fieldId]; - } - - map![item.key.rowId] = item.object; - } - - T? get(_GridCellCacheKey key) { - final map = _cellDataByFieldId[key.fieldId]; - if (map == null) { - return null; - } else { - final object = map[key.rowId]; - if (object is T) { - return object; - } else { - if (object != null) { - Log.error("Cache data type does not match the cache data type"); - } - - return null; - } - } - } - - Future dispose() async { - _fieldListenerByFieldId.clear(); - _cellDataByFieldId.clear(); - } -} diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_cache.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_cache.dart new file mode 100644 index 0000000000..1f14c7c54a --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_cache.dart @@ -0,0 +1,70 @@ +part of 'cell_service.dart'; + +typedef GridCellMap = LinkedHashMap; + +class GridCell { + dynamic object; + GridCell({ + required this.object, + }); +} + +/// Use to index the cell in the grid. +/// We use [fieldId + rowId] to identify the cell. +class GridCellCacheKey { + final String fieldId; + final String rowId; + GridCellCacheKey({ + required this.fieldId, + required this.rowId, + }); +} + +/// GridCellCache is used to cache cell data of each block. +/// We use GridCellCacheKey to index the cell in the cache. +/// Read https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid +/// for more information +class GridCellCache { + final String gridId; + + /// fieldId: {cacheKey: GridCell} + final Map> _cellDataByFieldId = {}; + GridCellCache({ + required this.gridId, + }); + + void remove(String fieldId) { + _cellDataByFieldId.remove(fieldId); + } + + void insert(GridCellCacheKey key, T value) { + var map = _cellDataByFieldId[key.fieldId]; + if (map == null) { + _cellDataByFieldId[key.fieldId] = {}; + map = _cellDataByFieldId[key.fieldId]; + } + + map![key.rowId] = value.object; + } + + T? get(GridCellCacheKey key) { + final map = _cellDataByFieldId[key.fieldId]; + if (map == null) { + return null; + } else { + final value = map[key.rowId]; + if (value is T) { + return value; + } else { + if (value != null) { + Log.error("Expected value type: $T, but receive $value"); + } + return null; + } + } + } + + Future dispose() async { + _cellDataByFieldId.clear(); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_loader.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_loader.dart index 676e3f66d0..324c65c5f5 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_loader.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_loader.dart @@ -3,58 +3,26 @@ part of 'cell_service.dart'; abstract class IGridCellDataConfig { // The cell data will reload if it receives the field's change notification. bool get reloadOnFieldChanged; - - // When the reloadOnCellChanged is true, it will load the cell data after user input. - // For example: The number cell reload the cell data that carries the format - // user input: 12 - // cell display: $12 - bool get reloadOnCellChanged; -} - -class GridCellDataConfig implements IGridCellDataConfig { - @override - final bool reloadOnCellChanged; - - @override - final bool reloadOnFieldChanged; - - const GridCellDataConfig({ - this.reloadOnCellChanged = false, - this.reloadOnFieldChanged = false, - }); -} - -abstract class IGridCellDataLoader { - Future loadData(); - - IGridCellDataConfig get config; } abstract class ICellDataParser { T? parserData(List data); } -class GridCellDataLoader extends IGridCellDataLoader { +class GridCellDataLoader { final CellService service = CellService(); - final GridCell gridCell; + final GridCellIdentifier cellId; final ICellDataParser parser; - - @override - final IGridCellDataConfig config; + final bool reloadOnFieldChanged; GridCellDataLoader({ - required this.gridCell, + required this.cellId, required this.parser, - this.config = const GridCellDataConfig(), + this.reloadOnFieldChanged = false, }); - @override Future loadData() { - final fut = service.getCell( - gridId: gridCell.gridId, - fieldId: gridCell.field.id, - rowId: gridCell.rowId, - ); + final fut = service.getCell(cellId: cellId); return fut.then( (result) => result.fold((Cell cell) { try { @@ -72,29 +40,6 @@ class GridCellDataLoader extends IGridCellDataLoader { } } -class SelectOptionCellDataLoader extends IGridCellDataLoader { - final SelectOptionService service; - final GridCell gridCell; - SelectOptionCellDataLoader({ - required this.gridCell, - }) : service = SelectOptionService(gridCell: gridCell); - @override - Future loadData() async { - return service.getOpitonContext().then((result) { - return result.fold( - (data) => data, - (err) { - Log.error(err); - return null; - }, - ); - }); - } - - @override - IGridCellDataConfig get config => const GridCellDataConfig(reloadOnFieldChanged: true); -} - class StringCellDataParser implements ICellDataParser { @override String? parserData(List data) { diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_persistence.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_persistence.dart index 2ad217e062..4959adf3ed 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_persistence.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_persistence.dart @@ -1,25 +1,22 @@ part of 'cell_service.dart'; -abstract class _GridCellDataPersistence { +/// Save the cell data to disk +/// You can extend this class to do custom operations. For example, the DateCellDataPersistence. +abstract class IGridCellDataPersistence { Future> save(D data); } -class CellDataPersistence implements _GridCellDataPersistence { - final GridCell gridCell; +class CellDataPersistence implements IGridCellDataPersistence { + final GridCellIdentifier cellId; CellDataPersistence({ - required this.gridCell, + required this.cellId, }); final CellService _cellService = CellService(); @override Future> save(String data) async { - final fut = _cellService.updateCell( - gridId: gridCell.gridId, - fieldId: gridCell.field.id, - rowId: gridCell.rowId, - data: data, - ); + final fut = _cellService.updateCell(cellId: cellId, data: data); return fut.then((result) { return result.fold( @@ -35,15 +32,15 @@ class CalendarData with _$CalendarData { const factory CalendarData({required DateTime date, String? time}) = _CalendarData; } -class DateCellDataPersistence implements _GridCellDataPersistence { - final GridCell gridCell; +class DateCellDataPersistence implements IGridCellDataPersistence { + final GridCellIdentifier cellId; DateCellDataPersistence({ - required this.gridCell, + required this.cellId, }); @override Future> save(CalendarData data) { - var payload = DateChangesetPayload.create()..cellIdentifier = _cellIdentifier(gridCell); + var payload = DateChangesetPayload.create()..cellIdentifier = _makeCellIdPayload(cellId); final date = (data.date.millisecondsSinceEpoch ~/ 1000).toString(); payload.date = date; @@ -61,9 +58,9 @@ class DateCellDataPersistence implements _GridCellDataPersistence } } -CellIdentifierPayload _cellIdentifier(GridCell gridCell) { +CellIdentifierPayload _makeCellIdPayload(GridCellIdentifier cellId) { return CellIdentifierPayload.create() - ..gridId = gridCell.gridId - ..fieldId = gridCell.field.id - ..rowId = gridCell.rowId; + ..gridId = cellId.gridId + ..fieldId = cellId.fieldId + ..rowId = cellId.rowId; } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_field_notifier.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_field_notifier.dart new file mode 100644 index 0000000000..e4c909d501 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_field_notifier.dart @@ -0,0 +1,60 @@ +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:flutter/foundation.dart'; + +import 'cell_service.dart'; + +abstract class GridFieldChangedNotifier { + void onFieldChanged(void Function(Field) callback); + void dispose(); +} + +/// Grid's cell helper wrapper that enables each cell will get notified when the corresponding field was changed. +/// You Register an onFieldChanged callback to listen to the cell changes, and unregister if you don't want to listen. +class GridCellFieldNotifier { + /// fieldId: {objectId: callback} + final Map>> _fieldListenerByFieldId = {}; + + GridCellFieldNotifier({required GridFieldChangedNotifier notifier}) { + notifier.onFieldChanged( + (field) { + final map = _fieldListenerByFieldId[field.id]; + if (map != null) { + for (final callbacks in map.values) { + for (final callback in callbacks) { + callback(); + } + } + } + }, + ); + } + + /// + void register(GridCellCacheKey cacheKey, VoidCallback onFieldChanged) { + var map = _fieldListenerByFieldId[cacheKey.fieldId]; + if (map == null) { + _fieldListenerByFieldId[cacheKey.fieldId] = {}; + map = _fieldListenerByFieldId[cacheKey.fieldId]; + map![cacheKey.rowId] = [onFieldChanged]; + } else { + var objects = map[cacheKey.rowId]; + if (objects == null) { + map[cacheKey.rowId] = [onFieldChanged]; + } else { + objects.add(onFieldChanged); + } + } + } + + void unregister(GridCellCacheKey cacheKey, VoidCallback fn) { + var callbacks = _fieldListenerByFieldId[cacheKey.fieldId]?[cacheKey.rowId]; + final index = callbacks?.indexWhere((callback) => callback == fn); + if (index != null && index != -1) { + callbacks?.removeAt(index); + } + } + + Future dispose() async { + _fieldListenerByFieldId.clear(); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart index bc5c683414..fab9c1a724 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:collection'; +import 'package:app_flowy/workspace/application/grid/grid_service.dart'; import 'package:dartz/dartz.dart'; import 'package:equatable/equatable.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; @@ -14,13 +15,15 @@ import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option_entities.pb.dart'; import 'package:flutter/foundation.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart'; -import 'package:app_flowy/workspace/application/grid/cell/select_option_service.dart'; import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; import 'dart:convert' show utf8; + +import '../../field/type_option/type_option_service.dart'; +import 'cell_field_notifier.dart'; part 'cell_service.freezed.dart'; part 'cell_data_loader.dart'; part 'context_builder.dart'; -part 'cache.dart'; +part 'cell_cache.dart'; part 'cell_data_persistence.dart'; // key: rowId @@ -29,44 +32,46 @@ class CellService { CellService(); Future> updateCell({ - required String gridId, - required String fieldId, - required String rowId, + required GridCellIdentifier cellId, required String data, }) { final payload = CellChangeset.create() - ..gridId = gridId - ..fieldId = fieldId - ..rowId = rowId + ..gridId = cellId.gridId + ..fieldId = cellId.fieldId + ..rowId = cellId.rowId ..content = data; return GridEventUpdateCell(payload).send(); } Future> getCell({ - required String gridId, - required String fieldId, - required String rowId, + required GridCellIdentifier cellId, }) { final payload = CellIdentifierPayload.create() - ..gridId = gridId - ..fieldId = fieldId - ..rowId = rowId; + ..gridId = cellId.gridId + ..fieldId = cellId.fieldId + ..rowId = cellId.rowId; return GridEventGetCell(payload).send(); } } +/// Id of the cell +/// We can locate the cell by using gridId + rowId + field.id. @freezed -class GridCell with _$GridCell { - const factory GridCell({ +class GridCellIdentifier with _$GridCellIdentifier { + const factory GridCellIdentifier({ required String gridId, required String rowId, required Field field, - }) = _GridCell; + }) = _GridCellIdentifier; // ignore: unused_element - const GridCell._(); + const GridCellIdentifier._(); - String cellId() { - return rowId + field.id + "${field.fieldType}"; + String get fieldId => field.id; + + FieldType get fieldType => field.fieldType; + + ValueKey key() { + return ValueKey(rowId + fieldId + "${field.fieldType}"); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart index 00264ad4b0..124835cf94 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart @@ -1,154 +1,185 @@ part of 'cell_service.dart'; -typedef GridCellContext = _GridCellContext; -typedef GridSelectOptionCellContext = _GridCellContext; -typedef GridDateCellContext = _GridCellContext; -typedef GridURLCellContext = _GridCellContext; +typedef GridCellController = IGridCellController; +typedef GridSelectOptionCellController = IGridCellController; +typedef GridDateCellController = IGridCellController; +typedef GridURLCellController = IGridCellController; -class GridCellContextBuilder { - final GridCellCacheService _cellCache; - final GridCell _gridCell; - GridCellContextBuilder({ - required GridCellCacheService cellCache, - required GridCell gridCell, +class GridCellControllerBuilder { + final GridCellIdentifier _cellId; + final GridCellCache _cellCache; + final GridFieldCache _fieldCache; + + GridCellControllerBuilder({ + required GridCellIdentifier cellId, + required GridCellCache cellCache, + required GridFieldCache fieldCache, }) : _cellCache = cellCache, - _gridCell = gridCell; + _fieldCache = fieldCache, + _cellId = cellId; - _GridCellContext build() { - switch (_gridCell.field.fieldType) { + IGridCellController build() { + final cellFieldNotifier = GridCellFieldNotifier(notifier: _GridFieldChangedNotifierImpl(_fieldCache)); + + switch (_cellId.fieldType) { case FieldType.Checkbox: final cellDataLoader = GridCellDataLoader( - gridCell: _gridCell, + cellId: _cellId, parser: StringCellDataParser(), ); - return GridCellContext( - gridCell: _gridCell, + return GridCellController( + cellId: _cellId, cellCache: _cellCache, cellDataLoader: cellDataLoader, - cellDataPersistence: CellDataPersistence(gridCell: _gridCell), + fieldNotifier: cellFieldNotifier, + cellDataPersistence: CellDataPersistence(cellId: _cellId), ); case FieldType.DateTime: final cellDataLoader = GridCellDataLoader( - gridCell: _gridCell, + cellId: _cellId, parser: DateCellDataParser(), - config: const GridCellDataConfig(reloadOnFieldChanged: true), + reloadOnFieldChanged: true, ); - return GridDateCellContext( - gridCell: _gridCell, + return GridDateCellController( + cellId: _cellId, cellCache: _cellCache, cellDataLoader: cellDataLoader, - cellDataPersistence: DateCellDataPersistence(gridCell: _gridCell), + fieldNotifier: cellFieldNotifier, + cellDataPersistence: DateCellDataPersistence(cellId: _cellId), ); case FieldType.Number: final cellDataLoader = GridCellDataLoader( - gridCell: _gridCell, + cellId: _cellId, parser: StringCellDataParser(), - config: const GridCellDataConfig(reloadOnCellChanged: true, reloadOnFieldChanged: true), ); - return GridCellContext( - gridCell: _gridCell, + return GridCellController( + cellId: _cellId, cellCache: _cellCache, cellDataLoader: cellDataLoader, - cellDataPersistence: CellDataPersistence(gridCell: _gridCell), + fieldNotifier: cellFieldNotifier, + cellDataPersistence: CellDataPersistence(cellId: _cellId), ); case FieldType.RichText: final cellDataLoader = GridCellDataLoader( - gridCell: _gridCell, + cellId: _cellId, parser: StringCellDataParser(), ); - return GridCellContext( - gridCell: _gridCell, + return GridCellController( + cellId: _cellId, cellCache: _cellCache, cellDataLoader: cellDataLoader, - cellDataPersistence: CellDataPersistence(gridCell: _gridCell), + fieldNotifier: cellFieldNotifier, + cellDataPersistence: CellDataPersistence(cellId: _cellId), ); case FieldType.MultiSelect: case FieldType.SingleSelect: final cellDataLoader = GridCellDataLoader( - gridCell: _gridCell, + cellId: _cellId, parser: SelectOptionCellDataParser(), - config: const GridCellDataConfig(reloadOnFieldChanged: true), + reloadOnFieldChanged: true, ); - return GridSelectOptionCellContext( - gridCell: _gridCell, + return GridSelectOptionCellController( + cellId: _cellId, cellCache: _cellCache, cellDataLoader: cellDataLoader, - cellDataPersistence: CellDataPersistence(gridCell: _gridCell), + fieldNotifier: cellFieldNotifier, + cellDataPersistence: CellDataPersistence(cellId: _cellId), ); case FieldType.URL: final cellDataLoader = GridCellDataLoader( - gridCell: _gridCell, + cellId: _cellId, parser: URLCellDataParser(), ); - return GridURLCellContext( - gridCell: _gridCell, + return GridURLCellController( + cellId: _cellId, cellCache: _cellCache, cellDataLoader: cellDataLoader, - cellDataPersistence: CellDataPersistence(gridCell: _gridCell), + fieldNotifier: cellFieldNotifier, + cellDataPersistence: CellDataPersistence(cellId: _cellId), ); } throw UnimplementedError; } } -// T: the type of the CellData -// D: the type of the data that will be save to disk +/// IGridCellController is used to manipulate the cell and receive notifications. +/// * Read/Write cell data +/// * Listen on field/cell notifications. +/// +/// Generic T represents the type of the cell data. +/// Generic D represents the type of data that will be saved to the disk +/// // ignore: must_be_immutable -class _GridCellContext extends Equatable { - final GridCell gridCell; - final GridCellCacheService cellCache; - final _GridCellCacheKey _cacheKey; - final IGridCellDataLoader cellDataLoader; - final _GridCellDataPersistence cellDataPersistence; +class IGridCellController extends Equatable { + final GridCellIdentifier cellId; + final GridCellCache _cellsCache; + final GridCellCacheKey _cacheKey; final FieldService _fieldService; + final GridCellFieldNotifier _fieldNotifier; + final GridCellDataLoader _cellDataLoader; + final IGridCellDataPersistence _cellDataPersistence; late final CellListener _cellListener; - late final ValueNotifier? _cellDataNotifier; + ValueNotifier? _cellDataNotifier; + bool isListening = false; VoidCallback? _onFieldChangedFn; Timer? _loadDataOperation; Timer? _saveDataOperation; + bool _isDispose = false; - _GridCellContext({ - required this.gridCell, - required this.cellCache, - required this.cellDataLoader, - required this.cellDataPersistence, - }) : _fieldService = FieldService(gridId: gridCell.gridId, fieldId: gridCell.field.id), - _cacheKey = _GridCellCacheKey(rowId: gridCell.rowId, fieldId: gridCell.field.id); + IGridCellController({ + required this.cellId, + required GridCellCache cellCache, + required GridCellFieldNotifier fieldNotifier, + required GridCellDataLoader cellDataLoader, + required IGridCellDataPersistence cellDataPersistence, + }) : _cellsCache = cellCache, + _cellDataLoader = cellDataLoader, + _cellDataPersistence = cellDataPersistence, + _fieldNotifier = fieldNotifier, + _fieldService = FieldService(gridId: cellId.gridId, fieldId: cellId.field.id), + _cacheKey = GridCellCacheKey(rowId: cellId.rowId, fieldId: cellId.field.id); - _GridCellContext clone() { - return _GridCellContext( - gridCell: gridCell, - cellDataLoader: cellDataLoader, - cellCache: cellCache, - cellDataPersistence: cellDataPersistence); + IGridCellController clone() { + return IGridCellController( + cellId: cellId, + cellDataLoader: _cellDataLoader, + cellCache: _cellsCache, + fieldNotifier: _fieldNotifier, + cellDataPersistence: _cellDataPersistence); } - String get gridId => gridCell.gridId; + String get gridId => cellId.gridId; - String get rowId => gridCell.rowId; + String get rowId => cellId.rowId; - String get cellId => gridCell.rowId + gridCell.field.id; + String get fieldId => cellId.field.id; - String get fieldId => gridCell.field.id; + Field get field => cellId.field; - Field get field => gridCell.field; + FieldType get fieldType => cellId.field.fieldType; - FieldType get fieldType => gridCell.field.fieldType; - - VoidCallback? startListening({required void Function(T?) onCellChanged}) { + VoidCallback? startListening({required void Function(T?) onCellChanged, VoidCallback? onCellFieldChanged}) { if (isListening) { Log.error("Already started. It seems like you should call clone first"); return null; } - isListening = true; - _cellDataNotifier = ValueNotifier(cellCache.get(_cacheKey)); - _cellListener = CellListener(rowId: gridCell.rowId, fieldId: gridCell.field.id); + + /// The cell data will be changed by two reasons: + /// 1. User edit the cell + /// 2. User edit the field + /// For example: The number cell reload the cell data that carries the format + /// user input: 12 + /// cell display: $12 + _cellDataNotifier = ValueNotifier(_cellsCache.get(_cacheKey)); + _cellListener = CellListener(rowId: cellId.rowId, fieldId: cellId.field.id); + + /// 1.Listen on user edit event and load the new cell data if needed. _cellListener.start(onCellChanged: (result) { result.fold( (_) => _loadData(), @@ -156,22 +187,24 @@ class _GridCellContext extends Equatable { ); }); - if (cellDataLoader.config.reloadOnFieldChanged) { - _onFieldChangedFn = () { - _loadData(); - }; - cellCache.addFieldListener(_cacheKey, _onFieldChangedFn!); - } + /// 2.Listen on the field event and load the cell data if needed. + _onFieldChangedFn = () { + if (onCellFieldChanged != null) { + onCellFieldChanged(); + } - onCellChangedFn() { - onCellChanged(_cellDataNotifier?.value); - - if (cellDataLoader.config.reloadOnCellChanged) { + if (_cellDataLoader.reloadOnFieldChanged) { _loadData(); } - } + }; + _fieldNotifier.register(_cacheKey, _onFieldChangedFn!); + + /// Notify the listener, the cell data was changed. + onCellChangedFn() => onCellChanged(_cellDataNotifier?.value); _cellDataNotifier?.addListener(onCellChangedFn); + + // Return the function pointer that can be used when calling removeListener. return onCellChangedFn; } @@ -179,29 +212,45 @@ class _GridCellContext extends Equatable { _cellDataNotifier?.removeListener(fn); } - T? getCellData({bool loadIfNoCache = true}) { - final data = cellCache.get(_cacheKey); - if (data == null && loadIfNoCache) { + /// Return the cell data. + /// The cell data will be read from the Cache first, and load from disk if it does not exist. + /// You can set [loadIfNotExist] to false (default is true) to disable loading the cell data. + T? getCellData({bool loadIfNotExist = true}) { + final data = _cellsCache.get(_cacheKey); + if (data == null && loadIfNotExist) { _loadData(); } return data; } - Future> getTypeOptionData() { - return _fieldService.getFieldTypeOptionData(fieldType: fieldType); + /// Return the FieldTypeOptionData that can be parsed into corresponding class using the [parser]. + /// [PD] is the type that the parser return. + Future> getFieldTypeOption(P parser) { + return _fieldService.getFieldTypeOptionData(fieldType: fieldType).then((result) { + return result.fold( + (data) => parser.fromBuffer(data.typeOptionData), + (err) => right(err), + ); + }); } + /// Save the cell data to disk + /// You can set [dedeplicate] to true (default is false) to reduce the save operation. + /// It's useful when you call this method when user editing the [TextField]. + /// The default debounce interval is 300 milliseconds. void saveCellData(D data, {bool deduplicate = false, void Function(Option)? resultCallback}) async { if (deduplicate) { _loadDataOperation?.cancel(); - _loadDataOperation = Timer(const Duration(milliseconds: 300), () async { - final result = await cellDataPersistence.save(data); + + _saveDataOperation?.cancel(); + _saveDataOperation = Timer(const Duration(milliseconds: 300), () async { + final result = await _cellDataPersistence.save(data); if (resultCallback != null) { resultCallback(result); } }); } else { - final result = await cellDataPersistence.save(data); + final result = await _cellDataPersistence.save(data); if (resultCallback != null) { resultCallback(result); } @@ -209,26 +258,59 @@ class _GridCellContext extends Equatable { } void _loadData() { + _saveDataOperation?.cancel(); + _loadDataOperation?.cancel(); _loadDataOperation = Timer(const Duration(milliseconds: 10), () { - cellDataLoader.loadData().then((data) { + _cellDataLoader.loadData().then((data) { _cellDataNotifier?.value = data; - cellCache.insert(_GridCellCacheObject(key: _cacheKey, object: data)); + _cellsCache.insert(_cacheKey, GridCell(object: data)); }); }); } void dispose() { + if (_isDispose) { + Log.error("$this should only dispose once"); + return; + } + _isDispose = true; _cellListener.stop(); _loadDataOperation?.cancel(); _saveDataOperation?.cancel(); + _cellDataNotifier = null; if (_onFieldChangedFn != null) { - cellCache.removeFieldListener(_cacheKey, _onFieldChangedFn!); + _fieldNotifier.unregister(_cacheKey, _onFieldChangedFn!); _onFieldChangedFn = null; } } @override - List get props => [cellCache.get(_cacheKey) ?? "", cellId]; + List get props => [_cellsCache.get(_cacheKey) ?? "", cellId.rowId + cellId.field.id]; +} + +class _GridFieldChangedNotifierImpl extends GridFieldChangedNotifier { + final GridFieldCache _cache; + FieldChangesetCallback? _onChangesetFn; + + _GridFieldChangedNotifierImpl(GridFieldCache cache) : _cache = cache; + + @override + void dispose() { + if (_onChangesetFn != null) { + _cache.removeListener(onChangsetListener: _onChangesetFn!); + _onChangesetFn = null; + } + } + + @override + void onFieldChanged(void Function(Field p1) callback) { + _onChangesetFn = (GridFieldChangeset changeset) { + for (final updatedField in changeset.updatedFields) { + callback(updatedField); + } + }; + _cache.addListener(onChangeset: _onChangesetFn); + } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/checkbox_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/checkbox_cell_bloc.dart index b8e2b13bbc..041e687c9b 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/checkbox_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/checkbox_cell_bloc.dart @@ -6,7 +6,7 @@ import 'cell_service/cell_service.dart'; part 'checkbox_cell_bloc.freezed.dart'; class CheckboxCellBloc extends Bloc { - final GridCellContext cellContext; + final GridCellController cellContext; void Function()? _onCellChangedFn; CheckboxCellBloc({ @@ -67,7 +67,7 @@ class CheckboxCellState with _$CheckboxCellState { required bool isSelected, }) = _CheckboxCellState; - factory CheckboxCellState.initial(GridCellContext context) { + factory CheckboxCellState.initial(GridCellController context) { return CheckboxCellState(isSelected: _isSelected(context.getCellData())); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart index c5cfe397a3..77a7c7f066 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart @@ -17,7 +17,7 @@ import 'package:fixnum/fixnum.dart' as $fixnum; part 'date_cal_bloc.freezed.dart'; class DateCalBloc extends Bloc { - final GridDateCellContext cellContext; + final GridDateCellController cellContext; void Function()? _onCellChangedFn; DateCalBloc({ diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/date_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/date_cell_bloc.dart index 7c03354134..d42769549a 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/date_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/date_cell_bloc.dart @@ -7,7 +7,7 @@ import 'cell_service/cell_service.dart'; part 'date_cell_bloc.freezed.dart'; class DateCellBloc extends Bloc { - final GridDateCellContext cellContext; + final GridDateCellController cellContext; void Function()? _onCellChangedFn; DateCellBloc({required this.cellContext}) : super(DateCellState.initial(cellContext)) { @@ -60,7 +60,7 @@ class DateCellState with _$DateCellState { required Field field, }) = _DateCellState; - factory DateCellState.initial(GridDateCellContext context) { + factory DateCellState.initial(GridDateCellController context) { final cellData = context.getCellData(); return DateCellState( diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/number_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/number_cell_bloc.dart index adcfee71e6..65eec13e6c 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/number_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/number_cell_bloc.dart @@ -8,7 +8,7 @@ import 'cell_service/cell_service.dart'; part 'number_cell_bloc.freezed.dart'; class NumberCellBloc extends Bloc { - final GridCellContext cellContext; + final GridCellController cellContext; void Function()? _onCellChangedFn; NumberCellBloc({ @@ -72,7 +72,7 @@ class NumberCellState with _$NumberCellState { required Either content, }) = _NumberCellState; - factory NumberCellState.initial(GridCellContext context) { + factory NumberCellState.initial(GridCellController context) { final cellContent = context.getCellData() ?? ""; return NumberCellState( content: left(cellContent), diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_cell_bloc.dart index a6e140f707..a8a9a435e8 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_cell_bloc.dart @@ -7,7 +7,7 @@ import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_serv part 'select_option_cell_bloc.freezed.dart'; class SelectOptionCellBloc extends Bloc { - final GridSelectOptionCellContext cellContext; + final GridSelectOptionCellController cellContext; void Function()? _onCellChangedFn; SelectOptionCellBloc({ @@ -66,7 +66,7 @@ class SelectOptionCellState with _$SelectOptionCellState { required List selectedOptions, }) = _SelectOptionCellState; - factory SelectOptionCellState.initial(GridSelectOptionCellContext context) { + factory SelectOptionCellState.initial(GridSelectOptionCellController context) { final data = context.getCellData(); return SelectOptionCellState( diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_editor_bloc.dart index 9ce003b154..2daabe1a98 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_editor_bloc.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'package:app_flowy/workspace/application/grid/field/grid_listenr.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart'; @@ -13,16 +12,13 @@ part 'select_option_editor_bloc.freezed.dart'; class SelectOptionCellEditorBloc extends Bloc { final SelectOptionService _selectOptionService; - final GridSelectOptionCellContext cellContext; - late final GridFieldsListener _fieldListener; - void Function()? _onCellChangedFn; + final GridSelectOptionCellController cellController; Timer? _delayOperation; SelectOptionCellEditorBloc({ - required this.cellContext, - }) : _selectOptionService = SelectOptionService(gridCell: cellContext.gridCell), - _fieldListener = GridFieldsListener(gridId: cellContext.gridId), - super(SelectOptionEditorState.initial(cellContext)) { + required this.cellController, + }) : _selectOptionService = SelectOptionService(cellId: cellController.cellId), + super(SelectOptionEditorState.initial(cellController)) { on( (event, emit) async { await event.map( @@ -64,13 +60,8 @@ class SelectOptionCellEditorBloc extends Bloc close() async { - if (_onCellChangedFn != null) { - cellContext.removeListener(_onCellChangedFn!); - _onCellChangedFn = null; - } _delayOperation?.cancel(); - await _fieldListener.stop(); - cellContext.dispose(); + cellController.dispose(); return super.close(); } @@ -157,24 +148,16 @@ class SelectOptionCellEditorBloc extends Bloc Log.error(err), - ); - }); } } @@ -200,8 +183,8 @@ class SelectOptionEditorState with _$SelectOptionEditorState { required Option filter, }) = _SelectOptionEditorState; - factory SelectOptionEditorState.initial(GridSelectOptionCellContext context) { - final data = context.getCellData(loadIfNoCache: false); + factory SelectOptionEditorState.initial(GridSelectOptionCellController context) { + final data = context.getCellData(loadIfNotExist: false); return SelectOptionEditorState( options: data?.options ?? [], allOptions: data?.options ?? [], diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_service.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_service.dart index f3458454d1..7b6fffa310 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_service.dart @@ -7,12 +7,12 @@ import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart'; import 'cell_service/cell_service.dart'; class SelectOptionService { - final GridCell gridCell; - SelectOptionService({required this.gridCell}); + final GridCellIdentifier cellId; + SelectOptionService({required this.cellId}); - String get gridId => gridCell.gridId; - String get fieldId => gridCell.field.id; - String get rowId => gridCell.rowId; + String get gridId => cellId.gridId; + String get fieldId => cellId.field.id; + String get rowId => cellId.rowId; Future> create({required String name}) { return TypeOptionService(gridId: gridId, fieldId: fieldId).newOption(name: name).then( diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/text_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/text_cell_bloc.dart index e3b7fd2dca..783564b5fa 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/text_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/text_cell_bloc.dart @@ -6,7 +6,7 @@ import 'cell_service/cell_service.dart'; part 'text_cell_bloc.freezed.dart'; class TextCellBloc extends Bloc { - final GridCellContext cellContext; + final GridCellController cellContext; void Function()? _onCellChangedFn; TextCellBloc({ required this.cellContext, @@ -63,7 +63,7 @@ class TextCellState with _$TextCellState { required String content, }) = _TextCellState; - factory TextCellState.initial(GridCellContext context) => TextCellState( + factory TextCellState.initial(GridCellController context) => TextCellState( content: context.getCellData() ?? "", ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_bloc.dart index 6129f90f71..ed81f697f8 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_bloc.dart @@ -7,7 +7,7 @@ import 'cell_service/cell_service.dart'; part 'url_cell_bloc.freezed.dart'; class URLCellBloc extends Bloc { - final GridURLCellContext cellContext; + final GridURLCellController cellContext; void Function()? _onCellChangedFn; URLCellBloc({ required this.cellContext, @@ -67,7 +67,7 @@ class URLCellState with _$URLCellState { required String url, }) = _URLCellState; - factory URLCellState.initial(GridURLCellContext context) { + factory URLCellState.initial(GridURLCellController context) { final cellData = context.getCellData(); return URLCellState( content: cellData?.content ?? "", diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_editor_bloc.dart index dcb643d535..e69a150a38 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_editor_bloc.dart @@ -7,7 +7,7 @@ import 'cell_service/cell_service.dart'; part 'url_cell_editor_bloc.freezed.dart'; class URLCellEditorBloc extends Bloc { - final GridURLCellContext cellContext; + final GridURLCellController cellContext; void Function()? _onCellChangedFn; URLCellEditorBloc({ required this.cellContext, @@ -64,7 +64,7 @@ class URLCellEditorState with _$URLCellEditorState { required String content, }) = _URLCellEditorState; - factory URLCellEditorState.initial(GridURLCellContext context) { + factory URLCellEditorState.initial(GridURLCellController context) { final cellData = context.getCellData(); return URLCellEditorState( content: cellData?.content ?? "", diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart index 2815d5519d..19da67e557 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart @@ -1,3 +1,4 @@ +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; @@ -6,27 +7,32 @@ import 'package:dartz/dartz.dart'; part 'field_editor_bloc.freezed.dart'; class FieldEditorBloc extends Bloc { + final TypeOptionDataController dataController; + FieldEditorBloc({ required String gridId, required String fieldName, - required IFieldContextLoader fieldContextLoader, - }) : super(FieldEditorState.initial(gridId, fieldName, fieldContextLoader)) { + required IFieldTypeOptionLoader loader, + }) : dataController = TypeOptionDataController(gridId: gridId, loader: loader), + super(FieldEditorState.initial(gridId, fieldName)) { on( (event, emit) async { await event.when( initial: () async { - final fieldContext = GridFieldContext(gridId: gridId, loader: fieldContextLoader); - await fieldContext.loadData().then((result) { - result.fold( - (l) => emit(state.copyWith(fieldContext: Some(fieldContext), name: fieldContext.field.name)), - (r) => null, - ); + dataController.addFieldListener((field) { + if (!isClosed) { + add(FieldEditorEvent.didReceiveFieldChanged(field)); + } }); + await dataController.loadData(); }, updateName: (name) { - state.fieldContext.fold(() => null, (fieldContext) => fieldContext.fieldName = name); + dataController.fieldName = name; emit(state.copyWith(name: name)); }, + didReceiveFieldChanged: (Field field) { + emit(state.copyWith(field: Some(field))); + }, ); }, ); @@ -42,6 +48,7 @@ class FieldEditorBloc extends Bloc { class FieldEditorEvent with _$FieldEditorEvent { const factory FieldEditorEvent.initial() = _InitialField; const factory FieldEditorEvent.updateName(String name) = _UpdateName; + const factory FieldEditorEvent.didReceiveFieldChanged(Field field) = _DidReceiveFieldChanged; } @freezed @@ -50,13 +57,17 @@ class FieldEditorState with _$FieldEditorState { required String gridId, required String errorText, required String name, - required Option fieldContext, + required Option field, }) = _FieldEditorState; - factory FieldEditorState.initial(String gridId, String fieldName, IFieldContextLoader loader) => FieldEditorState( + factory FieldEditorState.initial( + String gridId, + String fieldName, + ) => + FieldEditorState( gridId: gridId, - fieldContext: none(), errorText: '', + field: none(), name: fieldName, ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart deleted file mode 100644 index 6310452d48..0000000000 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart +++ /dev/null @@ -1,57 +0,0 @@ -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'dart:async'; - -import 'field_service.dart'; - -part 'field_editor_pannel_bloc.freezed.dart'; - -class FieldEditorPannelBloc extends Bloc { - final GridFieldContext _fieldContext; - void Function()? _fieldListenFn; - - FieldEditorPannelBloc(GridFieldContext fieldContext) - : _fieldContext = fieldContext, - super(FieldEditorPannelState.initial(fieldContext)) { - on( - (event, emit) async { - event.when( - initial: () { - _fieldListenFn = fieldContext.addFieldListener((field) { - add(FieldEditorPannelEvent.didReceiveFieldUpdated(field)); - }); - }, - didReceiveFieldUpdated: (field) { - emit(state.copyWith(field: field)); - }, - ); - }, - ); - } - - @override - Future close() async { - if (_fieldListenFn != null) { - _fieldContext.removeFieldListener(_fieldListenFn!); - } - return super.close(); - } -} - -@freezed -class FieldEditorPannelEvent with _$FieldEditorPannelEvent { - const factory FieldEditorPannelEvent.initial() = _Initial; - const factory FieldEditorPannelEvent.didReceiveFieldUpdated(Field field) = _DidReceiveFieldUpdated; -} - -@freezed -class FieldEditorPannelState with _$FieldEditorPannelState { - const factory FieldEditorPannelState({ - required Field field, - }) = _FieldEditorPannelState; - - factory FieldEditorPannelState.initial(GridFieldContext fieldContext) => FieldEditorPannelState( - field: fieldContext.field, - ); -} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart index 99fef626c0..de5b6adcb0 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -1,4 +1,5 @@ import 'package:dartz/dartz.dart'; +import 'package:flowy_infra/notifier.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; @@ -9,6 +10,10 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:protobuf/protobuf.dart'; part 'field_service.freezed.dart'; +/// FieldService consists of lots of event functions. We define the events in the backend(Rust), +/// you can find the corresponding event implementation in event_map.rs of the corresponding crate. +/// +/// You could check out the rust-lib/flowy-grid/event_map.rs for more information. class FieldService { final String gridId; final String fieldId; @@ -137,7 +142,7 @@ class GridFieldCellContext with _$GridFieldCellContext { }) = _GridFieldCellContext; } -abstract class IFieldContextLoader { +abstract class IFieldTypeOptionLoader { String get gridId; Future> load(); @@ -151,10 +156,10 @@ abstract class IFieldContextLoader { } } -class NewFieldContextLoader extends IFieldContextLoader { +class NewFieldTypeOptionLoader extends IFieldTypeOptionLoader { @override final String gridId; - NewFieldContextLoader({ + NewFieldTypeOptionLoader({ required this.gridId, }); @@ -168,12 +173,12 @@ class NewFieldContextLoader extends IFieldContextLoader { } } -class FieldContextLoader extends IFieldContextLoader { +class FieldTypeOptionLoader extends IFieldTypeOptionLoader { @override final String gridId; final Field field; - FieldContextLoader({ + FieldTypeOptionLoader({ required this.gridId, required this.field, }); @@ -189,16 +194,16 @@ class FieldContextLoader extends IFieldContextLoader { } } -class GridFieldContext { +class TypeOptionDataController { final String gridId; - final IFieldContextLoader _loader; + final IFieldTypeOptionLoader _loader; late FieldTypeOptionData _data; - ValueNotifier? _fieldNotifier; + final PublishNotifier _fieldNotifier = PublishNotifier(); - GridFieldContext({ + TypeOptionDataController({ required this.gridId, - required IFieldContextLoader loader, + required IFieldTypeOptionLoader loader, }) : _loader = loader; Future> loadData() async { @@ -207,13 +212,7 @@ class GridFieldContext { (data) { data.freeze(); _data = data; - - if (_fieldNotifier == null) { - _fieldNotifier = ValueNotifier(data.field_2); - } else { - _fieldNotifier?.value = data.field_2; - } - + _fieldNotifier.value = data.field_2; return left(unit); }, (err) { @@ -256,9 +255,7 @@ class GridFieldContext { } }); - if (_data.field_2 != _fieldNotifier?.value) { - _fieldNotifier?.value = _data.field_2; - } + _fieldNotifier.value = _data.field_2; FieldService.insertField( gridId: gridId, @@ -288,11 +285,11 @@ class GridFieldContext { callback(field); } - _fieldNotifier?.addListener(listener); + _fieldNotifier.addListener(listener); return listener; } void removeFieldListener(void Function() listener) { - _fieldNotifier?.removeListener(listener); + _fieldNotifier.removeListener(listener); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_type_option_edit_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_type_option_edit_bloc.dart new file mode 100644 index 0000000000..b9407ac2ad --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_type_option_edit_bloc.dart @@ -0,0 +1,57 @@ +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; + +import 'field_service.dart'; + +part 'field_type_option_edit_bloc.freezed.dart'; + +class FieldTypeOptionEditBloc extends Bloc { + final TypeOptionDataController _dataController; + void Function()? _fieldListenFn; + + FieldTypeOptionEditBloc(TypeOptionDataController dataController) + : _dataController = dataController, + super(FieldTypeOptionEditState.initial(dataController)) { + on( + (event, emit) async { + event.when( + initial: () { + _fieldListenFn = dataController.addFieldListener((field) { + add(FieldTypeOptionEditEvent.didReceiveFieldUpdated(field)); + }); + }, + didReceiveFieldUpdated: (field) { + emit(state.copyWith(field: field)); + }, + ); + }, + ); + } + + @override + Future close() async { + if (_fieldListenFn != null) { + _dataController.removeFieldListener(_fieldListenFn!); + } + return super.close(); + } +} + +@freezed +class FieldTypeOptionEditEvent with _$FieldTypeOptionEditEvent { + const factory FieldTypeOptionEditEvent.initial() = _Initial; + const factory FieldTypeOptionEditEvent.didReceiveFieldUpdated(Field field) = _DidReceiveFieldUpdated; +} + +@freezed +class FieldTypeOptionEditState with _$FieldTypeOptionEditState { + const factory FieldTypeOptionEditState({ + required Field field, + }) = _FieldTypeOptionEditState; + + factory FieldTypeOptionEditState.initial(TypeOptionDataController fieldContext) => FieldTypeOptionEditState( + field: fieldContext.field, + ); +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart index 556b33d40f..00deff56e7 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart @@ -7,9 +7,9 @@ import 'dart:async'; import 'package:protobuf/protobuf.dart'; part 'date_bloc.freezed.dart'; -typedef DateTypeOptionContext = TypeOptionContext; +typedef DateTypeOptionContext = TypeOptionWidgetContext; -class DateTypeOptionDataBuilder extends TypeOptionDataBuilder { +class DateTypeOptionDataParser extends TypeOptionDataParser { @override DateTypeOption fromBuffer(List buffer) { return DateTypeOption.fromBuffer(buffer); diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_type_option.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_type_option.dart index 0a6e2de14c..0d9d75d4c7 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_type_option.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_type_option.dart @@ -7,17 +7,18 @@ import 'package:protobuf/protobuf.dart'; import 'select_option_type_option_bloc.dart'; import 'type_option_service.dart'; -class MultiSelectTypeOptionContext extends TypeOptionContext with SelectOptionTypeOptionAction { +class MultiSelectTypeOptionContext extends TypeOptionWidgetContext + with SelectOptionTypeOptionAction { final TypeOptionService service; MultiSelectTypeOptionContext({ - required MultiSelectTypeOptionDataBuilder dataBuilder, - required GridFieldContext fieldContext, + required MultiSelectTypeOptionWidgetDataParser dataBuilder, + required TypeOptionDataController dataController, }) : service = TypeOptionService( - gridId: fieldContext.gridId, - fieldId: fieldContext.field.id, + gridId: dataController.gridId, + fieldId: dataController.field.id, ), - super(dataBuilder: dataBuilder, fieldContext: fieldContext); + super(dataParser: dataBuilder, dataController: dataController); @override List Function(SelectOption) get deleteOption { @@ -70,7 +71,7 @@ class MultiSelectTypeOptionContext extends TypeOptionContext { +class MultiSelectTypeOptionWidgetDataParser extends TypeOptionDataParser { @override MultiSelectTypeOption fromBuffer(List buffer) { return MultiSelectTypeOption.fromBuffer(buffer); diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart index a708668066..804ce3ee11 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart @@ -8,9 +8,9 @@ import 'package:protobuf/protobuf.dart'; part 'number_bloc.freezed.dart'; -typedef NumberTypeOptionContext = TypeOptionContext; +typedef NumberTypeOptionContext = TypeOptionWidgetContext; -class NumberTypeOptionDataBuilder extends TypeOptionDataBuilder { +class NumberTypeOptionWidgetDataParser extends TypeOptionDataParser { @override NumberTypeOption fromBuffer(List buffer) { return NumberTypeOption.fromBuffer(buffer); diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_type_option.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_type_option.dart index c09d17f11e..b2b4581d96 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_type_option.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_type_option.dart @@ -7,18 +7,18 @@ import 'package:protobuf/protobuf.dart'; import 'select_option_type_option_bloc.dart'; import 'type_option_service.dart'; -class SingleSelectTypeOptionContext extends TypeOptionContext +class SingleSelectTypeOptionContext extends TypeOptionWidgetContext with SelectOptionTypeOptionAction { final TypeOptionService service; SingleSelectTypeOptionContext({ - required SingleSelectTypeOptionDataBuilder dataBuilder, - required GridFieldContext fieldContext, + required SingleSelectTypeOptionWidgetDataParser dataBuilder, + required TypeOptionDataController fieldContext, }) : service = TypeOptionService( gridId: fieldContext.gridId, fieldId: fieldContext.field.id, ), - super(dataBuilder: dataBuilder, fieldContext: fieldContext); + super(dataParser: dataBuilder, dataController: fieldContext); @override List Function(SelectOption) get deleteOption { @@ -71,7 +71,7 @@ class SingleSelectTypeOptionContext extends TypeOptionContext { +class SingleSelectTypeOptionWidgetDataParser extends TypeOptionDataParser { @override SingleSelectTypeOption fromBuffer(List buffer) { return SingleSelectTypeOption.fromBuffer(buffer); diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart index 3a30ef30ca..c7c86ae661 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart @@ -33,36 +33,36 @@ class TypeOptionService { } } -abstract class TypeOptionDataBuilder { +abstract class TypeOptionDataParser { T fromBuffer(List buffer); } -class TypeOptionContext { +class TypeOptionWidgetContext { T? _typeOptionObject; - final GridFieldContext _fieldContext; - final TypeOptionDataBuilder dataBuilder; + final TypeOptionDataController _dataController; + final TypeOptionDataParser dataParser; - TypeOptionContext({ - required this.dataBuilder, - required GridFieldContext fieldContext, - }) : _fieldContext = fieldContext; + TypeOptionWidgetContext({ + required this.dataParser, + required TypeOptionDataController dataController, + }) : _dataController = dataController; - String get gridId => _fieldContext.gridId; + String get gridId => _dataController.gridId; - Field get field => _fieldContext.field; + Field get field => _dataController.field; T get typeOption { if (_typeOptionObject != null) { return _typeOptionObject!; } - final T object = dataBuilder.fromBuffer(_fieldContext.typeOptionData); + final T object = dataParser.fromBuffer(_dataController.typeOptionData); _typeOptionObject = object; return object; } set typeOption(T typeOption) { - _fieldContext.typeOptionData = typeOption.writeToBuffer(); + _dataController.typeOptionData = typeOption.writeToBuffer(); _typeOptionObject = typeOption; } } @@ -77,7 +77,7 @@ class TypeOptionContext2 { final Field field; final FieldService _fieldService; T? _data; - final TypeOptionDataBuilder dataBuilder; + final TypeOptionDataParser dataBuilder; TypeOptionContext2({ required this.gridId, diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart index 49e90b6a9e..7f120cf3d8 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -7,7 +7,7 @@ import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'block/block_service.dart'; +import 'block/block_cache.dart'; import 'grid_service.dart'; import 'row/row_service.dart'; import 'dart:collection'; @@ -20,7 +20,7 @@ class GridBloc extends Bloc { final GridFieldCache fieldCache; // key: the block id - final LinkedHashMap _blocks; + final LinkedHashMap _blocks; List get rows { final List rows = []; @@ -68,8 +68,8 @@ class GridBloc extends Bloc { return super.close(); } - GridRowCacheService? getRowCache(String blockId, String rowId) { - final GridBlockCacheService? blockCache = _blocks[blockId]; + GridRowCache? getRowCache(String blockId, String rowId) { + final GridBlockCache? blockCache = _blocks[blockId]; return blockCache?.rowCache; } @@ -119,7 +119,7 @@ class GridBloc extends Bloc { return; } - final cache = GridBlockCacheService( + final cache = GridBlockCache( gridId: gridId, block: block, fieldCache: fieldCache, diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart index 391a5d13a2..4e742f9f42 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart @@ -61,13 +61,12 @@ typedef FieldsCallback = void Function(List); class GridFieldCache { final String gridId; - late final GridFieldsListener _fieldListener; + final GridFieldsListener _fieldListener; FieldsNotifier? _fieldNotifier = FieldsNotifier(); final Map _fieldsCallbackMap = {}; final Map _changesetCallbackMap = {}; - GridFieldCache({required this.gridId}) { - _fieldListener = GridFieldsListener(gridId: gridId); + GridFieldCache({required this.gridId}) : _fieldListener = GridFieldsListener(gridId: gridId) { _fieldListener.start(onFieldsChanged: (result) { result.fold( (changeset) { @@ -186,11 +185,11 @@ class GridFieldCache { } } -class GridRowCacheDelegateImpl extends GridRowCacheDelegate { +class GridRowCacheFieldNotifierImpl extends GridRowCacheFieldNotifier { final GridFieldCache _cache; FieldChangesetCallback? _onChangesetFn; FieldsCallback? _onFieldFn; - GridRowCacheDelegateImpl(GridFieldCache cache) : _cache = cache; + GridRowCacheFieldNotifierImpl(GridFieldCache cache) : _cache = cache; @override UnmodifiableListView get fields => _cache.unmodifiableFields; @@ -202,7 +201,7 @@ class GridRowCacheDelegateImpl extends GridRowCacheDelegate { } @override - void onFieldUpdated(void Function(Field) callback) { + void onFieldChanged(void Function(Field) callback) { _onChangesetFn = (GridFieldChangeset changeset) { for (final updatedField in changeset.updatedFields) { callback(updatedField); diff --git a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart index 6ea198f303..9c09a038e1 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart @@ -8,7 +8,7 @@ export 'grid_header_bloc.dart'; export 'field/field_service.dart'; export 'field/field_action_sheet_bloc.dart'; export 'field/field_editor_bloc.dart'; -export 'field/field_editor_pannel_bloc.dart'; +export 'field/field_type_option_edit_bloc.dart'; // Field Type Option export 'field/type_option/date_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_action_sheet_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_action_sheet_bloc.dart index 8754917223..7d570c9412 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_action_sheet_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_action_sheet_bloc.dart @@ -15,7 +15,7 @@ class RowActionSheetBloc extends Bloc : _rowService = RowService( gridId: rowData.gridId, blockId: rowData.blockId, - rowId: rowData.rowId, + rowId: rowData.id, ), super(RowActionSheetState.initial(rowData)) { on( diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart index 7f565b500a..69d2a95059 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart @@ -11,19 +11,19 @@ part 'row_bloc.freezed.dart'; class RowBloc extends Bloc { final RowService _rowService; - final GridRowCacheService _rowCache; + final GridRowCache _rowCache; void Function()? _rowListenFn; RowBloc({ required GridRow rowData, - required GridRowCacheService rowCache, + required GridRowCache rowCache, }) : _rowService = RowService( gridId: rowData.gridId, blockId: rowData.blockId, - rowId: rowData.rowId, + rowId: rowData.id, ), _rowCache = rowCache, - super(RowState.initial(rowData, rowCache.loadGridCells(rowData.rowId))) { + super(RowState.initial(rowData, rowCache.loadGridCells(rowData.id))) { on( (event, emit) async { await event.map( @@ -58,7 +58,7 @@ class RowBloc extends Bloc { Future _startListening() async { _rowListenFn = _rowCache.addListener( - rowId: state.rowData.rowId, + rowId: state.rowData.id, onCellUpdated: (cellDatas, reason) => add(RowEvent.didReceiveCellDatas(cellDatas, reason)), listenWhen: () => !isClosed, ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_detail_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_detail_bloc.dart index f17f0f4cb6..b75caf32cf 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_detail_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_detail_bloc.dart @@ -8,12 +8,12 @@ part 'row_detail_bloc.freezed.dart'; class RowDetailBloc extends Bloc { final GridRow rowData; - final GridRowCacheService _rowCache; + final GridRowCache _rowCache; void Function()? _rowListenFn; RowDetailBloc({ required this.rowData, - required GridRowCacheService rowCache, + required GridRowCache rowCache, }) : _rowCache = rowCache, super(RowDetailState.initial()) { on( @@ -41,14 +41,14 @@ class RowDetailBloc extends Bloc { Future _startListening() async { _rowListenFn = _rowCache.addListener( - rowId: rowData.rowId, + rowId: rowData.id, onCellUpdated: (cellDatas, reason) => add(RowDetailEvent.didReceiveCellDatas(cellDatas.values.toList())), listenWhen: () => !isClosed, ); } Future _loadCellData() async { - final cellDataMap = _rowCache.loadGridCells(rowData.rowId); + final cellDataMap = _rowCache.loadGridCells(rowData.id); if (!isClosed) { add(RowDetailEvent.didReceiveCellDatas(cellDataMap.values.toList())); } @@ -58,13 +58,13 @@ class RowDetailBloc extends Bloc { @freezed class RowDetailEvent with _$RowDetailEvent { const factory RowDetailEvent.initial() = _Initial; - const factory RowDetailEvent.didReceiveCellDatas(List gridCells) = _DidReceiveCellDatas; + const factory RowDetailEvent.didReceiveCellDatas(List gridCells) = _DidReceiveCellDatas; } @freezed class RowDetailState with _$RowDetailState { const factory RowDetailState({ - required List gridCells, + required List gridCells, }) = _RowDetailState; factory RowDetailState.initial() => RowDetailState( diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart index 78e4e6715f..7296fd51a8 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart @@ -1,5 +1,4 @@ import 'dart:collection'; - import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_service.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; @@ -15,40 +14,53 @@ part 'row_service.freezed.dart'; typedef RowUpdateCallback = void Function(); -abstract class GridRowCacheDelegate with GridCellCacheDelegate { +abstract class GridRowCacheFieldNotifier { UnmodifiableListView get fields; - void onFieldsChanged(void Function() callback); + void onFieldsChanged(VoidCallback callback); + void onFieldChanged(void Function(Field) callback); void dispose(); } -class GridRowCacheService { +/// Cache the rows in memory +/// Insert / delete / update row +/// +/// Read https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid for more information. + +class GridRowCache { final String gridId; final GridBlock block; - final _Notifier _notifier; + + /// _rows containers the current block's rows + /// Use List to reverse the order of the GridRow. List _rows = []; + + /// Use Map for faster access the raw row data. final HashMap _rowByRowId; - final GridRowCacheDelegate _delegate; - final GridCellCacheService _cellCache; - List get rows => _rows; - GridCellCacheService get cellCache => _cellCache; + final GridCellCache _cellCache; + final GridRowCacheFieldNotifier _fieldNotifier; + final _GridRowChangesetNotifier _rowChangeReasonNotifier; - GridRowCacheService({ + UnmodifiableListView get rows => UnmodifiableListView(_rows); + GridCellCache get cellCache => _cellCache; + + GridRowCache({ required this.gridId, required this.block, - required GridRowCacheDelegate delegate, - }) : _cellCache = GridCellCacheService(gridId: gridId, delegate: delegate), + required GridRowCacheFieldNotifier notifier, + }) : _cellCache = GridCellCache(gridId: gridId), _rowByRowId = HashMap(), - _notifier = _Notifier(), - _delegate = delegate { + _rowChangeReasonNotifier = _GridRowChangesetNotifier(), + _fieldNotifier = notifier { // - delegate.onFieldsChanged(() => _notifier.receive(const GridRowChangeReason.fieldDidChange())); + notifier.onFieldsChanged(() => _rowChangeReasonNotifier.receive(const GridRowChangeReason.fieldDidChange())); + notifier.onFieldChanged((field) => _cellCache.remove(field.id)); _rows = block.rowInfos.map((rowInfo) => buildGridRow(rowInfo.rowId, rowInfo.height.toDouble())).toList(); } Future dispose() async { - _delegate.dispose(); - _notifier.dispose(); + _fieldNotifier.dispose(); + _rowChangeReasonNotifier.dispose(); await _cellCache.dispose(); } @@ -72,14 +84,15 @@ class GridRowCacheService { final Map deletedRowByRowId = {for (var rowId in deletedRows) rowId: rowId}; _rows.asMap().forEach((index, row) { - if (deletedRowByRowId[row.rowId] == null) { + if (deletedRowByRowId[row.id] == null) { newRows.add(row); } else { + _rowByRowId.remove(row.id); deletedIndex.add(DeletedIndex(index: index, row: row)); } }); _rows = newRows; - _notifier.receive(GridRowChangeReason.delete(deletedIndex)); + _rowChangeReasonNotifier.receive(GridRowChangeReason.delete(deletedIndex)); } void _insertRows(List insertRows) { @@ -88,17 +101,16 @@ class GridRowCacheService { } InsertedIndexs insertIndexs = []; - final List newRows = _rows; for (final insertRow in insertRows) { final insertIndex = InsertedIndex( index: insertRow.index, rowId: insertRow.rowId, ); insertIndexs.add(insertIndex); - newRows.insert(insertRow.index, (buildGridRow(insertRow.rowId, insertRow.height.toDouble()))); + _rows.insert(insertRow.index, (buildGridRow(insertRow.rowId, insertRow.height.toDouble()))); } - _notifier.receive(GridRowChangeReason.insert(insertIndexs)); + _rowChangeReasonNotifier.receive(GridRowChangeReason.insert(insertIndexs)); } void _updateRows(List updatedRows) { @@ -107,20 +119,19 @@ class GridRowCacheService { } final UpdatedIndexs updatedIndexs = UpdatedIndexs(); - final List newRows = _rows; for (final updatedRow in updatedRows) { final rowId = updatedRow.rowId; - final index = newRows.indexWhere((row) => row.rowId == rowId); + final index = _rows.indexWhere((row) => row.id == rowId); if (index != -1) { _rowByRowId[rowId] = updatedRow.row; - newRows.removeAt(index); - newRows.insert(index, buildGridRow(rowId, updatedRow.row.height.toDouble())); + _rows.removeAt(index); + _rows.insert(index, buildGridRow(rowId, updatedRow.row.height.toDouble())); updatedIndexs[rowId] = UpdatedIndex(index: index, rowId: rowId); } } - _notifier.receive(GridRowChangeReason.update(updatedIndexs)); + _rowChangeReasonNotifier.receive(GridRowChangeReason.update(updatedIndexs)); } void _hideRows(List hideRows) {} @@ -130,8 +141,8 @@ class GridRowCacheService { void onRowsChanged( void Function(GridRowChangeReason) onRowChanged, ) { - _notifier.addListener(() { - onRowChanged(_notifier._reason); + _rowChangeReasonNotifier.addListener(() { + onRowChanged(_rowChangeReasonNotifier.reason); }); } @@ -150,12 +161,12 @@ class GridRowCacheService { final row = _rowByRowId[rowId]; if (row != null) { final GridCellMap cellDataMap = _makeGridCells(rowId, row); - onCellUpdated(cellDataMap, _notifier._reason); + onCellUpdated(cellDataMap, _rowChangeReasonNotifier.reason); } } } - _notifier._reason.whenOrNull( + _rowChangeReasonNotifier.reason.whenOrNull( update: (indexs) { if (indexs[rowId] != null) notifyUpdate(); }, @@ -163,12 +174,12 @@ class GridRowCacheService { ); } - _notifier.addListener(listenrHandler); + _rowChangeReasonNotifier.addListener(listenrHandler); return listenrHandler; } void removeRowListener(VoidCallback callback) { - _notifier.removeListener(callback); + _rowChangeReasonNotifier.removeListener(callback); } GridCellMap loadGridCells(String rowId) { @@ -194,9 +205,9 @@ class GridRowCacheService { GridCellMap _makeGridCells(String rowId, Row? row) { var cellDataMap = GridCellMap.new(); - for (final field in _delegate.fields) { + for (final field in _fieldNotifier.fields) { if (field.visibility) { - cellDataMap[field.id] = GridCell( + cellDataMap[field.id] = GridCellIdentifier( rowId: rowId, gridId: gridId, field: field, @@ -214,19 +225,19 @@ class GridRowCacheService { updatedRow.freeze(); _rowByRowId[updatedRow.id] = updatedRow; - final index = _rows.indexWhere((gridRow) => gridRow.rowId == updatedRow.id); + final index = _rows.indexWhere((gridRow) => gridRow.id == updatedRow.id); if (index != -1) { // update the corresponding row in _rows if they are not the same - if (_rows[index].data != updatedRow) { - final row = _rows.removeAt(index).copyWith(data: updatedRow); + if (_rows[index].rawRow != updatedRow) { + final row = _rows.removeAt(index).copyWith(rawRow: updatedRow); _rows.insert(index, row); // Calculate the update index final UpdatedIndexs updatedIndexs = UpdatedIndexs(); - updatedIndexs[row.rowId] = UpdatedIndex(index: index, rowId: row.rowId); + updatedIndexs[row.id] = UpdatedIndex(index: index, rowId: row.id); // - _notifier.receive(GridRowChangeReason.update(updatedIndexs)); + _rowChangeReasonNotifier.receive(GridRowChangeReason.update(updatedIndexs)); } } } @@ -235,20 +246,20 @@ class GridRowCacheService { return GridRow( gridId: gridId, blockId: block.id, - fields: _delegate.fields, - rowId: rowId, + fields: _fieldNotifier.fields, + id: rowId, height: rowHeight, ); } } -class _Notifier extends ChangeNotifier { - GridRowChangeReason _reason = const InitialListState(); +class _GridRowChangesetNotifier extends ChangeNotifier { + GridRowChangeReason reason = const InitialListState(); - _Notifier(); + _GridRowChangesetNotifier(); - void receive(GridRowChangeReason reason) { - _reason = reason; + void receive(GridRowChangeReason newReason) { + reason = newReason; reason.map( insert: (_) => notifyListeners(), delete: (_) => notifyListeners(), @@ -318,10 +329,10 @@ class GridRow with _$GridRow { const factory GridRow({ required String gridId, required String blockId, - required String rowId, + required String id, required UnmodifiableListView fields, required double height, - Row? data, + Row? rawRow, }) = _GridRow; } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart index 6daf2c50fa..d7d2999dd1 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart @@ -227,14 +227,16 @@ class _GridRowsState extends State<_GridRows> { GridRow rowData, Animation animation, ) { - final rowCache = context.read().getRowCache(rowData.blockId, rowData.rowId); + final rowCache = context.read().getRowCache(rowData.blockId, rowData.id); + final fieldCache = context.read().fieldCache; if (rowCache != null) { return SizeTransition( sizeFactor: animation, child: GridRowWidget( rowData: rowData, rowCache: rowCache, - key: ValueKey(rowData.rowId), + fieldCache: fieldCache, + key: ValueKey(rowData.id), ), ); } else { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart index 9f3c7a632e..10efcbb0de 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart @@ -1,4 +1,5 @@ import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_service.dart'; +import 'package:app_flowy/workspace/application/grid/grid_service.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; @@ -12,28 +13,39 @@ import 'select_option_cell/select_option_cell.dart'; import 'text_cell.dart'; import 'url_cell/url_cell.dart'; -GridCellWidget buildGridCellWidget(GridCell gridCell, GridCellCacheService cellCache, {GridCellStyle? style}) { - final key = ValueKey(gridCell.cellId()); +class GridCellBuilder { + final GridCellCache cellCache; + final GridFieldCache fieldCache; + GridCellBuilder({ + required this.cellCache, + required this.fieldCache, + }); - final cellContextBuilder = GridCellContextBuilder(gridCell: gridCell, cellCache: cellCache); - - switch (gridCell.field.fieldType) { - case FieldType.Checkbox: - return CheckboxCell(cellContextBuilder: cellContextBuilder, key: key); - case FieldType.DateTime: - return DateCell(cellContextBuilder: cellContextBuilder, key: key, style: style); - case FieldType.SingleSelect: - return SingleSelectCell(cellContextBuilder: cellContextBuilder, style: style, key: key); - case FieldType.MultiSelect: - return MultiSelectCell(cellContextBuilder: cellContextBuilder, style: style, key: key); - case FieldType.Number: - return NumberCell(cellContextBuilder: cellContextBuilder, key: key); - case FieldType.RichText: - return GridTextCell(cellContextBuilder: cellContextBuilder, style: style, key: key); - case FieldType.URL: - return GridURLCell(cellContextBuilder: cellContextBuilder, style: style, key: key); + GridCellWidget build(GridCellIdentifier cell, {GridCellStyle? style}) { + final cellControllerBuilder = GridCellControllerBuilder( + cellId: cell, + cellCache: cellCache, + fieldCache: fieldCache, + ); + final key = cell.key(); + switch (cell.fieldType) { + case FieldType.Checkbox: + return CheckboxCell(cellControllerBuilder: cellControllerBuilder, key: key); + case FieldType.DateTime: + return DateCell(cellControllerBuilder: cellControllerBuilder, key: key, style: style); + case FieldType.SingleSelect: + return SingleSelectCell(cellContorllerBuilder: cellControllerBuilder, style: style, key: key); + case FieldType.MultiSelect: + return MultiSelectCell(cellContorllerBuilder: cellControllerBuilder, style: style, key: key); + case FieldType.Number: + return NumberCell(cellContorllerBuilder: cellControllerBuilder, key: key); + case FieldType.RichText: + return GridTextCell(cellContorllerBuilder: cellControllerBuilder, style: style, key: key); + case FieldType.URL: + return GridURLCell(cellContorllerBuilder: cellControllerBuilder, style: style, key: key); + } + throw UnimplementedError; } - throw UnimplementedError; } class BlankCell extends StatelessWidget { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart index 384d85737f..ac2a2fb979 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart @@ -7,9 +7,9 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'cell_builder.dart'; class CheckboxCell extends GridCellWidget { - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellControllerBuilder; CheckboxCell({ - required this.cellContextBuilder, + required this.cellControllerBuilder, Key? key, }) : super(key: key); @@ -22,7 +22,7 @@ class _CheckboxCellState extends GridCellState { @override void initState() { - final cellContext = widget.cellContextBuilder.build(); + final cellContext = widget.cellControllerBuilder.build(); _cellBloc = getIt(param1: cellContext)..add(const CheckboxCellEvent.initial()); super.initState(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart index 3e7d40c796..7436d0ac7f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart @@ -19,12 +19,12 @@ abstract class GridCellDelegate { } class DateCell extends GridCellWidget { - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellControllerBuilder; late final DateCellStyle? cellStyle; DateCell({ GridCellStyle? style, - required this.cellContextBuilder, + required this.cellControllerBuilder, Key? key, }) : super(key: key) { if (style != null) { @@ -43,7 +43,7 @@ class _DateCellState extends GridCellState { @override void initState() { - final cellContext = widget.cellContextBuilder.build(); + final cellContext = widget.cellControllerBuilder.build(); _cellBloc = getIt(param1: cellContext)..add(const DateCellEvent.initial()); super.initState(); } @@ -80,7 +80,7 @@ class _DateCellState extends GridCellState { final calendar = DateCellEditor(onDismissed: () => widget.onCellEditing.value = false); calendar.show( context, - cellContext: bloc.cellContext.clone(), + cellController: bloc.cellContext.clone(), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart index 93d304cd1a..36ad22ec53 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart @@ -31,16 +31,16 @@ class DateCellEditor with FlowyOverlayDelegate { Future show( BuildContext context, { - required GridDateCellContext cellContext, + required GridDateCellController cellController, }) async { DateCellEditor.remove(context); - final result = await cellContext.getTypeOptionData(); + final result = await cellController.getFieldTypeOption(DateTypeOptionDataParser()); result.fold( - (data) { + (dateTypeOption) { final calendar = _CellCalendarWidget( - cellContext: cellContext, - dateTypeOption: DateTypeOption.fromBuffer(data.typeOptionData), + cellContext: cellController, + dateTypeOption: dateTypeOption, ); FlowyOverlay.of(context).insertWithAnchor( @@ -75,7 +75,7 @@ class DateCellEditor with FlowyOverlayDelegate { } class _CellCalendarWidget extends StatelessWidget { - final GridDateCellContext cellContext; + final GridDateCellController cellContext; final DateTypeOption dateTypeOption; const _CellCalendarWidget({ diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart index 7d16b16ef0..6b1cf4ceae 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart @@ -7,10 +7,10 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'cell_builder.dart'; class NumberCell extends GridCellWidget { - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellContorllerBuilder; NumberCell({ - required this.cellContextBuilder, + required this.cellContorllerBuilder, Key? key, }) : super(key: key); @@ -25,7 +25,7 @@ class _NumberCellState extends GridFocusNodeCellState { @override void initState() { - final cellContext = widget.cellContextBuilder.build(); + final cellContext = widget.cellContorllerBuilder.build(); _cellBloc = getIt(param1: cellContext)..add(const NumberCellEvent.initial()); _controller = TextEditingController(text: contentFromState(_cellBloc.state)); super.initState(); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_cell.dart index 63f7e0fc28..4068507f5a 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_cell.dart @@ -21,11 +21,11 @@ class SelectOptionCellStyle extends GridCellStyle { } class SingleSelectCell extends GridCellWidget { - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellContorllerBuilder; late final SelectOptionCellStyle? cellStyle; SingleSelectCell({ - required this.cellContextBuilder, + required this.cellContorllerBuilder, GridCellStyle? style, Key? key, }) : super(key: key) { @@ -45,7 +45,7 @@ class _SingleSelectCellState extends State { @override void initState() { - final cellContext = widget.cellContextBuilder.build() as GridSelectOptionCellContext; + final cellContext = widget.cellContorllerBuilder.build() as GridSelectOptionCellController; _cellBloc = getIt(param1: cellContext)..add(const SelectOptionCellEvent.initial()); super.initState(); } @@ -60,7 +60,7 @@ class _SingleSelectCellState extends State { selectOptions: state.selectedOptions, cellStyle: widget.cellStyle, onFocus: (value) => widget.onCellEditing.value = value, - cellContextBuilder: widget.cellContextBuilder); + cellContorllerBuilder: widget.cellContorllerBuilder); }, ), ); @@ -75,11 +75,11 @@ class _SingleSelectCellState extends State { //---------------------------------------------------------------- class MultiSelectCell extends GridCellWidget { - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellContorllerBuilder; late final SelectOptionCellStyle? cellStyle; MultiSelectCell({ - required this.cellContextBuilder, + required this.cellContorllerBuilder, GridCellStyle? style, Key? key, }) : super(key: key) { @@ -99,7 +99,7 @@ class _MultiSelectCellState extends State { @override void initState() { - final cellContext = widget.cellContextBuilder.build() as GridSelectOptionCellContext; + final cellContext = widget.cellContorllerBuilder.build() as GridSelectOptionCellController; _cellBloc = getIt(param1: cellContext)..add(const SelectOptionCellEvent.initial()); super.initState(); } @@ -114,7 +114,7 @@ class _MultiSelectCellState extends State { selectOptions: state.selectedOptions, cellStyle: widget.cellStyle, onFocus: (value) => widget.onCellEditing.value = value, - cellContextBuilder: widget.cellContextBuilder); + cellContorllerBuilder: widget.cellContorllerBuilder); }, ), ); @@ -131,12 +131,12 @@ class _SelectOptionCell extends StatelessWidget { final List selectOptions; final void Function(bool) onFocus; final SelectOptionCellStyle? cellStyle; - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellContorllerBuilder; const _SelectOptionCell({ required this.selectOptions, required this.onFocus, required this.cellStyle, - required this.cellContextBuilder, + required this.cellContorllerBuilder, Key? key, }) : super(key: key); @@ -172,7 +172,7 @@ class _SelectOptionCell extends StatelessWidget { InkWell( onTap: () { onFocus(true); - final cellContext = cellContextBuilder.build() as GridSelectOptionCellContext; + final cellContext = cellContorllerBuilder.build() as GridSelectOptionCellController; SelectOptionCellEditor.show(context, cellContext, () => onFocus(false)); }, ), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart index 76d9a379d7..45a641c39c 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart @@ -24,11 +24,11 @@ import 'text_field.dart'; const double _editorPannelWidth = 300; class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate { - final GridSelectOptionCellContext cellContext; + final GridSelectOptionCellController cellController; final VoidCallback onDismissed; const SelectOptionCellEditor({ - required this.cellContext, + required this.cellController, required this.onDismissed, Key? key, }) : super(key: key); @@ -37,7 +37,7 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate { Widget build(BuildContext context) { return BlocProvider( create: (context) => SelectOptionCellEditorBloc( - cellContext: cellContext, + cellController: cellController, )..add(const SelectOptionEditorEvent.initial()), child: BlocBuilder( builder: (context, state) { @@ -59,12 +59,12 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate { static void show( BuildContext context, - GridSelectOptionCellContext cellContext, + GridSelectOptionCellController cellContext, VoidCallback onDismissed, ) { SelectOptionCellEditor.remove(context); final editor = SelectOptionCellEditor( - cellContext: cellContext, + cellController: cellContext, onDismissed: onDismissed, ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart index 1bece5a3d7..55bf757ba4 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart @@ -14,10 +14,10 @@ class GridTextCellStyle extends GridCellStyle { } class GridTextCell extends GridCellWidget { - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellContorllerBuilder; late final GridTextCellStyle? cellStyle; GridTextCell({ - required this.cellContextBuilder, + required this.cellContorllerBuilder, GridCellStyle? style, Key? key, }) : super(key: key) { @@ -39,7 +39,7 @@ class _GridTextCellState extends GridFocusNodeCellState { @override void initState() { - final cellContext = widget.cellContextBuilder.build(); + final cellContext = widget.cellContorllerBuilder.build(); _cellBloc = getIt(param1: cellContext); _cellBloc.add(const TextCellEvent.initial()); _controller = TextEditingController(text: _cellBloc.state.content); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/cell_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/cell_editor.dart index f4da18be86..b6bc8daa21 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/cell_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/cell_editor.dart @@ -7,21 +7,21 @@ import 'dart:async'; import 'package:flutter_bloc/flutter_bloc.dart'; class URLCellEditor extends StatefulWidget with FlowyOverlayDelegate { - final GridURLCellContext cellContext; + final GridURLCellController cellController; final VoidCallback completed; - const URLCellEditor({required this.cellContext, required this.completed, Key? key}) : super(key: key); + const URLCellEditor({required this.cellController, required this.completed, Key? key}) : super(key: key); @override State createState() => _URLCellEditorState(); static void show( BuildContext context, - GridURLCellContext cellContext, + GridURLCellController cellContext, VoidCallback completed, ) { FlowyOverlay.of(context).remove(identifier()); final editor = URLCellEditor( - cellContext: cellContext, + cellController: cellContext, completed: completed, ); @@ -62,7 +62,7 @@ class _URLCellEditorState extends State { @override void initState() { - _cellBloc = URLCellEditorBloc(cellContext: widget.cellContext); + _cellBloc = URLCellEditorBloc(cellContext: widget.cellController); _cellBloc.add(const URLCellEditorEvent.initial()); _controller = TextEditingController(text: _cellBloc.state.content); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart index e37dca6632..9cc14fbbda 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart @@ -31,10 +31,10 @@ enum GridURLCellAccessoryType { } class GridURLCell extends GridCellWidget { - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellContorllerBuilder; late final GridURLCellStyle? cellStyle; GridURLCell({ - required this.cellContextBuilder, + required this.cellContorllerBuilder, GridCellStyle? style, Key? key, }) : super(key: key) { @@ -51,11 +51,11 @@ class GridURLCell extends GridCellWidget { GridCellAccessory accessoryFromType(GridURLCellAccessoryType ty, GridCellAccessoryBuildContext buildContext) { switch (ty) { case GridURLCellAccessoryType.edit: - final cellContext = cellContextBuilder.build() as GridURLCellContext; + final cellContext = cellContorllerBuilder.build() as GridURLCellController; return _EditURLAccessory(cellContext: cellContext, anchorContext: buildContext.anchorContext); case GridURLCellAccessoryType.copyURL: - final cellContext = cellContextBuilder.build() as GridURLCellContext; + final cellContext = cellContorllerBuilder.build() as GridURLCellController; return _CopyURLAccessory(cellContext: cellContext); } } @@ -83,7 +83,7 @@ class _GridURLCellState extends GridCellState { @override void initState() { - final cellContext = widget.cellContextBuilder.build() as GridURLCellContext; + final cellContext = widget.cellContorllerBuilder.build() as GridURLCellController; _cellBloc = URLCellBloc(cellContext: cellContext); _cellBloc.add(const URLCellEvent.initial()); super.initState(); @@ -132,7 +132,7 @@ class _GridURLCellState extends GridCellState { if (url.isNotEmpty && await canLaunchUrl(uri)) { await launchUrl(uri); } else { - final cellContext = widget.cellContextBuilder.build() as GridURLCellContext; + final cellContext = widget.cellContorllerBuilder.build() as GridURLCellController; widget.onCellEditing.value = true; URLCellEditor.show(context, cellContext, () { widget.onCellEditing.value = false; @@ -155,7 +155,7 @@ class _GridURLCellState extends GridCellState { } class _EditURLAccessory extends StatelessWidget with GridCellAccessory { - final GridURLCellContext cellContext; + final GridURLCellController cellContext; final BuildContext anchorContext; const _EditURLAccessory({ required this.cellContext, @@ -176,7 +176,7 @@ class _EditURLAccessory extends StatelessWidget with GridCellAccessory { } class _CopyURLAccessory extends StatelessWidget with GridCellAccessory { - final GridURLCellContext cellContext; + final GridURLCellController cellContext; const _CopyURLAccessory({required this.cellContext, Key? key}) : super(key: key); @override @@ -187,7 +187,7 @@ class _CopyURLAccessory extends StatelessWidget with GridCellAccessory { @override void onTap() { - final content = cellContext.getCellData(loadIfNoCache: false)?.content ?? ""; + final content = cellContext.getCellData(loadIfNotExist: false)?.content ?? ""; Clipboard.setData(ClipboardData(text: content)); showMessageToast(LocaleKeys.grid_row_copyProperty.tr()); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart index 9237c71be0..266ec5a619 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart @@ -65,7 +65,7 @@ class GridFieldCell extends StatelessWidget { FieldEditor( gridId: state.gridId, fieldName: field.name, - contextLoader: FieldContextLoader( + typeOptionLoader: FieldTypeOptionLoader( gridId: state.gridId, field: field, ), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart index 3390351663..3a857a9fb4 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart @@ -8,17 +8,17 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'field_name_input.dart'; -import 'field_editor_pannel.dart'; +import 'field_type_option_editor.dart'; class FieldEditor extends StatelessWidget with FlowyOverlayDelegate { final String gridId; final String fieldName; - final IFieldContextLoader contextLoader; + final IFieldTypeOptionLoader typeOptionLoader; const FieldEditor({ required this.gridId, required this.fieldName, - required this.contextLoader, + required this.typeOptionLoader, Key? key, }) : super(key: key); @@ -28,7 +28,7 @@ class FieldEditor extends StatelessWidget with FlowyOverlayDelegate { create: (context) => FieldEditorBloc( gridId: gridId, fieldName: fieldName, - fieldContextLoader: contextLoader, + loader: typeOptionLoader, )..add(const FieldEditorEvent.initial()), child: BlocBuilder( buildWhen: (p, c) => false, @@ -38,9 +38,9 @@ class FieldEditor extends StatelessWidget with FlowyOverlayDelegate { children: [ FlowyText.medium(LocaleKeys.grid_field_editProperty.tr(), fontSize: 12), const VSpace(10), - const _FieldNameTextField(), + const _FieldNameCell(), const VSpace(10), - const _FieldPannel(), + const _FieldTypeOptionCell(), ], ); }, @@ -74,25 +74,28 @@ class FieldEditor extends StatelessWidget with FlowyOverlayDelegate { bool asBarrier() => true; } -class _FieldPannel extends StatelessWidget { - const _FieldPannel({Key? key}) : super(key: key); +class _FieldTypeOptionCell extends StatelessWidget { + const _FieldTypeOptionCell({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return BlocBuilder( - buildWhen: (p, c) => p.fieldContext != c.fieldContext, + buildWhen: (p, c) => p.field != c.field, builder: (context, state) { - return state.fieldContext.fold( + return state.field.fold( () => const SizedBox(), - (fieldContext) => FieldEditorPannel(fieldContext: fieldContext), + (fieldContext) { + final dataController = context.read().dataController; + return FieldTypeOptionEditor(dataController: dataController); + }, ); }, ); } } -class _FieldNameTextField extends StatelessWidget { - const _FieldNameTextField({Key? key}) : super(key: key); +class _FieldNameCell extends StatelessWidget { + const _FieldNameCell({Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart deleted file mode 100644 index 7ec5144458..0000000000 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart +++ /dev/null @@ -1,243 +0,0 @@ -import 'dart:typed_data'; - -import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_type_option.dart'; -import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart'; -import 'package:dartz/dartz.dart' show Either; -import 'package:flowy_infra/image.dart'; -import 'package:flowy_infra/theme.dart'; -import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:app_flowy/workspace/application/grid/prelude.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart'; -import 'field_type_extension.dart'; -import 'type_option/multi_select.dart'; -import 'type_option/number.dart'; -import 'type_option/rich_text.dart'; -import 'type_option/single_select.dart'; -import 'type_option/url.dart'; - -typedef UpdateFieldCallback = void Function(Field, Uint8List); -typedef SwitchToFieldCallback = Future> Function( - String fieldId, - FieldType fieldType, -); - -class FieldEditorPannel extends StatefulWidget { - final GridFieldContext fieldContext; - - const FieldEditorPannel({ - required this.fieldContext, - Key? key, - }) : super(key: key); - - @override - State createState() => _FieldEditorPannelState(); -} - -class _FieldEditorPannelState extends State { - String? currentOverlayIdentifier; - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => FieldEditorPannelBloc(widget.fieldContext)..add(const FieldEditorPannelEvent.initial()), - child: BlocBuilder( - builder: (context, state) { - List children = [_switchFieldTypeButton(context, widget.fieldContext.field)]; - final typeOptionWidget = _typeOptionWidget(context: context, state: state); - - if (typeOptionWidget != null) { - children.add(typeOptionWidget); - } - - return ListView( - shrinkWrap: true, - children: children, - ); - }, - ), - ); - } - - Widget _switchFieldTypeButton(BuildContext context, Field field) { - final theme = context.watch(); - return SizedBox( - height: GridSize.typeOptionItemHeight, - child: FlowyButton( - text: FlowyText.medium(field.fieldType.title(), fontSize: 12), - margin: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), - hoverColor: theme.hover, - onTap: () { - final list = FieldTypeList(onSelectField: (newFieldType) { - widget.fieldContext.switchToField(newFieldType); - }); - _showOverlay(context, list); - }, - leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor), - rightIcon: svgWidget("grid/more", color: theme.iconColor), - ), - ); - } - - Widget? _typeOptionWidget({ - required BuildContext context, - required FieldEditorPannelState state, - }) { - final overlayDelegate = TypeOptionOverlayDelegate( - showOverlay: _showOverlay, - hideOverlay: _hideOverlay, - ); - - final builder = _makeTypeOptionBuild( - typeOptionContext: _makeTypeOptionContext(widget.fieldContext), - overlayDelegate: overlayDelegate, - ); - - return builder.customWidget; - } - - void _showOverlay(BuildContext context, Widget child, {VoidCallback? onRemoved}) { - final identifier = child.toString(); - if (currentOverlayIdentifier != null) { - FlowyOverlay.of(context).remove(currentOverlayIdentifier!); - } - - currentOverlayIdentifier = identifier; - FlowyOverlay.of(context).insertWithAnchor( - widget: OverlayContainer( - child: child, - constraints: BoxConstraints.loose(const Size(460, 440)), - ), - identifier: identifier, - anchorContext: context, - anchorDirection: AnchorDirection.leftWithCenterAligned, - style: FlowyOverlayStyle(blur: false), - anchorOffset: const Offset(-20, 0), - ); - } - - void _hideOverlay(BuildContext context) { - if (currentOverlayIdentifier != null) { - FlowyOverlay.of(context).remove(currentOverlayIdentifier!); - } - } -} - -abstract class TypeOptionBuilder { - Widget? get customWidget; -} - -TypeOptionBuilder _makeTypeOptionBuild({ - required TypeOptionContext typeOptionContext, - required TypeOptionOverlayDelegate overlayDelegate, -}) { - switch (typeOptionContext.field.fieldType) { - case FieldType.Checkbox: - return CheckboxTypeOptionBuilder( - typeOptionContext as CheckboxTypeOptionContext, - ); - case FieldType.DateTime: - return DateTypeOptionBuilder( - typeOptionContext as DateTypeOptionContext, - overlayDelegate, - ); - case FieldType.SingleSelect: - return SingleSelectTypeOptionBuilder( - typeOptionContext as SingleSelectTypeOptionContext, - overlayDelegate, - ); - case FieldType.MultiSelect: - return MultiSelectTypeOptionBuilder( - typeOptionContext as MultiSelectTypeOptionContext, - overlayDelegate, - ); - case FieldType.Number: - return NumberTypeOptionBuilder( - typeOptionContext as NumberTypeOptionContext, - overlayDelegate, - ); - case FieldType.RichText: - return RichTextTypeOptionBuilder( - typeOptionContext as RichTextTypeOptionContext, - ); - - case FieldType.URL: - return URLTypeOptionBuilder( - typeOptionContext as URLTypeOptionContext, - ); - } - throw UnimplementedError; -} - -TypeOptionContext _makeTypeOptionContext(GridFieldContext fieldContext) { - switch (fieldContext.field.fieldType) { - case FieldType.Checkbox: - return CheckboxTypeOptionContext( - fieldContext: fieldContext, - dataBuilder: CheckboxTypeOptionDataBuilder(), - ); - case FieldType.DateTime: - return DateTypeOptionContext( - fieldContext: fieldContext, - dataBuilder: DateTypeOptionDataBuilder(), - ); - case FieldType.MultiSelect: - return MultiSelectTypeOptionContext( - fieldContext: fieldContext, - dataBuilder: MultiSelectTypeOptionDataBuilder(), - ); - case FieldType.Number: - return NumberTypeOptionContext( - fieldContext: fieldContext, - dataBuilder: NumberTypeOptionDataBuilder(), - ); - case FieldType.RichText: - return RichTextTypeOptionContext( - fieldContext: fieldContext, - dataBuilder: RichTextTypeOptionDataBuilder(), - ); - case FieldType.SingleSelect: - return SingleSelectTypeOptionContext( - fieldContext: fieldContext, - dataBuilder: SingleSelectTypeOptionDataBuilder(), - ); - - case FieldType.URL: - return URLTypeOptionContext( - fieldContext: fieldContext, - dataBuilder: URLTypeOptionDataBuilder(), - ); - } - - throw UnimplementedError(); -} - -abstract class TypeOptionWidget extends StatelessWidget { - const TypeOptionWidget({Key? key}) : super(key: key); -} - -typedef TypeOptionData = Uint8List; -typedef TypeOptionDataCallback = void Function(TypeOptionData typeOptionData); -typedef ShowOverlayCallback = void Function( - BuildContext anchorContext, - Widget child, { - VoidCallback? onRemoved, -}); -typedef HideOverlayCallback = void Function(BuildContext anchorContext); - -class TypeOptionOverlayDelegate { - ShowOverlayCallback showOverlay; - HideOverlayCallback hideOverlay; - TypeOptionOverlayDelegate({ - required this.showOverlay, - required this.hideOverlay, - }); -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_option_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_option_editor.dart new file mode 100644 index 0000000000..60592d1032 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_option_editor.dart @@ -0,0 +1,127 @@ +import 'dart:typed_data'; +import 'package:dartz/dartz.dart' show Either; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart'; +import 'field_type_extension.dart'; +import 'type_option/builder.dart'; + +typedef UpdateFieldCallback = void Function(Field, Uint8List); +typedef SwitchToFieldCallback = Future> Function( + String fieldId, + FieldType fieldType, +); + +class FieldTypeOptionEditor extends StatefulWidget { + final TypeOptionDataController dataController; + + const FieldTypeOptionEditor({ + required this.dataController, + Key? key, + }) : super(key: key); + + @override + State createState() => _FieldTypeOptionEditorState(); +} + +class _FieldTypeOptionEditorState extends State { + String? currentOverlayIdentifier; + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => + FieldTypeOptionEditBloc(widget.dataController)..add(const FieldTypeOptionEditEvent.initial()), + child: BlocBuilder( + builder: (context, state) { + List children = [_switchFieldTypeButton(context, widget.dataController.field)]; + final typeOptionWidget = _typeOptionWidget(context: context, state: state); + + if (typeOptionWidget != null) { + children.add(typeOptionWidget); + } + + return ListView( + shrinkWrap: true, + children: children, + ); + }, + ), + ); + } + + Widget _switchFieldTypeButton(BuildContext context, Field field) { + final theme = context.watch(); + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(field.fieldType.title(), fontSize: 12), + margin: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + hoverColor: theme.hover, + onTap: () { + final list = FieldTypeList(onSelectField: (newFieldType) { + widget.dataController.switchToField(newFieldType); + }); + _showOverlay(context, list); + }, + leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor), + rightIcon: svgWidget("grid/more", color: theme.iconColor), + ), + ); + } + + Widget? _typeOptionWidget({ + required BuildContext context, + required FieldTypeOptionEditState state, + }) { + final overlayDelegate = TypeOptionOverlayDelegate( + showOverlay: _showOverlay, + hideOverlay: _hideOverlay, + ); + + return makeTypeOptionWidget( + context: context, + dataController: widget.dataController, + overlayDelegate: overlayDelegate, + ); + } + + void _showOverlay(BuildContext context, Widget child, {VoidCallback? onRemoved}) { + final identifier = child.toString(); + if (currentOverlayIdentifier != null) { + FlowyOverlay.of(context).remove(currentOverlayIdentifier!); + } + + currentOverlayIdentifier = identifier; + FlowyOverlay.of(context).insertWithAnchor( + widget: OverlayContainer( + child: child, + constraints: BoxConstraints.loose(const Size(460, 440)), + ), + identifier: identifier, + anchorContext: context, + anchorDirection: AnchorDirection.leftWithCenterAligned, + style: FlowyOverlayStyle(blur: false), + anchorOffset: const Offset(-20, 0), + ); + } + + void _hideOverlay(BuildContext context) { + if (currentOverlayIdentifier != null) { + FlowyOverlay.of(context).remove(currentOverlayIdentifier!); + } + } +} + +abstract class TypeOptionWidget extends StatelessWidget { + const TypeOptionWidget({Key? key}) : super(key: key); +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart index cc968d15cb..2240d7f6aa 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart @@ -151,7 +151,7 @@ class CreateFieldButton extends StatelessWidget { onTap: () => FieldEditor( gridId: gridId, fieldName: "", - contextLoader: NewFieldContextLoader(gridId: gridId), + typeOptionLoader: NewFieldTypeOptionLoader(gridId: gridId), ).show(context), leftIcon: svgWidget("home/add"), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/builder.dart new file mode 100644 index 0000000000..63fa761d98 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/builder.dart @@ -0,0 +1,108 @@ +import 'dart:typed_data'; + +import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_type_option.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:flutter/material.dart'; +import 'date.dart'; +import 'multi_select.dart'; +import 'number.dart'; +import 'rich_text.dart'; +import 'single_select.dart'; +import 'url.dart'; + +typedef TypeOptionData = Uint8List; +typedef TypeOptionDataCallback = void Function(TypeOptionData typeOptionData); +typedef ShowOverlayCallback = void Function( + BuildContext anchorContext, + Widget child, { + VoidCallback? onRemoved, +}); +typedef HideOverlayCallback = void Function(BuildContext anchorContext); + +class TypeOptionOverlayDelegate { + ShowOverlayCallback showOverlay; + HideOverlayCallback hideOverlay; + TypeOptionOverlayDelegate({ + required this.showOverlay, + required this.hideOverlay, + }); +} + +abstract class TypeOptionWidgetBuilder { + Widget? build(BuildContext context); +} + +Widget? makeTypeOptionWidget({ + required BuildContext context, + required TypeOptionDataController dataController, + required TypeOptionOverlayDelegate overlayDelegate, +}) { + final builder = makeTypeOptionWidgetBuilder(dataController, overlayDelegate); + return builder.build(context); +} + +TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder( + TypeOptionDataController dataController, + TypeOptionOverlayDelegate overlayDelegate, +) { + switch (dataController.field.fieldType) { + case FieldType.Checkbox: + final context = CheckboxTypeOptionContext( + dataController: dataController, + dataParser: CheckboxTypeOptionWidgetDataParser(), + ); + return CheckboxTypeOptionWidgetBuilder(context); + case FieldType.DateTime: + final context = DateTypeOptionContext( + dataController: dataController, + dataParser: DateTypeOptionDataParser(), + ); + return DateTypeOptionWidgetBuilder( + context, + overlayDelegate, + ); + case FieldType.SingleSelect: + final context = SingleSelectTypeOptionContext( + fieldContext: dataController, + dataBuilder: SingleSelectTypeOptionWidgetDataParser(), + ); + return SingleSelectTypeOptionWidgetBuilder( + context, + overlayDelegate, + ); + case FieldType.MultiSelect: + final context = MultiSelectTypeOptionContext( + dataController: dataController, + dataBuilder: MultiSelectTypeOptionWidgetDataParser(), + ); + return MultiSelectTypeOptionWidgetBuilder( + context, + overlayDelegate, + ); + case FieldType.Number: + final context = NumberTypeOptionContext( + dataController: dataController, + dataParser: NumberTypeOptionWidgetDataParser(), + ); + return NumberTypeOptionWidgetBuilder( + context, + overlayDelegate, + ); + case FieldType.RichText: + final context = RichTextTypeOptionContext( + dataController: dataController, + dataParser: RichTextTypeOptionWidgetDataParser(), + ); + return RichTextTypeOptionWidgetBuilder(context); + + case FieldType.URL: + final context = URLTypeOptionContext( + dataController: dataController, + dataParser: URLTypeOptionWidgetDataParser(), + ); + return URLTypeOptionWidgetBuilder(context); + } + throw UnimplementedError; +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart index c1e202f358..beca8acd09 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart @@ -1,20 +1,20 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart'; import 'package:flutter/material.dart'; +import 'builder.dart'; -typedef CheckboxTypeOptionContext = TypeOptionContext; +typedef CheckboxTypeOptionContext = TypeOptionWidgetContext; -class CheckboxTypeOptionDataBuilder extends TypeOptionDataBuilder { +class CheckboxTypeOptionWidgetDataParser extends TypeOptionDataParser { @override CheckboxTypeOption fromBuffer(List buffer) { return CheckboxTypeOption.fromBuffer(buffer); } } -class CheckboxTypeOptionBuilder extends TypeOptionBuilder { - CheckboxTypeOptionBuilder(CheckboxTypeOptionContext typeOptionContext); +class CheckboxTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder { + CheckboxTypeOptionWidgetBuilder(CheckboxTypeOptionContext typeOptionContext); @override - Widget? get customWidget => null; + Widget? build(BuildContext context) => null; } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart index b9b2f8e89d..39408c9ee3 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart @@ -1,6 +1,6 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/date_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_option_editor.dart'; import 'package:easy_localization/easy_localization.dart' hide DateFormat; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:flowy_infra/image.dart'; @@ -12,11 +12,12 @@ import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'builder.dart'; -class DateTypeOptionBuilder extends TypeOptionBuilder { +class DateTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder { final DateTypeOptionWidget _widget; - DateTypeOptionBuilder( + DateTypeOptionWidgetBuilder( DateTypeOptionContext typeOptionContext, TypeOptionOverlayDelegate overlayDelegate, ) : _widget = DateTypeOptionWidget( @@ -25,7 +26,9 @@ class DateTypeOptionBuilder extends TypeOptionBuilder { ); @override - Widget? get customWidget => _widget; + Widget? build(BuildContext context) { + return _widget; + } } class DateTypeOptionWidget extends TypeOptionWidget { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart index fc310410f9..8c7ab40a6f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart @@ -1,13 +1,14 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_type_option.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_option_editor.dart'; import 'package:flutter/material.dart'; +import 'builder.dart'; import 'select_option.dart'; -class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { +class MultiSelectTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder { final MultiSelectTypeOptionWidget _widget; - MultiSelectTypeOptionBuilder( + MultiSelectTypeOptionWidgetBuilder( MultiSelectTypeOptionContext typeOptionContext, TypeOptionOverlayDelegate overlayDelegate, ) : _widget = MultiSelectTypeOptionWidget( @@ -16,7 +17,7 @@ class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { ); @override - Widget? get customWidget => _widget; + Widget? build(BuildContext context) => _widget; } class MultiSelectTypeOptionWidget extends TypeOptionWidget { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart index bca17e1cd8..e15abb1728 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/number_bl import 'package:app_flowy/workspace/application/grid/field/type_option/number_format_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_option_editor.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -15,10 +15,12 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:easy_localization/easy_localization.dart' hide NumberFormat; import 'package:app_flowy/generated/locale_keys.g.dart'; -class NumberTypeOptionBuilder extends TypeOptionBuilder { +import 'builder.dart'; + +class NumberTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder { final NumberTypeOptionWidget _widget; - NumberTypeOptionBuilder( + NumberTypeOptionWidgetBuilder( NumberTypeOptionContext typeOptionContext, TypeOptionOverlayDelegate overlayDelegate, ) : _widget = NumberTypeOptionWidget( @@ -27,7 +29,7 @@ class NumberTypeOptionBuilder extends TypeOptionBuilder { ); @override - Widget? get customWidget => _widget; + Widget? build(BuildContext context) => _widget; } class NumberTypeOptionWidget extends TypeOptionWidget { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/rich_text.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/rich_text.dart index 03f9ed347c..2375918f11 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/rich_text.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/rich_text.dart @@ -1,21 +1,20 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart'; - import 'package:flutter/material.dart'; +import 'builder.dart'; -typedef RichTextTypeOptionContext = TypeOptionContext; +typedef RichTextTypeOptionContext = TypeOptionWidgetContext; -class RichTextTypeOptionDataBuilder extends TypeOptionDataBuilder { +class RichTextTypeOptionWidgetDataParser extends TypeOptionDataParser { @override RichTextTypeOption fromBuffer(List buffer) { return RichTextTypeOption.fromBuffer(buffer); } } -class RichTextTypeOptionBuilder extends TypeOptionBuilder { - RichTextTypeOptionBuilder(RichTextTypeOptionContext typeOptionContext); +class RichTextTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder { + RichTextTypeOptionWidgetBuilder(RichTextTypeOptionContext typeOptionContext); @override - Widget? get customWidget => null; + Widget? build(BuildContext context) => null; } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart index 60c1bfcdd6..fea3e5df43 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart @@ -2,7 +2,6 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/select_op import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; @@ -14,6 +13,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'builder.dart'; import 'select_option_editor.dart'; class SelectOptionTypeOptionWidget extends StatelessWidget { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart index fedddec11d..a1ed4e857a 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart @@ -1,12 +1,13 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/single_select_type_option.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_option_editor.dart'; import 'package:flutter/material.dart'; +import 'builder.dart'; import 'select_option.dart'; -class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { +class SingleSelectTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder { final SingleSelectTypeOptionWidget _widget; - SingleSelectTypeOptionBuilder( + SingleSelectTypeOptionWidgetBuilder( SingleSelectTypeOptionContext typeOptionContext, TypeOptionOverlayDelegate overlayDelegate, ) : _widget = SingleSelectTypeOptionWidget( @@ -15,7 +16,7 @@ class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { ); @override - Widget? get customWidget => _widget; + Widget? build(BuildContext context) => _widget; } class SingleSelectTypeOptionWidget extends TypeOptionWidget { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/url.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/url.dart index f4e73f7fdc..97c0db0814 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/url.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/url.dart @@ -1,20 +1,20 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option.pb.dart'; import 'package:flutter/material.dart'; +import 'builder.dart'; -typedef URLTypeOptionContext = TypeOptionContext; +typedef URLTypeOptionContext = TypeOptionWidgetContext; -class URLTypeOptionDataBuilder extends TypeOptionDataBuilder { +class URLTypeOptionWidgetDataParser extends TypeOptionDataParser { @override URLTypeOption fromBuffer(List buffer) { return URLTypeOption.fromBuffer(buffer); } } -class URLTypeOptionBuilder extends TypeOptionBuilder { - URLTypeOptionBuilder(URLTypeOptionContext typeOptionContext); +class URLTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder { + URLTypeOptionWidgetBuilder(URLTypeOptionContext typeOptionContext); @override - Widget? get customWidget => null; + Widget? build(BuildContext context) => null; } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart index de7f117d51..b0c1cd2ea0 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart @@ -10,19 +10,25 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:provider/provider.dart'; -import 'row_action_sheet.dart'; +import 'row_action_sheet.dart'; import 'row_detail.dart'; class GridRowWidget extends StatefulWidget { final GridRow rowData; - final GridRowCacheService rowCache; + final GridRowCache rowCache; + final GridCellBuilder cellBuilder; - const GridRowWidget({ + GridRowWidget({ required this.rowData, required this.rowCache, + required GridFieldCache fieldCache, Key? key, - }) : super(key: key); + }) : cellBuilder = GridCellBuilder( + cellCache: rowCache.cellCache, + fieldCache: fieldCache, + ), + super(key: key); @override State createState() => _GridRowWidgetState(); @@ -52,7 +58,11 @@ class _GridRowWidgetState extends State { return Row( children: [ const _RowLeading(), - Expanded(child: _RowCells(cellCache: widget.rowCache.cellCache, onExpand: () => _expandRow(context))), + Expanded( + child: _RowCells( + builder: widget.cellBuilder, + onExpand: () => _expandRow(context), + )), const _RowTrailing(), ], ); @@ -72,6 +82,7 @@ class _GridRowWidgetState extends State { final page = RowDetailPage( rowData: widget.rowData, rowCache: widget.rowCache, + cellBuilder: widget.cellBuilder, ); page.show(context); } @@ -146,9 +157,13 @@ class _DeleteRowButton extends StatelessWidget { } class _RowCells extends StatelessWidget { - final GridCellCacheService cellCache; final VoidCallback onExpand; - const _RowCells({required this.cellCache, required this.onExpand, Key? key}) : super(key: key); + final GridCellBuilder builder; + const _RowCells({ + required this.builder, + required this.onExpand, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { @@ -168,13 +183,12 @@ class _RowCells extends StatelessWidget { List _makeCells(BuildContext context, GridCellMap gridCellMap) { return gridCellMap.values.map( - (gridCell) { - final GridCellWidget child = buildGridCellWidget(gridCell, cellCache); - + (cellId) { + final GridCellWidget child = builder.build(cellId); accessoryBuilder(GridCellAccessoryBuildContext buildContext) { final builder = child.accessoryBuilder; List accessories = []; - if (gridCell.field.isPrimary) { + if (cellId.field.isPrimary) { accessories.add(PrimaryCellAccessory( onTapCallback: onExpand, isCellEditing: buildContext.isCellEditing, @@ -188,7 +202,7 @@ class _RowCells extends StatelessWidget { } return CellContainer( - width: gridCell.field.width.toDouble(), + width: cellId.field.width.toDouble(), child: child, rowStateNotifier: Provider.of(context, listen: false), accessoryBuilder: accessoryBuilder, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart index c4ccc32a1a..4449ea6770 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart @@ -22,11 +22,13 @@ import 'package:flutter_bloc/flutter_bloc.dart'; class RowDetailPage extends StatefulWidget with FlowyOverlayDelegate { final GridRow rowData; - final GridRowCacheService rowCache; + final GridRowCache rowCache; + final GridCellBuilder cellBuilder; const RowDetailPage({ required this.rowData, required this.rowCache, + required this.cellBuilder, Key? key, }) : super(key: key); @@ -74,7 +76,7 @@ class _RowDetailPageState extends State { children: const [Spacer(), _CloseButton()], ), ), - Expanded(child: _PropertyList(cellCache: widget.rowCache.cellCache)), + Expanded(child: _PropertyList(cellBuilder: widget.cellBuilder)), ], ), ), @@ -98,10 +100,10 @@ class _CloseButton extends StatelessWidget { } class _PropertyList extends StatelessWidget { - final GridCellCacheService cellCache; + final GridCellBuilder cellBuilder; final ScrollController _scrollController; _PropertyList({ - required this.cellCache, + required this.cellBuilder, Key? key, }) : _scrollController = ScrollController(), super(key: key); @@ -120,8 +122,8 @@ class _PropertyList extends StatelessWidget { itemCount: state.gridCells.length, itemBuilder: (BuildContext context, int index) { return _RowDetailCell( - gridCell: state.gridCells[index], - cellCache: cellCache, + cellId: state.gridCells[index], + cellBuilder: cellBuilder, ); }, separatorBuilder: (BuildContext context, int index) { @@ -135,19 +137,19 @@ class _PropertyList extends StatelessWidget { } class _RowDetailCell extends StatelessWidget { - final GridCell gridCell; - final GridCellCacheService cellCache; + final GridCellIdentifier cellId; + final GridCellBuilder cellBuilder; const _RowDetailCell({ - required this.gridCell, - required this.cellCache, + required this.cellId, + required this.cellBuilder, Key? key, }) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); - final style = _customCellStyle(theme, gridCell.field.fieldType); - final cell = buildGridCellWidget(gridCell, cellCache, style: style); + final style = _customCellStyle(theme, cellId.fieldType); + final cell = cellBuilder.build(cellId, style: style); final gesture = GestureDetector( behavior: HitTestBehavior.translucent, @@ -167,7 +169,7 @@ class _RowDetailCell extends StatelessWidget { children: [ SizedBox( width: 150, - child: FieldCellButton(field: gridCell.field, onTap: () => _showFieldEditor(context)), + child: FieldCellButton(field: cellId.field, onTap: () => _showFieldEditor(context)), ), const HSpace(10), Expanded(child: gesture), @@ -179,11 +181,11 @@ class _RowDetailCell extends StatelessWidget { void _showFieldEditor(BuildContext context) { FieldEditor( - gridId: gridCell.gridId, - fieldName: gridCell.field.name, - contextLoader: FieldContextLoader( - gridId: gridCell.gridId, - field: gridCell.field, + gridId: cellId.gridId, + fieldName: cellId.field.name, + typeOptionLoader: FieldTypeOptionLoader( + gridId: cellId.gridId, + field: cellId.field, ), ).show(context); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart index e19c90ecea..99d70e93c7 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart @@ -116,7 +116,7 @@ class _GridPropertyCell extends StatelessWidget { FieldEditor( gridId: gridId, fieldName: field.name, - contextLoader: FieldContextLoader(gridId: gridId, field: field), + typeOptionLoader: FieldTypeOptionLoader(gridId: gridId, field: field), ).show(context, anchorDirection: AnchorDirection.bottomRight); }, ); diff --git a/frontend/app_flowy/packages/flowy_infra/pubspec.lock b/frontend/app_flowy/packages/flowy_infra/pubspec.lock deleted file mode 100644 index 256c2dac3a..0000000000 --- a/frontend/app_flowy/packages/flowy_infra/pubspec.lock +++ /dev/null @@ -1,231 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - async: - dependency: transitive - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "2.8.2" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - characters: - dependency: transitive - description: - name: characters - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" - clock: - dependency: transitive - description: - name: clock - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - collection: - dependency: transitive - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.15.0" - crypto: - dependency: transitive - description: - name: crypto - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" - fake_async: - dependency: transitive - description: - name: fake_async - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.4" - flutter_svg: - dependency: "direct main" - description: - name: flutter_svg - url: "https://pub.dartlang.org" - source: hosted - version: "0.22.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - lints: - dependency: transitive - description: - name: lints - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.11" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.3" - meta: - dependency: transitive - description: - name: meta - url: "https://pub.dartlang.org" - source: hosted - version: "1.7.0" - path: - dependency: transitive - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0" - path_drawing: - dependency: transitive - description: - name: path_drawing - url: "https://pub.dartlang.org" - source: hosted - version: "0.5.1" - path_parsing: - dependency: transitive - description: - name: path_parsing - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.1" - petitparser: - dependency: transitive - description: - name: petitparser - url: "https://pub.dartlang.org" - source: hosted - version: "4.2.0" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.10.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - test_api: - dependency: transitive - description: - name: test_api - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.8" - textstyle_extensions: - dependency: "direct main" - description: - name: textstyle_extensions - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0-nullsafety" - time: - dependency: "direct main" - description: - name: time - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - uuid: - dependency: "direct main" - description: - name: uuid - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.4" - vector_math: - dependency: transitive - description: - name: vector_math - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" - xml: - dependency: transitive - description: - name: xml - url: "https://pub.dartlang.org" - source: hosted - version: "5.2.0" -sdks: - dart: ">=2.14.0 <3.0.0" - flutter: ">=1.24.0-7.0" diff --git a/frontend/app_flowy/packages/flowy_infra_ui/example/pubspec.lock b/frontend/app_flowy/packages/flowy_infra_ui/example/pubspec.lock deleted file mode 100644 index 0a91c0b58c..0000000000 --- a/frontend/app_flowy/packages/flowy_infra_ui/example/pubspec.lock +++ /dev/null @@ -1,334 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - animations: - dependency: transitive - description: - name: animations - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - async: - dependency: transitive - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "2.8.2" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - characters: - dependency: transitive - description: - name: characters - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" - clock: - dependency: transitive - description: - name: clock - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - collection: - dependency: transitive - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.15.0" - crypto: - dependency: transitive - description: - name: crypto - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.3" - dartz: - dependency: transitive - description: - name: dartz - url: "https://pub.dartlang.org" - source: hosted - version: "0.10.0-nullsafety.2" - equatable: - dependency: transitive - description: - name: equatable - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.3" - fake_async: - dependency: transitive - description: - name: fake_async - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - flowy_infra: - dependency: transitive - description: - path: "../../flowy_infra" - relative: true - source: path - version: "0.0.1" - flowy_infra_ui: - dependency: "direct main" - description: - path: ".." - relative: true - source: path - version: "0.0.1" - flowy_infra_ui_platform_interface: - dependency: transitive - description: - path: "../flowy_infra_ui_platform_interface" - relative: true - source: path - version: "0.0.1" - flowy_infra_ui_web: - dependency: transitive - description: - path: "../flowy_infra_ui_web" - relative: true - source: path - version: "0.0.1" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.4" - flutter_svg: - dependency: transitive - description: - name: flutter_svg - url: "https://pub.dartlang.org" - source: hosted - version: "0.22.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - js: - dependency: transitive - description: - name: js - url: "https://pub.dartlang.org" - source: hosted - version: "0.6.3" - lint: - dependency: transitive - description: - name: lint - url: "https://pub.dartlang.org" - source: hosted - version: "1.5.3" - lints: - dependency: transitive - description: - name: lints - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - loading_indicator: - dependency: transitive - description: - name: loading_indicator - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.11" - meta: - dependency: transitive - description: - name: meta - url: "https://pub.dartlang.org" - source: hosted - version: "1.7.0" - nested: - dependency: transitive - description: - name: nested - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - path: - dependency: transitive - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0" - path_drawing: - dependency: transitive - description: - name: path_drawing - url: "https://pub.dartlang.org" - source: hosted - version: "0.5.1+1" - path_parsing: - dependency: transitive - description: - name: path_parsing - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.1" - petitparser: - dependency: transitive - description: - name: petitparser - url: "https://pub.dartlang.org" - source: hosted - version: "4.4.0" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - provider: - dependency: transitive - description: - name: provider - url: "https://pub.dartlang.org" - source: hosted - version: "6.0.1" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.10.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - styled_widget: - dependency: transitive - description: - name: styled_widget - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.1+2" - term_glyph: - dependency: transitive - description: - name: term_glyph - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - test_api: - dependency: transitive - description: - name: test_api - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.3" - textstyle_extensions: - dependency: transitive - description: - name: textstyle_extensions - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0-nullsafety" - time: - dependency: transitive - description: - name: time - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - uuid: - dependency: transitive - description: - name: uuid - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.4" - vector_math: - dependency: transitive - description: - name: vector_math - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - xml: - dependency: transitive - description: - name: xml - url: "https://pub.dartlang.org" - source: hosted - version: "5.3.1" -sdks: - dart: ">=2.14.0 <3.0.0" - flutter: ">=2.0.0" diff --git a/frontend/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/pubspec.lock b/frontend/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/pubspec.lock deleted file mode 100644 index a2ed8a8fe8..0000000000 --- a/frontend/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/pubspec.lock +++ /dev/null @@ -1,168 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - async: - dependency: transitive - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "2.6.1" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - characters: - dependency: transitive - description: - name: characters - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - clock: - dependency: transitive - description: - name: clock - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - collection: - dependency: transitive - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.15.0" - fake_async: - dependency: transitive - description: - name: fake_async - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.4" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - lints: - dependency: transitive - description: - name: lints - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.10" - meta: - dependency: transitive - description: - name: meta - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - path: - dependency: transitive - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0" - plugin_platform_interface: - dependency: "direct main" - description: - name: plugin_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.10.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - test_api: - dependency: transitive - description: - name: test_api - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.0" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - vector_math: - dependency: transitive - description: - name: vector_math - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" -sdks: - dart: ">=2.12.0 <3.0.0" - flutter: ">=1.17.0" diff --git a/frontend/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/pubspec.lock b/frontend/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/pubspec.lock deleted file mode 100644 index 804b67b5b9..0000000000 --- a/frontend/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/pubspec.lock +++ /dev/null @@ -1,187 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - async: - dependency: transitive - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "2.6.1" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - characters: - dependency: transitive - description: - name: characters - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - clock: - dependency: transitive - description: - name: clock - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - collection: - dependency: transitive - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.15.0" - fake_async: - dependency: transitive - description: - name: fake_async - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - flowy_infra_ui_platform_interface: - dependency: "direct main" - description: - path: "../flowy_infra_ui_platform_interface" - relative: true - source: path - version: "0.0.1" - flutter: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.4" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - js: - dependency: transitive - description: - name: js - url: "https://pub.dartlang.org" - source: hosted - version: "0.6.3" - lints: - dependency: transitive - description: - name: lints - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.10" - meta: - dependency: transitive - description: - name: meta - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - path: - dependency: transitive - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.10.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - test_api: - dependency: transitive - description: - name: test_api - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.0" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - vector_math: - dependency: transitive - description: - name: vector_math - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" -sdks: - dart: ">=2.12.0 <3.0.0" - flutter: ">=1.17.0" diff --git a/frontend/app_flowy/packages/flowy_infra_ui/pubspec.lock b/frontend/app_flowy/packages/flowy_infra_ui/pubspec.lock deleted file mode 100644 index 8ff7b9870b..0000000000 --- a/frontend/app_flowy/packages/flowy_infra_ui/pubspec.lock +++ /dev/null @@ -1,320 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - animations: - dependency: "direct main" - description: - name: animations - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - async: - dependency: transitive - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "2.8.2" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - characters: - dependency: transitive - description: - name: characters - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" - clock: - dependency: transitive - description: - name: clock - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - collection: - dependency: transitive - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.15.0" - crypto: - dependency: transitive - description: - name: crypto - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" - dartz: - dependency: "direct main" - description: - name: dartz - url: "https://pub.dartlang.org" - source: hosted - version: "0.10.0-nullsafety.2" - equatable: - dependency: "direct main" - description: - name: equatable - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.3" - fake_async: - dependency: transitive - description: - name: fake_async - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - flowy_infra: - dependency: "direct main" - description: - path: "../flowy_infra" - relative: true - source: path - version: "0.0.1" - flowy_infra_ui_platform_interface: - dependency: "direct main" - description: - path: flowy_infra_ui_platform_interface - relative: true - source: path - version: "0.0.1" - flowy_infra_ui_web: - dependency: "direct main" - description: - path: flowy_infra_ui_web - relative: true - source: path - version: "0.0.1" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.4" - flutter_svg: - dependency: transitive - description: - name: flutter_svg - url: "https://pub.dartlang.org" - source: hosted - version: "0.22.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - js: - dependency: transitive - description: - name: js - url: "https://pub.dartlang.org" - source: hosted - version: "0.6.3" - lint: - dependency: transitive - description: - name: lint - url: "https://pub.dartlang.org" - source: hosted - version: "1.5.3" - lints: - dependency: transitive - description: - name: lints - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - loading_indicator: - dependency: "direct main" - description: - name: loading_indicator - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.11" - meta: - dependency: transitive - description: - name: meta - url: "https://pub.dartlang.org" - source: hosted - version: "1.7.0" - nested: - dependency: transitive - description: - name: nested - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - path: - dependency: transitive - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0" - path_drawing: - dependency: transitive - description: - name: path_drawing - url: "https://pub.dartlang.org" - source: hosted - version: "0.5.1+1" - path_parsing: - dependency: transitive - description: - name: path_parsing - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.1" - petitparser: - dependency: transitive - description: - name: petitparser - url: "https://pub.dartlang.org" - source: hosted - version: "4.4.0" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - provider: - dependency: "direct main" - description: - name: provider - url: "https://pub.dartlang.org" - source: hosted - version: "6.0.1" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.10.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - styled_widget: - dependency: "direct main" - description: - name: styled_widget - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.1+2" - term_glyph: - dependency: transitive - description: - name: term_glyph - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - test_api: - dependency: transitive - description: - name: test_api - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.3" - textstyle_extensions: - dependency: "direct main" - description: - name: textstyle_extensions - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0-nullsafety" - time: - dependency: transitive - description: - name: time - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - uuid: - dependency: transitive - description: - name: uuid - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.4" - vector_math: - dependency: transitive - description: - name: vector_math - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - xml: - dependency: transitive - description: - name: xml - url: "https://pub.dartlang.org" - source: hosted - version: "5.3.1" -sdks: - dart: ">=2.14.0 <3.0.0" - flutter: ">=2.0.0" diff --git a/frontend/app_flowy/packages/flowy_sdk/example/pubspec.lock b/frontend/app_flowy/packages/flowy_sdk/example/pubspec.lock deleted file mode 100644 index 921bd4fb2b..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/example/pubspec.lock +++ /dev/null @@ -1,309 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - archive: - dependency: transitive - description: - name: archive - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.6" - async: - dependency: transitive - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "2.8.2" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - characters: - dependency: transitive - description: - name: characters - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" - clock: - dependency: transitive - description: - name: clock - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - collection: - dependency: transitive - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.15.0" - crypto: - dependency: transitive - description: - name: crypto - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" - dartz: - dependency: transitive - description: - name: dartz - url: "https://pub.dartlang.org" - source: hosted - version: "0.10.0-nullsafety.2" - fake_async: - dependency: transitive - description: - name: fake_async - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - ffi: - dependency: transitive - description: - name: ffi - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - file: - dependency: transitive - description: - name: file - url: "https://pub.dartlang.org" - source: hosted - version: "6.1.2" - fixnum: - dependency: transitive - description: - name: fixnum - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - flowy_sdk: - dependency: "direct main" - description: - path: ".." - relative: true - source: path - version: "0.0.1" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_driver: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.3" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - freezed_annotation: - dependency: transitive - description: - name: freezed_annotation - url: "https://pub.dartlang.org" - source: hosted - version: "0.14.1" - fuchsia_remote_debug_protocol: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - integration_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - isolates: - dependency: transitive - description: - name: isolates - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.3+8" - json_annotation: - dependency: transitive - description: - name: json_annotation - url: "https://pub.dartlang.org" - source: hosted - version: "4.0.1" - lints: - dependency: transitive - description: - name: lints - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - logger: - dependency: transitive - description: - name: logger - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.11" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.3" - meta: - dependency: transitive - description: - name: meta - url: "https://pub.dartlang.org" - source: hosted - version: "1.7.0" - path: - dependency: transitive - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0" - platform: - dependency: transitive - description: - name: platform - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.0" - process: - dependency: transitive - description: - name: process - url: "https://pub.dartlang.org" - source: hosted - version: "4.2.4" - protobuf: - dependency: transitive - description: - name: protobuf - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.10.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - sync_http: - dependency: transitive - description: - name: sync_http - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - test_api: - dependency: transitive - description: - name: test_api - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.8" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - vector_math: - dependency: transitive - description: - name: vector_math - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" - vm_service: - dependency: transitive - description: - name: vm_service - url: "https://pub.dartlang.org" - source: hosted - version: "7.5.0" - webdriver: - dependency: transitive - description: - name: webdriver - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.0" -sdks: - dart: ">=2.14.0 <3.0.0" - flutter: ">=1.17.0" diff --git a/frontend/app_flowy/packages/flowy_sdk/pubspec.lock b/frontend/app_flowy/packages/flowy_sdk/pubspec.lock deleted file mode 100644 index 1f5af870d9..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/pubspec.lock +++ /dev/null @@ -1,504 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - url: "https://pub.dartlang.org" - source: hosted - version: "20.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - url: "https://pub.dartlang.org" - source: hosted - version: "1.4.0" - args: - dependency: transitive - description: - name: args - url: "https://pub.dartlang.org" - source: hosted - version: "1.6.0" - async: - dependency: transitive - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "2.8.2" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - build: - dependency: transitive - description: - name: build - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - build_config: - dependency: transitive - description: - name: build_config - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.7" - build_daemon: - dependency: transitive - description: - name: build_daemon - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.10" - build_resolvers: - dependency: transitive - description: - name: build_resolvers - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - build_runner: - dependency: "direct dev" - description: - name: build_runner - url: "https://pub.dartlang.org" - source: hosted - version: "1.12.2" - build_runner_core: - dependency: transitive - description: - name: build_runner_core - url: "https://pub.dartlang.org" - source: hosted - version: "6.1.12" - built_collection: - dependency: transitive - description: - name: built_collection - url: "https://pub.dartlang.org" - source: hosted - version: "5.1.0" - built_value: - dependency: transitive - description: - name: built_value - url: "https://pub.dartlang.org" - source: hosted - version: "8.1.0" - characters: - dependency: transitive - description: - name: characters - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" - checked_yaml: - dependency: transitive - description: - name: checked_yaml - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - cli_util: - dependency: transitive - description: - name: cli_util - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.0" - clock: - dependency: transitive - description: - name: clock - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - code_builder: - dependency: transitive - description: - name: code_builder - url: "https://pub.dartlang.org" - source: hosted - version: "3.6.0" - collection: - dependency: transitive - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.15.0" - convert: - dependency: transitive - description: - name: convert - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.0" - crypto: - dependency: transitive - description: - name: crypto - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" - dart_style: - dependency: transitive - description: - name: dart_style - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - dartz: - dependency: "direct main" - description: - name: dartz - url: "https://pub.dartlang.org" - source: hosted - version: "0.10.0-nullsafety.2" - fake_async: - dependency: transitive - description: - name: fake_async - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - ffi: - dependency: "direct main" - description: - name: ffi - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - file: - dependency: transitive - description: - name: file - url: "https://pub.dartlang.org" - source: hosted - version: "6.1.0" - fixnum: - dependency: transitive - description: - name: fixnum - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.3" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - freezed: - dependency: "direct dev" - description: - name: freezed - url: "https://pub.dartlang.org" - source: hosted - version: "0.14.1+2" - freezed_annotation: - dependency: "direct main" - description: - name: freezed_annotation - url: "https://pub.dartlang.org" - source: hosted - version: "0.14.1" - glob: - dependency: transitive - description: - name: glob - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - graphs: - dependency: transitive - description: - name: graphs - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.0" - http_parser: - dependency: transitive - description: - name: http_parser - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.4" - io: - dependency: transitive - description: - name: io - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.4" - isolates: - dependency: "direct main" - description: - name: isolates - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.3+8" - js: - dependency: transitive - description: - name: js - url: "https://pub.dartlang.org" - source: hosted - version: "0.6.3" - json_annotation: - dependency: transitive - description: - name: json_annotation - url: "https://pub.dartlang.org" - source: hosted - version: "4.0.1" - lints: - dependency: transitive - description: - name: lints - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - logger: - dependency: "direct main" - description: - name: logger - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - logging: - dependency: transitive - description: - name: logging - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.11" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.3" - meta: - dependency: transitive - description: - name: meta - url: "https://pub.dartlang.org" - source: hosted - version: "1.7.0" - mime: - dependency: transitive - description: - name: mime - url: "https://pub.dartlang.org" - source: hosted - version: "0.9.7" - package_config: - dependency: transitive - description: - name: package_config - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - path: - dependency: transitive - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.11.0" - pool: - dependency: transitive - description: - name: pool - url: "https://pub.dartlang.org" - source: hosted - version: "1.5.0" - protobuf: - dependency: "direct main" - description: - name: protobuf - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - pub_semver: - dependency: transitive - description: - name: pub_semver - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - pubspec_parse: - dependency: transitive - description: - name: pubspec_parse - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - shelf: - dependency: transitive - description: - name: shelf - url: "https://pub.dartlang.org" - source: hosted - version: "0.7.9" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.3" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_gen: - dependency: transitive - description: - name: source_gen - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - source_span: - dependency: transitive - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.10.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - stream_transform: - dependency: transitive - description: - name: stream_transform - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - test_api: - dependency: transitive - description: - name: test_api - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.8" - timing: - dependency: transitive - description: - name: timing - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.1+3" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - vector_math: - dependency: transitive - description: - name: vector_math - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" - watcher: - dependency: transitive - description: - name: watcher - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - yaml: - dependency: transitive - description: - name: yaml - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.0" -sdks: - dart: ">=2.14.0 <3.0.0" - flutter: ">=1.17.0"