fix: cell focus issue on windows (#2880)

* fix: cell focus issue on windows

* fix: try to fix

* fix: cell focus not working on Windows platform there are multiple text cells

* docs: add documentation

* chore: adjust row detail page ui

* test: add test

* test: fix test

---------

Co-authored-by: vedon <vedon.fu@gmail.com>
This commit is contained in:
Nathan.fooo 2023-06-22 20:16:31 +08:00 committed by GitHub
parent f1bfcb6066
commit a29c8ab27a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 169 additions and 92 deletions

View File

@ -1,4 +1,5 @@
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart'; import 'package:integration_test/integration_test.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
@ -47,6 +48,44 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
}); });
// Makesure the text cells are filled with the right content when there are
// multiple text cell
testWidgets('edit multiple text cells', (tester) async {
await tester.initializeAppFlowy();
await tester.tapGoButton();
await tester.createNewPageWithName(ViewLayoutPB.Grid, 'my grid');
await tester.createField(FieldType.RichText, 'description');
await tester.editCell(
rowIndex: 0,
fieldType: FieldType.RichText,
input: 'hello',
);
await tester.editCell(
rowIndex: 0,
fieldType: FieldType.RichText,
input: 'world',
cellIndex: 1,
);
await tester.assertCellContent(
rowIndex: 0,
fieldType: FieldType.RichText,
content: 'hello',
cellIndex: 0,
);
await tester.assertCellContent(
rowIndex: 0,
fieldType: FieldType.RichText,
content: 'world',
cellIndex: 1,
);
await tester.pumpAndSettle();
});
testWidgets('edit number cell', (tester) async { testWidgets('edit number cell', (tester) async {
await tester.initializeAppFlowy(); await tester.initializeAppFlowy();
await tester.tapGoButton(); await tester.tapGoButton();

View File

@ -108,22 +108,26 @@ extension AppFlowyDatabaseTest on WidgetTester {
required int rowIndex, required int rowIndex,
required FieldType fieldType, required FieldType fieldType,
required String input, required String input,
int cellIndex = 0,
}) async { }) async {
final cell = cellFinder(rowIndex, fieldType); final cell = cellFinder(rowIndex, fieldType, cellIndex: cellIndex);
expect(cell, findsOneWidget); expect(cell, findsOneWidget);
await enterText(cell, input); await enterText(cell, input);
await pumpAndSettle(); await pumpAndSettle();
} }
Finder cellFinder(int rowIndex, FieldType fieldType) { ///
Finder cellFinder(int rowIndex, FieldType fieldType, {int cellIndex = 0}) {
final findRow = find.byType(GridRow, skipOffstage: false); final findRow = find.byType(GridRow, skipOffstage: false);
final findCell = finderForFieldType(fieldType); final findCell = finderForFieldType(fieldType);
return find.descendant( return find
.descendant(
of: findRow.at(rowIndex), of: findRow.at(rowIndex),
matching: findCell, matching: findCell,
skipOffstage: false, skipOffstage: false,
); )
.at(cellIndex);
} }
Future<void> tapCheckboxCellInGrid({ Future<void> tapCheckboxCellInGrid({
@ -173,8 +177,9 @@ extension AppFlowyDatabaseTest on WidgetTester {
required int rowIndex, required int rowIndex,
required FieldType fieldType, required FieldType fieldType,
required String content, required String content,
int cellIndex = 0,
}) async { }) async {
final findCell = cellFinder(rowIndex, fieldType); final findCell = cellFinder(rowIndex, fieldType, cellIndex: cellIndex);
final findContent = find.descendant( final findContent = find.descendant(
of: findCell, of: findCell,
matching: find.text(content), matching: find.text(content),

View File

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database_view/application/row/row_service.dart'; import 'package:appflowy/plugins/database_view/application/row/row_service.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/toolbar/grid_setting_bar.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/toolbar/grid_setting_bar.dart';
@ -241,7 +243,40 @@ class _GridRows extends StatelessWidget {
); );
return ScrollConfiguration( return ScrollConfiguration(
behavior: behavior, behavior: behavior,
child: ReorderableListView.builder( child: _renderList(context, state, rowInfos),
);
},
),
),
);
}
Widget _renderList(
BuildContext context,
GridState state,
List<RowInfo> rowInfos,
) {
if (Platform.isWindows) {
// Workaround: On Windows, the focusing of the text cell is not working
// properly when the list is reorderable. So using the ListView instead.
return ListView.builder(
controller: scrollController.verticalController,
itemCount: rowInfos.length + 1, // the extra item is the footer
itemBuilder: (context, index) {
if (index < rowInfos.length) {
final rowInfo = rowInfos[index];
return _renderRow(
context,
rowInfo.rowId,
isDraggable: false,
index: index,
);
}
return const GridRowBottomBar(key: Key('gridFooter'));
},
);
} else {
return ReorderableListView.builder(
/// TODO(Xazin): Resolve inconsistent scrollbar behavior /// TODO(Xazin): Resolve inconsistent scrollbar behavior
/// This is a workaround related to /// This is a workaround related to
/// https://github.com/flutter/flutter/issues/25652 /// https://github.com/flutter/flutter/issues/25652
@ -253,14 +288,11 @@ class _GridRows extends StatelessWidget {
child: Opacity(opacity: .5, child: child), child: Opacity(opacity: .5, child: child),
), ),
onReorder: (fromIndex, newIndex) { onReorder: (fromIndex, newIndex) {
final toIndex = final toIndex = newIndex > fromIndex ? newIndex - 1 : newIndex;
newIndex > fromIndex ? newIndex - 1 : newIndex;
if (fromIndex == toIndex) { if (fromIndex == toIndex) {
return; return;
} }
context context.read<GridBloc>().add(GridEvent.moveRow(fromIndex, toIndex));
.read<GridBloc>()
.add(GridEvent.moveRow(fromIndex, toIndex));
}, },
itemCount: rowInfos.length + 1, // the extra item is the footer itemCount: rowInfos.length + 1, // the extra item is the footer
itemBuilder: (context, index) { itemBuilder: (context, index) {
@ -275,13 +307,9 @@ class _GridRows extends StatelessWidget {
} }
return const GridRowBottomBar(key: Key('gridFooter')); return const GridRowBottomBar(key: Key('gridFooter'));
}, },
),
);
},
),
),
); );
} }
}
Widget _renderRow( Widget _renderRow(
BuildContext context, BuildContext context,

View File

@ -138,7 +138,6 @@ class _OptionNameTextField extends StatelessWidget {
return FlowyTextField( return FlowyTextField(
autoFocus: autoFocus, autoFocus: autoFocus,
text: name, text: name,
maxLength: 30,
submitOnLeave: true, submitOnLeave: true,
onSubmitted: (newName) { onSubmitted: (newName) {
if (name != newName) { if (name != newName) {

View File

@ -103,11 +103,11 @@ class BlankCell extends StatelessWidget {
} }
abstract class CellEditable { abstract class CellEditable {
GridCellFocusListener get beginFocus; RequestFocusListener get requestFocus;
ValueNotifier<bool> get onCellFocus; ValueNotifier<bool> get onCellFocus;
ValueNotifier<bool> get onCellEditing; // ValueNotifier<bool> get onCellEditing;
} }
typedef AccessoryBuilder = List<GridCellAccessoryBuilder> Function( typedef AccessoryBuilder = List<GridCellAccessoryBuilder> Function(
@ -125,11 +125,7 @@ abstract class CellAccessory extends Widget {
abstract class GridCellWidget extends StatefulWidget abstract class GridCellWidget extends StatefulWidget
implements CellAccessory, CellEditable, CellShortcuts { implements CellAccessory, CellEditable, CellShortcuts {
GridCellWidget({Key? key}) : super(key: key) { GridCellWidget({super.key});
onCellEditing.addListener(() {
onCellFocus.value = onCellEditing.value;
});
}
@override @override
final ValueNotifier<bool> onCellFocus = ValueNotifier<bool>(false); final ValueNotifier<bool> onCellFocus = ValueNotifier<bool>(false);
@ -138,8 +134,8 @@ abstract class GridCellWidget extends StatefulWidget
@override @override
ValueNotifier<bool> get onAccessoryHover => onCellFocus; ValueNotifier<bool> get onAccessoryHover => onCellFocus;
@override // @override
final ValueNotifier<bool> onCellEditing = ValueNotifier<bool>(false); // final ValueNotifier<bool> onCellEditing = ValueNotifier<bool>(false);
@override @override
List<GridCellAccessoryBuilder> Function( List<GridCellAccessoryBuilder> Function(
@ -147,7 +143,7 @@ abstract class GridCellWidget extends StatefulWidget
)? get accessoryBuilder => null; )? get accessoryBuilder => null;
@override @override
final GridCellFocusListener beginFocus = GridCellFocusListener(); final RequestFocusListener requestFocus = RequestFocusListener();
@override @override
final Map<CellKeyboardKey, CellKeyboardAction> shortcutHandlers = {}; final Map<CellKeyboardKey, CellKeyboardAction> shortcutHandlers = {};
@ -156,7 +152,7 @@ abstract class GridCellWidget extends StatefulWidget
abstract class GridCellState<T extends GridCellWidget> extends State<T> { abstract class GridCellState<T extends GridCellWidget> extends State<T> {
@override @override
void initState() { void initState() {
widget.beginFocus.setListener(() => requestBeginFocus()); widget.requestFocus.setListener(requestBeginFocus);
widget.shortcutHandlers[CellKeyboardKey.onCopy] = () => onCopy(); widget.shortcutHandlers[CellKeyboardKey.onCopy] = () => onCopy();
widget.shortcutHandlers[CellKeyboardKey.onInsert] = () { widget.shortcutHandlers[CellKeyboardKey.onInsert] = () {
Clipboard.getData("text/plain").then((data) { Clipboard.getData("text/plain").then((data) {
@ -172,17 +168,18 @@ abstract class GridCellState<T extends GridCellWidget> extends State<T> {
@override @override
void didUpdateWidget(covariant T oldWidget) { void didUpdateWidget(covariant T oldWidget) {
if (oldWidget != this) { if (oldWidget != this) {
widget.beginFocus.setListener(() => requestBeginFocus()); widget.requestFocus.setListener(requestBeginFocus);
} }
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
} }
@override @override
void dispose() { void dispose() {
widget.beginFocus.removeAllListener(); widget.requestFocus.removeAllListener();
super.dispose(); super.dispose();
} }
/// Subclass can override this method to request focus.
void requestBeginFocus(); void requestBeginFocus();
String? onCopy() => null; String? onCopy() => null;
@ -190,9 +187,9 @@ abstract class GridCellState<T extends GridCellWidget> extends State<T> {
void onInsert(String value) {} void onInsert(String value) {}
} }
abstract class GridFocusNodeCellState<T extends GridCellWidget> abstract class GridEditableTextCell<T extends GridCellWidget>
extends GridCellState<T> { extends GridCellState<T> {
SingleListenerFocusNode focusNode = SingleListenerFocusNode(); SingleListenerFocusNode get focusNode;
@override @override
void initState() { void initState() {
@ -226,9 +223,9 @@ abstract class GridFocusNodeCellState<T extends GridCellWidget>
} }
void _listenOnFocusNodeChanged() { void _listenOnFocusNodeChanged() {
widget.onCellEditing.value = focusNode.hasFocus; widget.onCellFocus.value = focusNode.hasFocus;
focusNode.setListener(() { focusNode.setListener(() {
widget.onCellEditing.value = focusNode.hasFocus; widget.onCellFocus.value = focusNode.hasFocus;
focusChanged(); focusChanged();
}); });
} }
@ -236,7 +233,7 @@ abstract class GridFocusNodeCellState<T extends GridCellWidget>
Future<void> focusChanged() async {} Future<void> focusChanged() async {}
} }
class GridCellFocusListener extends ChangeNotifier { class RequestFocusListener extends ChangeNotifier {
VoidCallback? _listener; VoidCallback? _listener;
void setListener(VoidCallback listener) { void setListener(VoidCallback listener) {

View File

@ -51,8 +51,8 @@ class CellContainer extends StatelessWidget {
} }
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.opaque,
onTap: () => child.beginFocus.notify(), onTap: () => child.requestFocus.notify(),
child: Container( child: Container(
constraints: BoxConstraints(maxWidth: width, minHeight: 46), constraints: BoxConstraints(maxWidth: width, minHeight: 46),
decoration: _makeBoxDecoration(context, isFocus), decoration: _makeBoxDecoration(context, isFocus),

View File

@ -45,14 +45,14 @@ class GridChecklistCellState extends GridCellState<GridChecklistCell> {
triggerActions: PopoverTriggerFlags.none, triggerActions: PopoverTriggerFlags.none,
popupBuilder: (BuildContext context) { popupBuilder: (BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
widget.onCellEditing.value = true; widget.onCellFocus.value = true;
}); });
return GridChecklistCellEditor( return GridChecklistCellEditor(
cellController: cellController:
widget.cellControllerBuilder.build() as ChecklistCellController, widget.cellControllerBuilder.build() as ChecklistCellController,
); );
}, },
onClose: () => widget.onCellEditing.value = false, onClose: () => widget.onCellFocus.value = false,
child: Padding( child: Padding(
padding: GridSize.cellContentInsets, padding: GridSize.cellContentInsets,
child: BlocBuilder<ChecklistCardCellBloc, ChecklistCellState>( child: BlocBuilder<ChecklistCardCellBloc, ChecklistCellState>(

View File

@ -90,11 +90,11 @@ class _DateCellState extends GridCellState<GridDateCell> {
return DateCellEditor( return DateCellEditor(
cellController: widget.cellControllerBuilder.build() cellController: widget.cellControllerBuilder.build()
as DateCellController, as DateCellController,
onDismissed: () => widget.onCellEditing.value = false, onDismissed: () => widget.onCellFocus.value = false,
); );
}, },
onClose: () { onClose: () {
widget.onCellEditing.value = false; widget.onCellFocus.value = false;
}, },
); );
} }
@ -115,7 +115,7 @@ class _DateCellState extends GridCellState<GridDateCell> {
_popover.show(); _popover.show();
if (widget.editable) { if (widget.editable) {
widget.onCellEditing.value = true; widget.onCellFocus.value = true;
} }
} }

View File

@ -16,13 +16,16 @@ class GridNumberCell extends GridCellWidget {
}) : super(key: key); }) : super(key: key);
@override @override
GridFocusNodeCellState<GridNumberCell> createState() => _NumberCellState(); GridEditableTextCell<GridNumberCell> createState() => _NumberCellState();
} }
class _NumberCellState extends GridFocusNodeCellState<GridNumberCell> { class _NumberCellState extends GridEditableTextCell<GridNumberCell> {
late NumberCellBloc _cellBloc; late NumberCellBloc _cellBloc;
late TextEditingController _controller; late TextEditingController _controller;
@override
SingleListenerFocusNode focusNode = SingleListenerFocusNode();
@override @override
void initState() { void initState() {
final cellController = final cellController =

View File

@ -62,7 +62,7 @@ class _SingleSelectCellState extends GridCellState<GridSingleSelectCell> {
return SelectOptionWrap( return SelectOptionWrap(
selectOptions: state.selectedOptions, selectOptions: state.selectedOptions,
cellStyle: widget.cellStyle, cellStyle: widget.cellStyle,
onCellEditing: widget.onCellEditing, onCellEditing: widget.onCellFocus,
popoverController: _popover, popoverController: _popover,
cellControllerBuilder: widget.cellControllerBuilder, cellControllerBuilder: widget.cellControllerBuilder,
); );
@ -125,7 +125,7 @@ class _MultiSelectCellState extends GridCellState<GridMultiSelectCell> {
return SelectOptionWrap( return SelectOptionWrap(
selectOptions: state.selectedOptions, selectOptions: state.selectedOptions,
cellStyle: widget.cellStyle, cellStyle: widget.cellStyle,
onCellEditing: widget.onCellEditing, onCellEditing: widget.onCellFocus,
popoverController: _popover, popoverController: _popover,
cellControllerBuilder: widget.cellControllerBuilder, cellControllerBuilder: widget.cellControllerBuilder,
); );

View File

@ -157,7 +157,6 @@ class _TextField extends StatelessWidget {
options: state.options, options: state.options,
selectedOptionMap: optionMap, selectedOptionMap: optionMap,
distanceToText: _editorPanelWidth * 0.7, distanceToText: _editorPanelWidth * 0.7,
maxLength: 30,
tagController: tagController, tagController: tagController,
textSeparators: const [','], textSeparators: const [','],
onClick: () => popoverMutex.close(), onClick: () => popoverMutex.close(),

View File

@ -41,13 +41,16 @@ class GridTextCell extends GridCellWidget {
} }
@override @override
GridFocusNodeCellState<GridTextCell> createState() => _GridTextCellState(); GridEditableTextCell<GridTextCell> createState() => _GridTextCellState();
} }
class _GridTextCellState extends GridFocusNodeCellState<GridTextCell> { class _GridTextCellState extends GridEditableTextCell<GridTextCell> {
late TextCellBloc _cellBloc; late TextCellBloc _cellBloc;
late TextEditingController _controller; late TextEditingController _controller;
@override
SingleListenerFocusNode focusNode = SingleListenerFocusNode();
@override @override
void initState() { void initState() {
final cellController = final cellController =

View File

@ -108,11 +108,14 @@ class GridURLCell extends GridCellWidget {
} }
} }
class _GridURLCellState extends GridFocusNodeCellState<GridURLCell> { class _GridURLCellState extends GridEditableTextCell<GridURLCell> {
final _popoverController = PopoverController(); final _popoverController = PopoverController();
late final URLCellBloc _cellBloc; late final URLCellBloc _cellBloc;
late final TextEditingController _controller; late final TextEditingController _controller;
@override
SingleListenerFocusNode focusNode = SingleListenerFocusNode();
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -182,7 +185,7 @@ class _GridURLCellState extends GridFocusNodeCellState<GridURLCell> {
@override @override
void requestBeginFocus() { void requestBeginFocus() {
widget.onCellEditing.value = true; widget.onCellFocus.value = true;
_popoverController.show(); _popoverController.show();
} }

View File

@ -85,8 +85,8 @@ class _PropertyCellState extends State<_PropertyCell> {
final cell = widget.cellBuilder.build(widget.cellContext, style: style); final cell = widget.cellBuilder.build(widget.cellContext, style: style);
final gesture = GestureDetector( final gesture = GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.opaque,
onTap: () => cell.beginFocus.notify(), onTap: () => cell.requestFocus.notify(),
child: AccessoryHover( child: AccessoryHover(
contentPadding: const EdgeInsets.symmetric(horizontal: 3, vertical: 3), contentPadding: const EdgeInsets.symmetric(horizontal: 3, vertical: 3),
child: cell, child: cell,
@ -97,8 +97,8 @@ class _PropertyCellState extends State<_PropertyCell> {
child: ConstrainedBox( child: ConstrainedBox(
constraints: const BoxConstraints(minHeight: 30), constraints: const BoxConstraints(minHeight: 30),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
AppFlowyPopover( AppFlowyPopover(
controller: popover, controller: popover,
@ -108,6 +108,7 @@ class _PropertyCellState extends State<_PropertyCell> {
popupBuilder: (popoverContext) => buildFieldEditor(), popupBuilder: (popoverContext) => buildFieldEditor(),
child: SizedBox( child: SizedBox(
width: 150, width: 150,
height: 40,
child: FieldCellButton( child: FieldCellButton(
field: widget.cellContext.fieldInfo.field, field: widget.cellContext.fieldInfo.field,
onTap: () => popover.show(), onTap: () => popover.show(),

View File

@ -105,7 +105,7 @@ checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
[[package]] [[package]]
name = "appflowy-integrate" name = "appflowy-integrate"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=e9f7fc#e9f7fc76192f2dbb2379f1a02310047763bd4426" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",
@ -1030,7 +1030,7 @@ dependencies = [
[[package]] [[package]]
name = "collab" name = "collab"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=e9f7fc#e9f7fc76192f2dbb2379f1a02310047763bd4426" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@ -1048,7 +1048,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-client-ws" name = "collab-client-ws"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=e9f7fc#e9f7fc76192f2dbb2379f1a02310047763bd4426" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
dependencies = [ dependencies = [
"bytes", "bytes",
"collab-sync", "collab-sync",
@ -1066,7 +1066,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-database" name = "collab-database"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=e9f7fc#e9f7fc76192f2dbb2379f1a02310047763bd4426" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -1092,7 +1092,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-derive" name = "collab-derive"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=e9f7fc#e9f7fc76192f2dbb2379f1a02310047763bd4426" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1104,7 +1104,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-document" name = "collab-document"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=e9f7fc#e9f7fc76192f2dbb2379f1a02310047763bd4426" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",
@ -1122,7 +1122,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-folder" name = "collab-folder"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=e9f7fc#e9f7fc76192f2dbb2379f1a02310047763bd4426" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
@ -1142,7 +1142,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-persistence" name = "collab-persistence"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=e9f7fc#e9f7fc76192f2dbb2379f1a02310047763bd4426" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
dependencies = [ dependencies = [
"bincode", "bincode",
"chrono", "chrono",
@ -1162,7 +1162,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-plugins" name = "collab-plugins"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=e9f7fc#e9f7fc76192f2dbb2379f1a02310047763bd4426" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -1193,7 +1193,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-sync" name = "collab-sync"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=e9f7fc#e9f7fc76192f2dbb2379f1a02310047763bd4426" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=06e942#06e942cb6433c94b5ecfe1d431b64bba625fc09c"
dependencies = [ dependencies = [
"bytes", "bytes",
"collab", "collab",