From 6078e46d3dae3f8db7ae72f01738b8acb735737e Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 25 Feb 2022 22:27:44 +0800 Subject: [PATCH 01/12] refactor: rename structs --- .../workspace/application/doc/doc_bloc.dart | 4 +- .../infrastructure/repos/document_repo.dart | 8 +- .../infrastructure/repos/share_repo.dart | 2 +- .../dart_event/flowy-folder/dart_event.dart | 10 +- .../flowy-collaboration/document_info.pb.dart | 120 ++++----- .../document_info.pbjson.dart | 42 ++-- .../flowy-folder-data-model/share.pb.dart | 16 +- .../flowy-folder-data-model/share.pbjson.dart | 4 +- frontend/rust-lib/Cargo.lock | 1 + .../rust-lib/flowy-document/src/editor.rs | 44 ++-- frontend/rust-lib/flowy-document/src/lib.rs | 10 +- .../rust-lib/flowy-document/src/manager.rs | 152 ++++++------ frontend/rust-lib/flowy-document/src/queue.rs | 18 +- .../rust-lib/flowy-document/src/web_socket.rs | 75 +++--- .../tests/document/edit_script.rs | 6 +- .../rust-lib/flowy-folder/src/controller.rs | 4 +- .../rust-lib/flowy-folder/src/event_map.rs | 8 +- .../src/services/app/event_handler.rs | 14 +- .../src/services/folder_editor.rs | 8 +- .../src/services/trash/event_handler.rs | 12 +- .../src/services/view/controller.rs | 56 ++--- .../src/services/view/event_handler.rs | 42 ++-- .../flowy-folder/src/services/web_socket.rs | 52 ++-- .../src/services/workspace/event_handler.rs | 14 +- .../flowy-folder/tests/workspace/helper.rs | 6 +- .../flowy-folder/tests/workspace/script.rs | 4 +- .../rust-lib/flowy-net/src/handlers/mod.rs | 4 +- .../flowy-net/src/http_server/document.rs | 24 +- .../flowy-net/src/local_server/persistence.rs | 6 +- .../flowy-net/src/local_server/server.rs | 14 +- .../src/deps_resolve/document_deps.rs | 22 +- .../flowy-sdk/src/deps_resolve/folder_deps.rs | 10 +- frontend/rust-lib/flowy-sdk/src/lib.rs | 4 +- frontend/rust-lib/flowy-sync/Cargo.toml | 2 +- frontend/rust-lib/flowy-sync/src/cache/mod.rs | 6 +- .../flowy-sync/src/conflict_resolve.rs | 24 +- .../rust-lib/flowy-sync/src/rev_manager.rs | 47 ++-- .../rust-lib/flowy-sync/src/ws_manager.rs | 115 +++++---- .../flowy-user/src/handlers/auth_handler.rs | 4 +- .../flowy-user/src/handlers/user_handler.rs | 10 +- .../rust-lib/lib-dispatch/src/module/data.rs | 22 +- .../lib-dispatch/src/module/module.rs | 4 +- .../src/entities/document_info.rs | 26 +- .../src/protobuf/model/document_info.rs | 228 +++++++++--------- .../src/protobuf/proto/document_info.proto | 10 +- .../src/server_document/document_manager.rs | 10 +- shared-lib/flowy-collaboration/src/util.rs | 22 +- .../src/entities/share.rs | 6 +- .../src/protobuf/model/share.rs | 52 ++-- .../src/protobuf/proto/share.proto | 2 +- 50 files changed, 707 insertions(+), 699 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart b/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart index 538c7b42b3..6b977a79e0 100644 --- a/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart @@ -84,8 +84,8 @@ class DocumentBloc extends Bloc { listener.start(); final result = await repo.openDocument(); result.fold( - (doc) { - document = _decodeJsonToDocument(doc.deltaJson); + (block) { + document = _decodeJsonToDocument(block.deltaJson); _subscription = document.changes.listen((event) { final delta = event.item2; final documentDelta = document.toDelta(); diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/document_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/document_repo.dart index 61fefab94a..4c01afe8ec 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/document_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/document_repo.dart @@ -10,14 +10,14 @@ class DocumentRepository { required this.docId, }); - Future> openDocument() { + Future> openDocument() { final request = ViewId(value: docId); return FolderEventOpenView(request).send(); } - Future> composeDelta({required String data}) { - final request = DocumentDelta.create() - ..docId = docId + Future> composeDelta({required String data}) { + final request = BlockDelta.create() + ..blockId = docId ..deltaJson = data; return FolderEventApplyDocDelta(request).send(); } diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart index ffd95d1e0b..ec9db2da2c 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart @@ -7,7 +7,7 @@ import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; class ShareRepo { Future> export(String docId, ExportType type) { final request = ExportPayload.create() - ..docId = docId + ..viewId = docId ..exportType = type; return FolderEventExportDocument(request).send(); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-folder/dart_event.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-folder/dart_event.dart index 94d4e3c775..99d6d56d89 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-folder/dart_event.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-folder/dart_event.dart @@ -271,14 +271,14 @@ class FolderEventOpenView { ViewId request; FolderEventOpenView(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = FolderEvent.OpenView.toString() ..payload = requestToBytes(this.request); return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( - (okBytes) => left(DocumentDelta.fromBuffer(okBytes)), + (okBytes) => left(BlockDelta.fromBuffer(okBytes)), (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } @@ -378,17 +378,17 @@ class FolderEventDeleteAllTrash { } class FolderEventApplyDocDelta { - DocumentDelta request; + BlockDelta request; FolderEventApplyDocDelta(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = FolderEvent.ApplyDocDelta.toString() ..payload = requestToBytes(this.request); return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( - (okBytes) => left(DocumentDelta.fromBuffer(okBytes)), + (okBytes) => left(BlockDelta.fromBuffer(okBytes)), (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/document_info.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/document_info.pb.dart index fcb1339131..968f76062a 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/document_info.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/document_info.pb.dart @@ -12,15 +12,15 @@ import 'package:protobuf/protobuf.dart' as $pb; import 'revision.pb.dart' as $0; -class CreateDocParams extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateDocParams', createEmptyInstance: create) +class CreateBlockParams extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateBlockParams', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') ..aOM<$0.RepeatedRevision>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'revisions', subBuilder: $0.RepeatedRevision.create) ..hasRequiredFields = false ; - CreateDocParams._() : super(); - factory CreateDocParams({ + CreateBlockParams._() : super(); + factory CreateBlockParams({ $core.String? id, $0.RepeatedRevision? revisions, }) { @@ -33,26 +33,26 @@ class CreateDocParams extends $pb.GeneratedMessage { } return _result; } - factory CreateDocParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory CreateDocParams.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory CreateBlockParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CreateBlockParams.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' 'Will be removed in next major version') - CreateDocParams clone() => CreateDocParams()..mergeFromMessage(this); + CreateBlockParams clone() => CreateBlockParams()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - CreateDocParams copyWith(void Function(CreateDocParams) updates) => super.copyWith((message) => updates(message as CreateDocParams)) as CreateDocParams; // ignore: deprecated_member_use + CreateBlockParams copyWith(void Function(CreateBlockParams) updates) => super.copyWith((message) => updates(message as CreateBlockParams)) as CreateBlockParams; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static CreateDocParams create() => CreateDocParams._(); - CreateDocParams createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static CreateBlockParams create() => CreateBlockParams._(); + CreateBlockParams createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static CreateDocParams getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static CreateDocParams? _defaultInstance; + static CreateBlockParams getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static CreateBlockParams? _defaultInstance; @$pb.TagNumber(1) $core.String get id => $_getSZ(0); @@ -75,8 +75,8 @@ class CreateDocParams extends $pb.GeneratedMessage { $0.RepeatedRevision ensureRevisions() => $_ensure(1); } -class DocumentInfo extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DocumentInfo', createEmptyInstance: create) +class BlockInfo extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'BlockInfo', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'docId') ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'text') ..aInt64(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'revId') @@ -84,8 +84,8 @@ class DocumentInfo extends $pb.GeneratedMessage { ..hasRequiredFields = false ; - DocumentInfo._() : super(); - factory DocumentInfo({ + BlockInfo._() : super(); + factory BlockInfo({ $core.String? docId, $core.String? text, $fixnum.Int64? revId, @@ -106,26 +106,26 @@ class DocumentInfo extends $pb.GeneratedMessage { } return _result; } - factory DocumentInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory DocumentInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory BlockInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory BlockInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' 'Will be removed in next major version') - DocumentInfo clone() => DocumentInfo()..mergeFromMessage(this); + BlockInfo clone() => BlockInfo()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - DocumentInfo copyWith(void Function(DocumentInfo) updates) => super.copyWith((message) => updates(message as DocumentInfo)) as DocumentInfo; // ignore: deprecated_member_use + BlockInfo copyWith(void Function(BlockInfo) updates) => super.copyWith((message) => updates(message as BlockInfo)) as BlockInfo; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static DocumentInfo create() => DocumentInfo._(); - DocumentInfo createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static BlockInfo create() => BlockInfo._(); + BlockInfo createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static DocumentInfo getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static DocumentInfo? _defaultInstance; + static BlockInfo getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static BlockInfo? _defaultInstance; @$pb.TagNumber(1) $core.String get docId => $_getSZ(0); @@ -227,56 +227,56 @@ class ResetDocumentParams extends $pb.GeneratedMessage { $0.RepeatedRevision ensureRevisions() => $_ensure(1); } -class DocumentDelta extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DocumentDelta', createEmptyInstance: create) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'docId') +class BlockDelta extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'BlockDelta', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockId') ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deltaJson') ..hasRequiredFields = false ; - DocumentDelta._() : super(); - factory DocumentDelta({ - $core.String? docId, + BlockDelta._() : super(); + factory BlockDelta({ + $core.String? blockId, $core.String? deltaJson, }) { final _result = create(); - if (docId != null) { - _result.docId = docId; + if (blockId != null) { + _result.blockId = blockId; } if (deltaJson != null) { _result.deltaJson = deltaJson; } return _result; } - factory DocumentDelta.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory DocumentDelta.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory BlockDelta.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory BlockDelta.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' 'Will be removed in next major version') - DocumentDelta clone() => DocumentDelta()..mergeFromMessage(this); + BlockDelta clone() => BlockDelta()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - DocumentDelta copyWith(void Function(DocumentDelta) updates) => super.copyWith((message) => updates(message as DocumentDelta)) as DocumentDelta; // ignore: deprecated_member_use + BlockDelta copyWith(void Function(BlockDelta) updates) => super.copyWith((message) => updates(message as BlockDelta)) as BlockDelta; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static DocumentDelta create() => DocumentDelta._(); - DocumentDelta createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static BlockDelta create() => BlockDelta._(); + BlockDelta createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static DocumentDelta getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static DocumentDelta? _defaultInstance; + static BlockDelta getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static BlockDelta? _defaultInstance; @$pb.TagNumber(1) - $core.String get docId => $_getSZ(0); + $core.String get blockId => $_getSZ(0); @$pb.TagNumber(1) - set docId($core.String v) { $_setString(0, v); } + set blockId($core.String v) { $_setString(0, v); } @$pb.TagNumber(1) - $core.bool hasDocId() => $_has(0); + $core.bool hasBlockId() => $_has(0); @$pb.TagNumber(1) - void clearDocId() => clearField(1); + void clearBlockId() => clearField(1); @$pb.TagNumber(2) $core.String get deltaJson => $_getSZ(1); @@ -363,14 +363,14 @@ class NewDocUser extends $pb.GeneratedMessage { void clearDocId() => clearField(3); } -class DocumentId extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DocumentId', createEmptyInstance: create) +class BlockId extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'BlockId', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'value') ..hasRequiredFields = false ; - DocumentId._() : super(); - factory DocumentId({ + BlockId._() : super(); + factory BlockId({ $core.String? value, }) { final _result = create(); @@ -379,26 +379,26 @@ class DocumentId extends $pb.GeneratedMessage { } return _result; } - factory DocumentId.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory DocumentId.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory BlockId.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory BlockId.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' 'Will be removed in next major version') - DocumentId clone() => DocumentId()..mergeFromMessage(this); + BlockId clone() => BlockId()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - DocumentId copyWith(void Function(DocumentId) updates) => super.copyWith((message) => updates(message as DocumentId)) as DocumentId; // ignore: deprecated_member_use + BlockId copyWith(void Function(BlockId) updates) => super.copyWith((message) => updates(message as BlockId)) as BlockId; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static DocumentId create() => DocumentId._(); - DocumentId createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static BlockId create() => BlockId._(); + BlockId createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static DocumentId getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static DocumentId? _defaultInstance; + static BlockId getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static BlockId? _defaultInstance; @$pb.TagNumber(1) $core.String get value => $_getSZ(0); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/document_info.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/document_info.pbjson.dart index ab64ac949c..d25e3b92b4 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/document_info.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/document_info.pbjson.dart @@ -8,20 +8,20 @@ import 'dart:core' as $core; import 'dart:convert' as $convert; import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use createDocParamsDescriptor instead') -const CreateDocParams$json = const { - '1': 'CreateDocParams', +@$core.Deprecated('Use createBlockParamsDescriptor instead') +const CreateBlockParams$json = const { + '1': 'CreateBlockParams', '2': const [ const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, const {'1': 'revisions', '3': 2, '4': 1, '5': 11, '6': '.RepeatedRevision', '10': 'revisions'}, ], }; -/// Descriptor for `CreateDocParams`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List createDocParamsDescriptor = $convert.base64Decode('Cg9DcmVhdGVEb2NQYXJhbXMSDgoCaWQYASABKAlSAmlkEi8KCXJldmlzaW9ucxgCIAEoCzIRLlJlcGVhdGVkUmV2aXNpb25SCXJldmlzaW9ucw=='); -@$core.Deprecated('Use documentInfoDescriptor instead') -const DocumentInfo$json = const { - '1': 'DocumentInfo', +/// Descriptor for `CreateBlockParams`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List createBlockParamsDescriptor = $convert.base64Decode('ChFDcmVhdGVCbG9ja1BhcmFtcxIOCgJpZBgBIAEoCVICaWQSLwoJcmV2aXNpb25zGAIgASgLMhEuUmVwZWF0ZWRSZXZpc2lvblIJcmV2aXNpb25z'); +@$core.Deprecated('Use blockInfoDescriptor instead') +const BlockInfo$json = const { + '1': 'BlockInfo', '2': const [ const {'1': 'doc_id', '3': 1, '4': 1, '5': 9, '10': 'docId'}, const {'1': 'text', '3': 2, '4': 1, '5': 9, '10': 'text'}, @@ -30,8 +30,8 @@ const DocumentInfo$json = const { ], }; -/// Descriptor for `DocumentInfo`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List documentInfoDescriptor = $convert.base64Decode('CgxEb2N1bWVudEluZm8SFQoGZG9jX2lkGAEgASgJUgVkb2NJZBISCgR0ZXh0GAIgASgJUgR0ZXh0EhUKBnJldl9pZBgDIAEoA1IFcmV2SWQSHgoLYmFzZV9yZXZfaWQYBCABKANSCWJhc2VSZXZJZA=='); +/// Descriptor for `BlockInfo`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List blockInfoDescriptor = $convert.base64Decode('CglCbG9ja0luZm8SFQoGZG9jX2lkGAEgASgJUgVkb2NJZBISCgR0ZXh0GAIgASgJUgR0ZXh0EhUKBnJldl9pZBgDIAEoA1IFcmV2SWQSHgoLYmFzZV9yZXZfaWQYBCABKANSCWJhc2VSZXZJZA=='); @$core.Deprecated('Use resetDocumentParamsDescriptor instead') const ResetDocumentParams$json = const { '1': 'ResetDocumentParams', @@ -43,17 +43,17 @@ const ResetDocumentParams$json = const { /// Descriptor for `ResetDocumentParams`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List resetDocumentParamsDescriptor = $convert.base64Decode('ChNSZXNldERvY3VtZW50UGFyYW1zEhUKBmRvY19pZBgBIAEoCVIFZG9jSWQSLwoJcmV2aXNpb25zGAIgASgLMhEuUmVwZWF0ZWRSZXZpc2lvblIJcmV2aXNpb25z'); -@$core.Deprecated('Use documentDeltaDescriptor instead') -const DocumentDelta$json = const { - '1': 'DocumentDelta', +@$core.Deprecated('Use blockDeltaDescriptor instead') +const BlockDelta$json = const { + '1': 'BlockDelta', '2': const [ - const {'1': 'doc_id', '3': 1, '4': 1, '5': 9, '10': 'docId'}, + const {'1': 'block_id', '3': 1, '4': 1, '5': 9, '10': 'blockId'}, const {'1': 'delta_json', '3': 2, '4': 1, '5': 9, '10': 'deltaJson'}, ], }; -/// Descriptor for `DocumentDelta`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List documentDeltaDescriptor = $convert.base64Decode('Cg1Eb2N1bWVudERlbHRhEhUKBmRvY19pZBgBIAEoCVIFZG9jSWQSHQoKZGVsdGFfanNvbhgCIAEoCVIJZGVsdGFKc29u'); +/// Descriptor for `BlockDelta`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List blockDeltaDescriptor = $convert.base64Decode('CgpCbG9ja0RlbHRhEhkKCGJsb2NrX2lkGAEgASgJUgdibG9ja0lkEh0KCmRlbHRhX2pzb24YAiABKAlSCWRlbHRhSnNvbg=='); @$core.Deprecated('Use newDocUserDescriptor instead') const NewDocUser$json = const { '1': 'NewDocUser', @@ -66,13 +66,13 @@ const NewDocUser$json = const { /// Descriptor for `NewDocUser`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List newDocUserDescriptor = $convert.base64Decode('CgpOZXdEb2NVc2VyEhcKB3VzZXJfaWQYASABKAlSBnVzZXJJZBIVCgZyZXZfaWQYAiABKANSBXJldklkEhUKBmRvY19pZBgDIAEoCVIFZG9jSWQ='); -@$core.Deprecated('Use documentIdDescriptor instead') -const DocumentId$json = const { - '1': 'DocumentId', +@$core.Deprecated('Use blockIdDescriptor instead') +const BlockId$json = const { + '1': 'BlockId', '2': const [ const {'1': 'value', '3': 1, '4': 1, '5': 9, '10': 'value'}, ], }; -/// Descriptor for `DocumentId`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List documentIdDescriptor = $convert.base64Decode('CgpEb2N1bWVudElkEhQKBXZhbHVlGAEgASgJUgV2YWx1ZQ=='); +/// Descriptor for `BlockId`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List blockIdDescriptor = $convert.base64Decode('CgdCbG9ja0lkEhQKBXZhbHVlGAEgASgJUgV2YWx1ZQ=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/share.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/share.pb.dart index f54efef79c..c90de870dd 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/share.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/share.pb.dart @@ -15,19 +15,19 @@ export 'share.pbenum.dart'; class ExportPayload extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ExportPayload', createEmptyInstance: create) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'docId') + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId') ..e(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'exportType', $pb.PbFieldType.OE, defaultOrMaker: ExportType.Text, valueOf: ExportType.valueOf, enumValues: ExportType.values) ..hasRequiredFields = false ; ExportPayload._() : super(); factory ExportPayload({ - $core.String? docId, + $core.String? viewId, ExportType? exportType, }) { final _result = create(); - if (docId != null) { - _result.docId = docId; + if (viewId != null) { + _result.viewId = viewId; } if (exportType != null) { _result.exportType = exportType; @@ -56,13 +56,13 @@ class ExportPayload extends $pb.GeneratedMessage { static ExportPayload? _defaultInstance; @$pb.TagNumber(1) - $core.String get docId => $_getSZ(0); + $core.String get viewId => $_getSZ(0); @$pb.TagNumber(1) - set docId($core.String v) { $_setString(0, v); } + set viewId($core.String v) { $_setString(0, v); } @$pb.TagNumber(1) - $core.bool hasDocId() => $_has(0); + $core.bool hasViewId() => $_has(0); @$pb.TagNumber(1) - void clearDocId() => clearField(1); + void clearViewId() => clearField(1); @$pb.TagNumber(2) ExportType get exportType => $_getN(1); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/share.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/share.pbjson.dart index 3f623fe48a..8224855b02 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/share.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/share.pbjson.dart @@ -24,13 +24,13 @@ final $typed_data.Uint8List exportTypeDescriptor = $convert.base64Decode('CgpFeH const ExportPayload$json = const { '1': 'ExportPayload', '2': const [ - const {'1': 'doc_id', '3': 1, '4': 1, '5': 9, '10': 'docId'}, + const {'1': 'view_id', '3': 1, '4': 1, '5': 9, '10': 'viewId'}, const {'1': 'export_type', '3': 2, '4': 1, '5': 14, '6': '.ExportType', '10': 'exportType'}, ], }; /// Descriptor for `ExportPayload`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List exportPayloadDescriptor = $convert.base64Decode('Cg1FeHBvcnRQYXlsb2FkEhUKBmRvY19pZBgBIAEoCVIFZG9jSWQSLAoLZXhwb3J0X3R5cGUYAiABKA4yCy5FeHBvcnRUeXBlUgpleHBvcnRUeXBl'); +final $typed_data.Uint8List exportPayloadDescriptor = $convert.base64Decode('Cg1FeHBvcnRQYXlsb2FkEhcKB3ZpZXdfaWQYASABKAlSBnZpZXdJZBIsCgtleHBvcnRfdHlwZRgCIAEoDjILLkV4cG9ydFR5cGVSCmV4cG9ydFR5cGU='); @$core.Deprecated('Use exportDataDescriptor instead') const ExportData$json = const { '1': 'ExportData', diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index c77c88fdf3..1f07ccdf24 100755 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -1108,6 +1108,7 @@ name = "flowy-sync" version = "0.1.0" dependencies = [ "async-stream", + "async-trait", "bytes", "dashmap", "diesel", diff --git a/frontend/rust-lib/flowy-document/src/editor.rs b/frontend/rust-lib/flowy-document/src/editor.rs index 77bc25ce8d..36099cffa3 100644 --- a/frontend/rust-lib/flowy-document/src/editor.rs +++ b/frontend/rust-lib/flowy-document/src/editor.rs @@ -3,11 +3,12 @@ use crate::web_socket::{make_document_ws_manager, EditorCommandSender}; use crate::{ errors::FlowyError, queue::{EditorCommand, EditorCommandQueue}, - DocumentUser, DocumentWSReceiver, + BlockUser, }; use bytes::Bytes; +use flowy_collaboration::entities::ws_data::ServerRevisionWSData; use flowy_collaboration::{ - entities::{document_info::DocumentInfo, revision::Revision}, + entities::{document_info::BlockInfo, revision::Revision}, errors::CollaborateResult, util::make_delta_from_revisions, }; @@ -19,10 +20,11 @@ use lib_ot::{ core::{Interval, Operation}, rich_text::{RichTextAttribute, RichTextDelta}, }; +use lib_ws::WSConnectState; use std::sync::Arc; use tokio::sync::{mpsc, oneshot}; -pub struct ClientDocumentEditor { +pub struct ClientBlockEditor { pub doc_id: String, #[allow(dead_code)] rev_manager: Arc, @@ -30,16 +32,16 @@ pub struct ClientDocumentEditor { edit_cmd_tx: EditorCommandSender, } -impl ClientDocumentEditor { +impl ClientBlockEditor { pub(crate) async fn new( doc_id: &str, - user: Arc, + user: Arc, mut rev_manager: RevisionManager, rev_web_socket: Arc, cloud_service: Arc, ) -> FlowyResult> { let document_info = rev_manager - .load::(cloud_service) + .load::(cloud_service) .await?; let delta = document_info.delta()?; let rev_manager = Arc::new(rev_manager); @@ -138,9 +140,9 @@ impl ClientDocumentEditor { Ok(()) } - pub async fn document_json(&self) -> FlowyResult { + pub async fn block_json(&self) -> FlowyResult { let (ret, rx) = oneshot::channel::>(); - let msg = EditorCommand::ReadDocumentAsJson { ret }; + let msg = EditorCommand::ReadBlockJson { ret }; let _ = self.edit_cmd_tx.send(msg).await; let json = rx.await.map_err(internal_error)??; Ok(json) @@ -163,12 +165,16 @@ impl ClientDocumentEditor { self.ws_manager.stop(); } - pub(crate) fn ws_handler(&self) -> Arc { - self.ws_manager.clone() + pub(crate) async fn receive_ws_data(&self, data: ServerRevisionWSData) -> Result<(), FlowyError> { + self.ws_manager.receive_ws_data(data).await + } + + pub(crate) fn receive_ws_state(&self, state: &WSConnectState) { + self.ws_manager.connect_state_changed(state.clone()); } } -impl std::ops::Drop for ClientDocumentEditor { +impl std::ops::Drop for ClientBlockEditor { fn drop(&mut self) { tracing::trace!("{} ClientDocumentEditor was dropped", self.doc_id) } @@ -176,7 +182,7 @@ impl std::ops::Drop for ClientDocumentEditor { // The edit queue will exit after the EditorCommandSender was dropped. fn spawn_edit_queue( - user: Arc, + user: Arc, rev_manager: Arc, delta: RichTextDelta, ) -> EditorCommandSender { @@ -187,10 +193,10 @@ fn spawn_edit_queue( } #[cfg(feature = "flowy_unit_test")] -impl ClientDocumentEditor { +impl ClientBlockEditor { pub async fn doc_json(&self) -> FlowyResult { let (ret, rx) = oneshot::channel::>(); - let msg = EditorCommand::ReadDocumentAsJson { ret }; + let msg = EditorCommand::ReadBlockJson { ret }; let _ = self.edit_cmd_tx.send(msg).await; let s = rx.await.map_err(internal_error)??; Ok(s) @@ -198,7 +204,7 @@ impl ClientDocumentEditor { pub async fn doc_delta(&self) -> FlowyResult { let (ret, rx) = oneshot::channel::>(); - let msg = EditorCommand::ReadDocumentAsDelta { ret }; + let msg = EditorCommand::ReadBlockDelta { ret }; let _ = self.edit_cmd_tx.send(msg).await; let delta = rx.await.map_err(internal_error)??; Ok(delta) @@ -209,16 +215,16 @@ impl ClientDocumentEditor { } } -struct DocumentInfoBuilder(); -impl RevisionObjectBuilder for DocumentInfoBuilder { - type Output = DocumentInfo; +struct BlockInfoBuilder(); +impl RevisionObjectBuilder for BlockInfoBuilder { + type Output = BlockInfo; fn build_object(object_id: &str, revisions: Vec) -> FlowyResult { let (base_rev_id, rev_id) = revisions.last().unwrap().pair_rev_id(); let mut delta = make_delta_from_revisions(revisions)?; correct_delta(&mut delta); - Result::::Ok(DocumentInfo { + Result::::Ok(BlockInfo { doc_id: object_id.to_owned(), text: delta.to_json(), rev_id, diff --git a/frontend/rust-lib/flowy-document/src/lib.rs b/frontend/rust-lib/flowy-document/src/lib.rs index 7697de9b5c..eeea94bdb1 100644 --- a/frontend/rust-lib/flowy-document/src/lib.rs +++ b/frontend/rust-lib/flowy-document/src/lib.rs @@ -11,13 +11,13 @@ pub mod errors { pub const DOCUMENT_SYNC_INTERVAL_IN_MILLIS: u64 = 1000; use crate::errors::FlowyError; -use flowy_collaboration::entities::document_info::{CreateDocParams, DocumentId, DocumentInfo, ResetDocumentParams}; +use flowy_collaboration::entities::document_info::{BlockId, BlockInfo, CreateBlockParams, ResetDocumentParams}; use lib_infra::future::FutureResult; -pub trait DocumentCloudService: Send + Sync { - fn create_document(&self, token: &str, params: CreateDocParams) -> FutureResult<(), FlowyError>; +pub trait BlockCloudService: Send + Sync { + fn create_block(&self, token: &str, params: CreateBlockParams) -> FutureResult<(), FlowyError>; - fn read_document(&self, token: &str, params: DocumentId) -> FutureResult, FlowyError>; + fn read_block(&self, token: &str, params: BlockId) -> FutureResult, FlowyError>; - fn update_document(&self, token: &str, params: ResetDocumentParams) -> FutureResult<(), FlowyError>; + fn update_block(&self, token: &str, params: ResetDocumentParams) -> FutureResult<(), FlowyError>; } diff --git a/frontend/rust-lib/flowy-document/src/manager.rs b/frontend/rust-lib/flowy-document/src/manager.rs index d02fa876e0..f98cf2af02 100644 --- a/frontend/rust-lib/flowy-document/src/manager.rs +++ b/frontend/rust-lib/flowy-document/src/manager.rs @@ -1,76 +1,64 @@ -use crate::{editor::ClientDocumentEditor, errors::FlowyError, DocumentCloudService}; -use async_trait::async_trait; +use crate::{editor::ClientBlockEditor, errors::FlowyError, BlockCloudService}; use bytes::Bytes; use dashmap::DashMap; use flowy_collaboration::entities::{ - document_info::{DocumentDelta, DocumentId}, + document_info::{BlockDelta, BlockId}, revision::{md5, RepeatedRevision, Revision}, ws_data::ServerRevisionWSData, }; use flowy_database::ConnectionPool; use flowy_error::FlowyResult; -use flowy_sync::{RevisionCache, RevisionCloudService, RevisionManager, RevisionWebSocket}; +use flowy_sync::{RevisionCloudService, RevisionManager, RevisionPersistence, RevisionWebSocket}; use lib_infra::future::FutureResult; -use lib_ws::WSConnectState; use std::{convert::TryInto, sync::Arc}; -pub trait DocumentUser: Send + Sync { +pub trait BlockUser: Send + Sync { fn user_dir(&self) -> Result; fn user_id(&self) -> Result; fn token(&self) -> Result; fn db_pool(&self) -> Result, FlowyError>; } -#[async_trait] -pub(crate) trait DocumentWSReceiver: Send + Sync { - async fn receive_ws_data(&self, data: ServerRevisionWSData) -> Result<(), FlowyError>; - fn connect_state_changed(&self, state: WSConnectState); -} -type WebSocketDataReceivers = Arc>>; -pub struct FlowyDocumentManager { - cloud_service: Arc, - ws_data_receivers: WebSocketDataReceivers, +pub struct BlockManager { + cloud_service: Arc, rev_web_socket: Arc, - document_handlers: Arc, - document_user: Arc, + block_handlers: Arc, + document_user: Arc, } -impl FlowyDocumentManager { +impl BlockManager { pub fn new( - cloud_service: Arc, - document_user: Arc, + cloud_service: Arc, + document_user: Arc, rev_web_socket: Arc, ) -> Self { - let ws_data_receivers = Arc::new(DashMap::new()); - let document_handlers = Arc::new(DocumentEditorHandlers::new()); + let block_handlers = Arc::new(BlockEditorHandlers::new()); Self { cloud_service, - ws_data_receivers, rev_web_socket, - document_handlers, + block_handlers, document_user, } } pub fn init(&self) -> FlowyResult<()> { - listen_ws_state_changed(self.rev_web_socket.clone(), self.ws_data_receivers.clone()); + listen_ws_state_changed(self.rev_web_socket.clone(), self.block_handlers.clone()); Ok(()) } - #[tracing::instrument(level = "debug", skip(self, doc_id), fields(doc_id), err)] - pub async fn open_document>(&self, doc_id: T) -> Result, FlowyError> { - let doc_id = doc_id.as_ref(); - tracing::Span::current().record("doc_id", &doc_id); - self.get_editor(doc_id).await + #[tracing::instrument(level = "debug", skip(self, block_id), fields(block_id), err)] + pub async fn open_block>(&self, block_id: T) -> Result, FlowyError> { + let block_id = block_id.as_ref(); + tracing::Span::current().record("block_id", &block_id); + self.get_block_editor(block_id).await } - #[tracing::instrument(level = "trace", skip(self, doc_id), fields(doc_id), err)] - pub fn close_document>(&self, doc_id: T) -> Result<(), FlowyError> { - let doc_id = doc_id.as_ref(); - tracing::Span::current().record("doc_id", &doc_id); - self.document_handlers.remove(doc_id); - self.ws_data_receivers.remove(doc_id); + #[tracing::instrument(level = "trace", skip(self, block_id), fields(block_id), err)] + pub fn close_block>(&self, block_id: T) -> Result<(), FlowyError> { + let block_id = block_id.as_ref(); + tracing::Span::current().record("block_id", &block_id); + self.block_handlers.remove(block_id); Ok(()) } @@ -78,18 +66,17 @@ impl FlowyDocumentManager { pub fn delete>(&self, doc_id: T) -> Result<(), FlowyError> { let doc_id = doc_id.as_ref(); tracing::Span::current().record("doc_id", &doc_id); - self.document_handlers.remove(doc_id); - self.ws_data_receivers.remove(doc_id); + self.block_handlers.remove(doc_id); Ok(()) } - #[tracing::instrument(level = "debug", skip(self, delta), fields(doc_id = %delta.doc_id), err)] - pub async fn receive_local_delta(&self, delta: DocumentDelta) -> Result { - let editor = self.get_editor(&delta.doc_id).await?; + #[tracing::instrument(level = "debug", skip(self, delta), fields(doc_id = %delta.block_id), err)] + pub async fn receive_local_delta(&self, delta: BlockDelta) -> Result { + let editor = self.get_block_editor(&delta.block_id).await?; let _ = editor.compose_local_delta(Bytes::from(delta.delta_json)).await?; - let document_json = editor.document_json().await?; - Ok(DocumentDelta { - doc_id: delta.doc_id.clone(), + let document_json = editor.block_json().await?; + Ok(BlockDelta { + block_id: delta.block_id.clone(), delta_json: document_json, }) } @@ -105,9 +92,9 @@ impl FlowyDocumentManager { pub async fn receive_ws_data(&self, data: Bytes) { let result: Result = data.try_into(); match result { - Ok(data) => match self.ws_data_receivers.get(&data.object_id) { + Ok(data) => match self.block_handlers.get(&data.object_id) { None => tracing::error!("Can't find any source handler for {:?}-{:?}", data.object_id, data.ty), - Some(handler) => match handler.receive_ws_data(data).await { + Some(block_editor) => match block_editor.receive_ws_data(data).await { Ok(_) => {} Err(e) => tracing::error!("{}", e), }, @@ -119,59 +106,57 @@ impl FlowyDocumentManager { } } -impl FlowyDocumentManager { - async fn get_editor(&self, doc_id: &str) -> FlowyResult> { - match self.document_handlers.get(doc_id) { +impl BlockManager { + async fn get_block_editor(&self, block_id: &str) -> FlowyResult> { + match self.block_handlers.get(block_id) { None => { let db_pool = self.document_user.db_pool()?; - self.make_editor(doc_id, db_pool).await + self.make_block_editor(block_id, db_pool).await } Some(editor) => Ok(editor), } } - async fn make_editor( + async fn make_block_editor( &self, - doc_id: &str, + block_id: &str, pool: Arc, - ) -> Result, FlowyError> { + ) -> Result, FlowyError> { let user = self.document_user.clone(); let token = self.document_user.token()?; - let rev_manager = self.make_rev_manager(doc_id, pool.clone())?; + let rev_manager = self.make_rev_manager(block_id, pool.clone())?; let cloud_service = Arc::new(DocumentRevisionCloudServiceImpl { token, server: self.cloud_service.clone(), }); let doc_editor = - ClientDocumentEditor::new(doc_id, user, rev_manager, self.rev_web_socket.clone(), cloud_service).await?; - self.ws_data_receivers - .insert(doc_id.to_string(), doc_editor.ws_handler()); - self.document_handlers.insert(doc_id, &doc_editor); + ClientBlockEditor::new(block_id, user, rev_manager, self.rev_web_socket.clone(), cloud_service).await?; + self.block_handlers.insert(block_id, &doc_editor); Ok(doc_editor) } fn make_rev_manager(&self, doc_id: &str, pool: Arc) -> Result { let user_id = self.document_user.user_id()?; - let cache = Arc::new(RevisionCache::new(&user_id, doc_id, pool)); - Ok(RevisionManager::new(&user_id, doc_id, cache)) + let rev_persistence = Arc::new(RevisionPersistence::new(&user_id, doc_id, pool)); + Ok(RevisionManager::new(&user_id, doc_id, rev_persistence)) } } struct DocumentRevisionCloudServiceImpl { token: String, - server: Arc, + server: Arc, } impl RevisionCloudService for DocumentRevisionCloudServiceImpl { #[tracing::instrument(level = "trace", skip(self))] fn fetch_object(&self, user_id: &str, object_id: &str) -> FutureResult, FlowyError> { - let params: DocumentId = object_id.to_string().into(); + let params: BlockId = object_id.to_string().into(); let server = self.server.clone(); let token = self.token.clone(); let user_id = user_id.to_string(); FutureResult::new(async move { - match server.read_document(&token, params).await? { + match server.read_block(&token, params).await? { None => Err(FlowyError::record_not_found().context("Remote doesn't have this document")), Some(doc) => { let delta_data = Bytes::from(doc.text.clone()); @@ -185,51 +170,50 @@ impl RevisionCloudService for DocumentRevisionCloudServiceImpl { } } -pub struct DocumentEditorHandlers { - inner: DashMap>, +pub struct BlockEditorHandlers { + inner: DashMap>, } -impl DocumentEditorHandlers { +impl BlockEditorHandlers { fn new() -> Self { Self { inner: DashMap::new() } } - pub(crate) fn insert(&self, doc_id: &str, doc: &Arc) { - if self.inner.contains_key(doc_id) { - log::warn!("Doc:{} already exists in cache", doc_id); + pub(crate) fn insert(&self, block_id: &str, doc: &Arc) { + if self.inner.contains_key(block_id) { + log::warn!("Doc:{} already exists in cache", block_id); } - self.inner.insert(doc_id.to_string(), doc.clone()); + self.inner.insert(block_id.to_string(), doc.clone()); } - pub(crate) fn contains(&self, doc_id: &str) -> bool { - self.inner.get(doc_id).is_some() + pub(crate) fn contains(&self, block_id: &str) -> bool { + self.inner.get(block_id).is_some() } - pub(crate) fn get(&self, doc_id: &str) -> Option> { - if !self.contains(doc_id) { + pub(crate) fn get(&self, block_id: &str) -> Option> { + if !self.contains(block_id) { return None; } - let opened_doc = self.inner.get(doc_id).unwrap(); + let opened_doc = self.inner.get(block_id).unwrap(); Some(opened_doc.clone()) } - pub(crate) fn remove(&self, id: &str) { - let doc_id = id.to_string(); - if let Some(editor) = self.get(id) { + pub(crate) fn remove(&self, block_id: &str) { + if let Some(editor) = self.get(block_id) { editor.stop() } - self.inner.remove(&doc_id); + self.inner.remove(block_id); } } -#[tracing::instrument(level = "trace", skip(web_socket, receivers))] -fn listen_ws_state_changed(web_socket: Arc, receivers: WebSocketDataReceivers) { +#[tracing::instrument(level = "trace", skip(web_socket, handlers))] +fn listen_ws_state_changed(web_socket: Arc, handlers: Arc) { tokio::spawn(async move { let mut notify = web_socket.subscribe_state_changed().await; while let Ok(state) = notify.recv().await { - for receiver in receivers.iter() { - receiver.value().connect_state_changed(state.clone()); - } + handlers.inner.iter().for_each(|handler| { + handler.receive_ws_state(&state); + }) } }); } diff --git a/frontend/rust-lib/flowy-document/src/queue.rs b/frontend/rust-lib/flowy-document/src/queue.rs index 5d97a6135d..3d780933de 100644 --- a/frontend/rust-lib/flowy-document/src/queue.rs +++ b/frontend/rust-lib/flowy-document/src/queue.rs @@ -1,5 +1,5 @@ use crate::web_socket::EditorCommandReceiver; -use crate::DocumentUser; +use crate::BlockUser; use async_stream::stream; use flowy_collaboration::util::make_delta_from_revisions; use flowy_collaboration::{ @@ -21,14 +21,14 @@ use tokio::sync::{oneshot, RwLock}; // serial. pub(crate) struct EditorCommandQueue { document: Arc>, - user: Arc, + user: Arc, rev_manager: Arc, receiver: Option, } impl EditorCommandQueue { pub(crate) fn new( - user: Arc, + user: Arc, rev_manager: Arc, delta: RichTextDelta, receiver: EditorCommandReceiver, @@ -161,11 +161,11 @@ impl EditorCommandQueue { let _ = self.save_local_delta(delta, md5).await?; let _ = ret.send(Ok(())); } - EditorCommand::ReadDocumentAsJson { ret } => { + EditorCommand::ReadBlockJson { ret } => { let data = self.document.read().await.to_json(); let _ = ret.send(Ok(data)); } - EditorCommand::ReadDocumentAsDelta { ret } => { + EditorCommand::ReadBlockDelta { ret } => { let delta = self.document.read().await.delta().clone(); let _ = ret.send(Ok(delta)); } @@ -265,11 +265,11 @@ pub(crate) enum EditorCommand { Redo { ret: Ret<()>, }, - ReadDocumentAsJson { + ReadBlockJson { ret: Ret, }, #[allow(dead_code)] - ReadDocumentAsDelta { + ReadBlockDelta { ret: Ret, }, } @@ -289,8 +289,8 @@ impl std::fmt::Debug for EditorCommand { EditorCommand::CanRedo { .. } => "CanRedo", EditorCommand::Undo { .. } => "Undo", EditorCommand::Redo { .. } => "Redo", - EditorCommand::ReadDocumentAsJson { .. } => "ReadDocumentAsJson", - EditorCommand::ReadDocumentAsDelta { .. } => "ReadDocumentAsDelta", + EditorCommand::ReadBlockJson { .. } => "ReadDocumentAsJson", + EditorCommand::ReadBlockDelta { .. } => "ReadDocumentAsDelta", }; f.write_str(s) } diff --git a/frontend/rust-lib/flowy-document/src/web_socket.rs b/frontend/rust-lib/flowy-document/src/web_socket.rs index b9b454d2a1..7798d74fa1 100644 --- a/frontend/rust-lib/flowy-document/src/web_socket.rs +++ b/frontend/rust-lib/flowy-document/src/web_socket.rs @@ -1,10 +1,9 @@ -use crate::{queue::EditorCommand, DocumentWSReceiver, DOCUMENT_SYNC_INTERVAL_IN_MILLIS}; -use async_trait::async_trait; +use crate::{queue::EditorCommand, DOCUMENT_SYNC_INTERVAL_IN_MILLIS}; use bytes::Bytes; use flowy_collaboration::{ entities::{ revision::RevisionRange, - ws_data::{ClientRevisionWSData, NewDocumentUser, ServerRevisionWSData, ServerRevisionWSDataType}, + ws_data::{ClientRevisionWSData, NewDocumentUser, ServerRevisionWSDataType}, }, errors::CollaborateResult, }; @@ -30,26 +29,23 @@ pub(crate) async fn make_document_ws_manager( rev_manager: Arc, rev_web_socket: Arc, ) -> Arc { - let composite_sink_provider = Arc::new(CompositeWSSinkDataProvider::new(&doc_id, rev_manager.clone())); - let resolve_target = Arc::new(DocumentRevisionResolveTarget { edit_cmd_tx }); - let resolver = RevisionConflictResolver::::new( + let ws_data_provider = Arc::new(WSDataProvider::new(&doc_id, Arc::new(rev_manager.clone()))); + let resolver = Arc::new(BlockConflictResolver { edit_cmd_tx }); + let conflict_controller = ConflictController::::new( &user_id, - resolve_target, - Arc::new(composite_sink_provider.clone()), + resolver, + Arc::new(ws_data_provider.clone()), rev_manager, ); - let ws_stream_consumer = Arc::new(DocumentWSSteamConsumerAdapter { - resolver: Arc::new(resolver), - }); - - let sink_provider = Arc::new(DocumentWSSinkDataProviderAdapter(composite_sink_provider)); + let ws_data_stream = Arc::new(BlockRevisionWSDataStream::new(conflict_controller)); + let ws_data_sink = Arc::new(BlockWSDataSink(ws_data_provider)); let ping_duration = Duration::from_millis(DOCUMENT_SYNC_INTERVAL_IN_MILLIS); let ws_manager = Arc::new(RevisionWebSocketManager::new( "Document", &doc_id, rev_web_socket, - sink_provider, - ws_stream_consumer, + ws_data_sink, + ws_data_stream, ping_duration, )); listen_document_ws_state(&user_id, &doc_id, ws_manager.scribe_state()); @@ -69,18 +65,26 @@ fn listen_document_ws_state(_user_id: &str, _doc_id: &str, mut subscriber: broad }); } -pub(crate) struct DocumentWSSteamConsumerAdapter { - resolver: Arc>, +pub(crate) struct BlockRevisionWSDataStream { + conflict_controller: Arc>, } -impl RevisionWSSteamConsumer for DocumentWSSteamConsumerAdapter { +impl BlockRevisionWSDataStream { + pub fn new(conflict_controller: ConflictController) -> Self { + Self { + conflict_controller: Arc::new(conflict_controller), + } + } +} + +impl RevisionWSDataStream for BlockRevisionWSDataStream { fn receive_push_revision(&self, bytes: Bytes) -> BoxResultFuture<(), FlowyError> { - let resolver = self.resolver.clone(); + let resolver = self.conflict_controller.clone(); Box::pin(async move { resolver.receive_bytes(bytes).await }) } fn receive_ack(&self, id: String, ty: ServerRevisionWSDataType) -> BoxResultFuture<(), FlowyError> { - let resolver = self.resolver.clone(); + let resolver = self.conflict_controller.clone(); Box::pin(async move { resolver.ack_revision(id, ty).await }) } @@ -90,24 +94,24 @@ impl RevisionWSSteamConsumer for DocumentWSSteamConsumerAdapter { } fn pull_revisions_in_range(&self, range: RevisionRange) -> BoxResultFuture<(), FlowyError> { - let resolver = self.resolver.clone(); + let resolver = self.conflict_controller.clone(); Box::pin(async move { resolver.send_revisions(range).await }) } } -pub(crate) struct DocumentWSSinkDataProviderAdapter(pub(crate) Arc); -impl RevisionWSSinkDataProvider for DocumentWSSinkDataProviderAdapter { +pub(crate) struct BlockWSDataSink(pub(crate) Arc); +impl RevisionWSDataIterator for BlockWSDataSink { fn next(&self) -> FutureResult, FlowyError> { let sink_provider = self.0.clone(); FutureResult::new(async move { sink_provider.next().await }) } } -struct DocumentRevisionResolveTarget { +struct BlockConflictResolver { edit_cmd_tx: EditorCommandSender, } -impl ResolverTarget for DocumentRevisionResolveTarget { +impl ConflictResolver for BlockConflictResolver { fn compose_delta(&self, delta: Delta) -> BoxResultFuture { let tx = self.edit_cmd_tx.clone(); Box::pin(async move { @@ -157,24 +161,3 @@ impl ResolverTarget for DocumentRevisionResolveTarget { }) } } - -// RevisionWebSocketManager registers itself as a DocumentWSReceiver for each -// opened document. -#[async_trait] -impl DocumentWSReceiver for RevisionWebSocketManager { - #[tracing::instrument(level = "debug", skip(self, data), err)] - async fn receive_ws_data(&self, data: ServerRevisionWSData) -> Result<(), FlowyError> { - let _ = self.ws_passthrough_tx.send(data).await.map_err(|e| { - let err_msg = format!("{} passthrough error: {}", self.object_id, e); - FlowyError::internal().context(err_msg) - })?; - Ok(()) - } - - fn connect_state_changed(&self, state: WSConnectState) { - match self.state_passthrough_tx.send(state) { - Ok(_) => {} - Err(e) => tracing::error!("{}", e), - } - } -} diff --git a/frontend/rust-lib/flowy-document/tests/document/edit_script.rs b/frontend/rust-lib/flowy-document/tests/document/edit_script.rs index a7c35aad17..9961812ec8 100644 --- a/frontend/rust-lib/flowy-document/tests/document/edit_script.rs +++ b/frontend/rust-lib/flowy-document/tests/document/edit_script.rs @@ -1,5 +1,5 @@ use flowy_collaboration::entities::revision::RevisionState; -use flowy_document::editor::ClientDocumentEditor; +use flowy_document::editor::ClientBlockEditor; use flowy_document::DOCUMENT_SYNC_INTERVAL_IN_MILLIS; use flowy_test::{helper::ViewTest, FlowySDKTest}; use lib_ot::{core::Interval, rich_text::RichTextDelta}; @@ -19,7 +19,7 @@ pub enum EditorScript { pub struct EditorTest { pub sdk: FlowySDKTest, - pub editor: Arc, + pub editor: Arc, } impl EditorTest { @@ -27,7 +27,7 @@ impl EditorTest { let sdk = FlowySDKTest::default(); let _ = sdk.init_user().await; let test = ViewTest::new(&sdk).await; - let editor = sdk.document_manager.open_document(&test.view.id).await.unwrap(); + let editor = sdk.document_manager.open_block(&test.view.id).await.unwrap(); Self { sdk, editor } } diff --git a/frontend/rust-lib/flowy-folder/src/controller.rs b/frontend/rust-lib/flowy-folder/src/controller.rs index edc1eb12a6..68d2edd8d8 100644 --- a/frontend/rust-lib/flowy-folder/src/controller.rs +++ b/frontend/rust-lib/flowy-folder/src/controller.rs @@ -6,7 +6,7 @@ use flowy_sync::RevisionWebSocket; use lazy_static::lazy_static; use flowy_collaboration::{client_folder::FolderPad, entities::ws_data::ServerRevisionWSData}; -use flowy_document::FlowyDocumentManager; +use flowy_document::BlockManager; use std::{collections::HashMap, convert::TryInto, fmt::Formatter, sync::Arc}; use tokio::sync::RwLock as TokioRwLock; @@ -71,7 +71,7 @@ impl FolderManager { user: Arc, cloud_service: Arc, database: Arc, - document_manager: Arc, + document_manager: Arc, web_socket: Arc, ) -> Self { if let Ok(user_id) = user.user_id() { diff --git a/frontend/rust-lib/flowy-folder/src/event_map.rs b/frontend/rust-lib/flowy-folder/src/event_map.rs index 8021d408fc..bd151f80b0 100644 --- a/frontend/rust-lib/flowy-folder/src/event_map.rs +++ b/frontend/rust-lib/flowy-folder/src/event_map.rs @@ -63,9 +63,9 @@ pub fn create(folder: Arc) -> Module { .event(FolderEvent::UpdateView, update_view_handler) .event(FolderEvent::DeleteView, delete_view_handler) .event(FolderEvent::DuplicateView, duplicate_view_handler) - .event(FolderEvent::OpenView, open_document_handler) + .event(FolderEvent::OpenView, open_view_handler) .event(FolderEvent::CloseView, close_view_handler) - .event(FolderEvent::ApplyDocDelta, document_delta_handler); + .event(FolderEvent::ApplyDocDelta, block_delta_handler); module = module .event(FolderEvent::ReadTrash, read_trash_handler) @@ -130,7 +130,7 @@ pub enum FolderEvent { #[event()] CopyLink = 206, - #[event(input = "ViewId", output = "DocumentDelta")] + #[event(input = "ViewId", output = "BlockDelta")] OpenView = 207, #[event(input = "ViewId")] @@ -151,7 +151,7 @@ pub enum FolderEvent { #[event()] DeleteAllTrash = 304, - #[event(input = "DocumentDelta", output = "DocumentDelta")] + #[event(input = "BlockDelta", output = "BlockDelta")] ApplyDocDelta = 400, #[event(input = "ExportPayload", output = "ExportData")] diff --git a/frontend/rust-lib/flowy-folder/src/services/app/event_handler.rs b/frontend/rust-lib/flowy-folder/src/services/app/event_handler.rs index 6c9b3df15c..f3f354d517 100644 --- a/frontend/rust-lib/flowy-folder/src/services/app/event_handler.rs +++ b/frontend/rust-lib/flowy-folder/src/services/app/event_handler.rs @@ -6,12 +6,12 @@ use crate::{ errors::FlowyError, services::{AppController, TrashController, ViewController}, }; -use lib_dispatch::prelude::{data_result, Data, DataResult, Unit}; +use lib_dispatch::prelude::{data_result, AppData, Data, DataResult}; use std::{convert::TryInto, sync::Arc}; pub(crate) async fn create_app_handler( data: Data, - controller: Unit>, + controller: AppData>, ) -> DataResult { let params: CreateAppParams = data.into_inner().try_into()?; let detail = controller.create_app_from_params(params).await?; @@ -21,8 +21,8 @@ pub(crate) async fn create_app_handler( pub(crate) async fn delete_app_handler( data: Data, - app_controller: Unit>, - trash_controller: Unit>, + app_controller: AppData>, + trash_controller: AppData>, ) -> Result<(), FlowyError> { let params: AppId = data.into_inner(); let trash = app_controller @@ -39,7 +39,7 @@ pub(crate) async fn delete_app_handler( #[tracing::instrument(skip(data, controller))] pub(crate) async fn update_app_handler( data: Data, - controller: Unit>, + controller: AppData>, ) -> Result<(), FlowyError> { let params: UpdateAppParams = data.into_inner().try_into()?; let _ = controller.update_app(params).await?; @@ -49,8 +49,8 @@ pub(crate) async fn update_app_handler( #[tracing::instrument(skip(data, app_controller, view_controller))] pub(crate) async fn read_app_handler( data: Data, - app_controller: Unit>, - view_controller: Unit>, + app_controller: AppData>, + view_controller: AppData>, ) -> DataResult { let params: AppId = data.into_inner(); let mut app = app_controller.read_app(params.clone()).await?; diff --git a/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs b/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs index ce3d421146..29365e71b0 100644 --- a/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs +++ b/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs @@ -8,8 +8,8 @@ use crate::controller::FolderId; use flowy_collaboration::util::make_delta_from_revisions; use flowy_error::{FlowyError, FlowyResult}; use flowy_sync::{ - RevisionCache, RevisionCloudService, RevisionCompact, RevisionManager, RevisionObjectBuilder, RevisionWebSocket, - RevisionWebSocketManager, + RevisionCloudService, RevisionCompact, RevisionManager, RevisionObjectBuilder, RevisionPersistence, + RevisionWebSocket, RevisionWebSocketManager, }; use lib_infra::future::FutureResult; use lib_ot::core::PlainAttributes; @@ -33,8 +33,8 @@ impl FolderEditor { pool: Arc, web_socket: Arc, ) -> FlowyResult { - let cache = Arc::new(RevisionCache::new(user_id, folder_id.as_ref(), pool)); - let mut rev_manager = RevisionManager::new(user_id, folder_id.as_ref(), cache); + let rev_persistence = Arc::new(RevisionPersistence::new(user_id, folder_id.as_ref(), pool)); + let mut rev_manager = RevisionManager::new(user_id, folder_id.as_ref(), rev_persistence); let cloud = Arc::new(FolderRevisionCloudServiceImpl { token: token.to_string(), }); diff --git a/frontend/rust-lib/flowy-folder/src/services/trash/event_handler.rs b/frontend/rust-lib/flowy-folder/src/services/trash/event_handler.rs index e35d91d6fa..1f7257a043 100644 --- a/frontend/rust-lib/flowy-folder/src/services/trash/event_handler.rs +++ b/frontend/rust-lib/flowy-folder/src/services/trash/event_handler.rs @@ -3,12 +3,12 @@ use crate::{ errors::FlowyError, services::TrashController, }; -use lib_dispatch::prelude::{data_result, Data, DataResult, Unit}; +use lib_dispatch::prelude::{data_result, AppData, Data, DataResult}; use std::sync::Arc; #[tracing::instrument(skip(controller), err)] pub(crate) async fn read_trash_handler( - controller: Unit>, + controller: AppData>, ) -> DataResult { let repeated_trash = controller.read_trash().await?; data_result(repeated_trash) @@ -17,7 +17,7 @@ pub(crate) async fn read_trash_handler( #[tracing::instrument(skip(identifier, controller), err)] pub(crate) async fn putback_trash_handler( identifier: Data, - controller: Unit>, + controller: AppData>, ) -> Result<(), FlowyError> { let _ = controller.putback(&identifier.id).await?; Ok(()) @@ -26,20 +26,20 @@ pub(crate) async fn putback_trash_handler( #[tracing::instrument(skip(identifiers, controller), err)] pub(crate) async fn delete_trash_handler( identifiers: Data, - controller: Unit>, + controller: AppData>, ) -> Result<(), FlowyError> { let _ = controller.delete(identifiers.into_inner()).await?; Ok(()) } #[tracing::instrument(skip(controller), err)] -pub(crate) async fn restore_all_trash_handler(controller: Unit>) -> Result<(), FlowyError> { +pub(crate) async fn restore_all_trash_handler(controller: AppData>) -> Result<(), FlowyError> { let _ = controller.restore_all_trash().await?; Ok(()) } #[tracing::instrument(skip(controller), err)] -pub(crate) async fn delete_all_trash_handler(controller: Unit>) -> Result<(), FlowyError> { +pub(crate) async fn delete_all_trash_handler(controller: AppData>) -> Result<(), FlowyError> { let _ = controller.delete_all_trash().await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs index 2f27c3f040..16bbe54949 100644 --- a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs +++ b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs @@ -1,6 +1,6 @@ use bytes::Bytes; use flowy_collaboration::entities::{ - document_info::{DocumentDelta, DocumentId}, + document_info::{BlockDelta, BlockId}, revision::{RepeatedRevision, Revision}, }; @@ -22,7 +22,7 @@ use crate::{ }, }; use flowy_database::kv::KV; -use flowy_document::FlowyDocumentManager; +use flowy_document::BlockManager; use flowy_folder_data_model::entities::share::{ExportData, ExportParams}; use lib_infra::uuid_string; @@ -33,7 +33,7 @@ pub(crate) struct ViewController { cloud_service: Arc, persistence: Arc, trash_controller: Arc, - document_manager: Arc, + block_manager: Arc, } impl ViewController { @@ -42,19 +42,19 @@ impl ViewController { persistence: Arc, cloud_service: Arc, trash_can: Arc, - document_manager: Arc, + document_manager: Arc, ) -> Self { Self { user, cloud_service, persistence, trash_controller: trash_can, - document_manager, + block_manager: document_manager, } } pub(crate) fn initialize(&self) -> Result<(), FlowyError> { - let _ = self.document_manager.init()?; + let _ = self.block_manager.init()?; self.listen_trash_can_event(); Ok(()) } @@ -72,7 +72,7 @@ impl ViewController { let repeated_revision: RepeatedRevision = Revision::initial_revision(&user_id, ¶ms.view_id, delta_data).into(); let _ = self - .document_manager + .block_manager .reset_with_revisions(¶ms.view_id, repeated_revision) .await?; let view = self.create_view_on_server(params).await?; @@ -95,7 +95,7 @@ impl ViewController { let user_id = self.user.user_id()?; let repeated_revision: RepeatedRevision = Revision::initial_revision(&user_id, view_id, delta_data).into(); let _ = self - .document_manager + .block_manager .reset_with_revisions(view_id, repeated_revision) .await?; Ok(()) @@ -143,42 +143,42 @@ impl ViewController { } #[tracing::instrument(level = "debug", skip(self), err)] - pub(crate) async fn open_document(&self, doc_id: &str) -> Result { - let editor = self.document_manager.open_document(doc_id).await?; - KV::set_str(LATEST_VIEW_ID, doc_id.to_owned()); - let document_json = editor.document_json().await?; - Ok(DocumentDelta { - doc_id: doc_id.to_string(), + pub(crate) async fn open_view(&self, view_id: &str) -> Result { + let editor = self.block_manager.open_block(view_id).await?; + KV::set_str(LATEST_VIEW_ID, view_id.to_owned()); + let document_json = editor.block_json().await?; + Ok(BlockDelta { + block_id: view_id.to_string(), delta_json: document_json, }) } #[tracing::instrument(level = "debug", skip(self), err)] pub(crate) async fn close_view(&self, doc_id: &str) -> Result<(), FlowyError> { - let _ = self.document_manager.close_document(doc_id)?; + let _ = self.block_manager.close_block(doc_id)?; Ok(()) } #[tracing::instrument(level = "debug", skip(self,params), fields(doc_id = %params.value), err)] - pub(crate) async fn delete_view(&self, params: DocumentId) -> Result<(), FlowyError> { + pub(crate) async fn delete_view(&self, params: BlockId) -> Result<(), FlowyError> { if let Some(view_id) = KV::get_str(LATEST_VIEW_ID) { if view_id == params.value { let _ = KV::remove(LATEST_VIEW_ID); } } - let _ = self.document_manager.close_document(¶ms.value)?; + let _ = self.block_manager.close_block(¶ms.value)?; Ok(()) } #[tracing::instrument(level = "debug", skip(self), err)] - pub(crate) async fn duplicate_view(&self, doc_id: &str) -> Result<(), FlowyError> { + pub(crate) async fn duplicate_view(&self, view_id: &str) -> Result<(), FlowyError> { let view = self .persistence - .begin_transaction(|transaction| transaction.read_view(doc_id)) + .begin_transaction(|transaction| transaction.read_view(view_id)) .await?; - let editor = self.document_manager.open_document(doc_id).await?; - let document_json = editor.document_json().await?; + let editor = self.block_manager.open_block(view_id).await?; + let document_json = editor.block_json().await?; let duplicate_params = CreateViewParams { belong_to_id: view.belong_to_id.clone(), name: format!("{} (copy)", &view.name), @@ -194,9 +194,9 @@ impl ViewController { } #[tracing::instrument(level = "debug", skip(self, params), err)] - pub(crate) async fn export_doc(&self, params: ExportParams) -> Result { - let editor = self.document_manager.open_document(¶ms.doc_id).await?; - let delta_json = editor.document_json().await?; + pub(crate) async fn export_view(&self, params: ExportParams) -> Result { + let editor = self.block_manager.open_block(¶ms.view_id).await?; + let delta_json = editor.block_json().await?; Ok(ExportData { data: delta_json, export_type: params.export_type, @@ -234,8 +234,8 @@ impl ViewController { Ok(view) } - pub(crate) async fn receive_document_delta(&self, params: DocumentDelta) -> Result { - let doc = self.document_manager.receive_local_delta(params).await?; + pub(crate) async fn receive_delta(&self, params: BlockDelta) -> Result { + let doc = self.block_manager.receive_local_delta(params).await?; Ok(doc) } @@ -312,7 +312,7 @@ impl ViewController { fn listen_trash_can_event(&self) { let mut rx = self.trash_controller.subscribe(); let persistence = self.persistence.clone(); - let document_manager = self.document_manager.clone(); + let document_manager = self.block_manager.clone(); let trash_controller = self.trash_controller.clone(); let _ = tokio::spawn(async move { loop { @@ -340,7 +340,7 @@ impl ViewController { #[tracing::instrument(level = "trace", skip(persistence, document_manager, trash_can))] async fn handle_trash_event( persistence: Arc, - document_manager: Arc, + document_manager: Arc, trash_can: Arc, event: TrashEvent, ) { diff --git a/frontend/rust-lib/flowy-folder/src/services/view/event_handler.rs b/frontend/rust-lib/flowy-folder/src/services/view/event_handler.rs index 1389336b55..002a2ac24f 100644 --- a/frontend/rust-lib/flowy-folder/src/services/view/event_handler.rs +++ b/frontend/rust-lib/flowy-folder/src/services/view/event_handler.rs @@ -8,14 +8,14 @@ use crate::{ errors::FlowyError, services::{TrashController, ViewController}, }; -use flowy_collaboration::entities::document_info::DocumentDelta; +use flowy_collaboration::entities::document_info::BlockDelta; use flowy_folder_data_model::entities::share::{ExportData, ExportParams, ExportPayload}; -use lib_dispatch::prelude::{data_result, Data, DataResult, Unit}; +use lib_dispatch::prelude::{data_result, AppData, Data, DataResult}; use std::{convert::TryInto, sync::Arc}; pub(crate) async fn create_view_handler( data: Data, - controller: Unit>, + controller: AppData>, ) -> DataResult { let params: CreateViewParams = data.into_inner().try_into()?; let view = controller.create_view_from_params(params).await?; @@ -24,7 +24,7 @@ pub(crate) async fn create_view_handler( pub(crate) async fn read_view_handler( data: Data, - controller: Unit>, + controller: AppData>, ) -> DataResult { let view_id: ViewId = data.into_inner(); let mut view = controller.read_view(view_id.clone()).await?; @@ -38,7 +38,7 @@ pub(crate) async fn read_view_handler( #[tracing::instrument(skip(data, controller), err)] pub(crate) async fn update_view_handler( data: Data, - controller: Unit>, + controller: AppData>, ) -> Result<(), FlowyError> { let params: UpdateViewParams = data.into_inner().try_into()?; let _ = controller.update_view(params).await?; @@ -46,18 +46,18 @@ pub(crate) async fn update_view_handler( Ok(()) } -pub(crate) async fn document_delta_handler( - data: Data, - controller: Unit>, -) -> DataResult { - let doc = controller.receive_document_delta(data.into_inner()).await?; - data_result(doc) +pub(crate) async fn block_delta_handler( + data: Data, + controller: AppData>, +) -> DataResult { + let block_delta = controller.receive_delta(data.into_inner()).await?; + data_result(block_delta) } pub(crate) async fn delete_view_handler( data: Data, - view_controller: Unit>, - trash_controller: Unit>, + view_controller: AppData>, + trash_controller: AppData>, ) -> Result<(), FlowyError> { let params: RepeatedViewId = data.into_inner(); for view_id in ¶ms.items { @@ -75,18 +75,18 @@ pub(crate) async fn delete_view_handler( Ok(()) } -pub(crate) async fn open_document_handler( +pub(crate) async fn open_view_handler( data: Data, - controller: Unit>, -) -> DataResult { + controller: AppData>, +) -> DataResult { let view_id: ViewId = data.into_inner(); - let doc = controller.open_document(&view_id.value).await?; + let doc = controller.open_view(&view_id.value).await?; data_result(doc) } pub(crate) async fn close_view_handler( data: Data, - controller: Unit>, + controller: AppData>, ) -> Result<(), FlowyError> { let view_id: ViewId = data.into_inner(); let _ = controller.close_view(&view_id.value).await?; @@ -96,7 +96,7 @@ pub(crate) async fn close_view_handler( #[tracing::instrument(skip(data, controller), err)] pub(crate) async fn duplicate_view_handler( data: Data, - controller: Unit>, + controller: AppData>, ) -> Result<(), FlowyError> { let view_id: ViewId = data.into_inner(); let _ = controller.duplicate_view(&view_id.value).await?; @@ -106,9 +106,9 @@ pub(crate) async fn duplicate_view_handler( #[tracing::instrument(skip(data, controller), err)] pub(crate) async fn export_handler( data: Data, - controller: Unit>, + controller: AppData>, ) -> DataResult { let params: ExportParams = data.into_inner().try_into()?; - let data = controller.export_doc(params).await?; + let data = controller.export_view(params).await?; data_result(data) } diff --git a/frontend/rust-lib/flowy-folder/src/services/web_socket.rs b/frontend/rust-lib/flowy-folder/src/services/web_socket.rs index 95c8fb2ead..c3b20f9c87 100644 --- a/frontend/rust-lib/flowy-folder/src/services/web_socket.rs +++ b/frontend/rust-lib/flowy-folder/src/services/web_socket.rs @@ -21,44 +21,36 @@ pub(crate) async fn make_folder_ws_manager( web_socket: Arc, folder_pad: Arc>, ) -> Arc { - let composite_sink_provider = Arc::new(CompositeWSSinkDataProvider::new(folder_id, rev_manager.clone())); - let resolve_target = Arc::new(FolderRevisionResolveTarget { folder_pad }); - let resolver = RevisionConflictResolver::::new( - user_id, - resolve_target, - Arc::new(composite_sink_provider.clone()), - rev_manager, - ); - - let ws_stream_consumer = Arc::new(FolderWSStreamConsumerAdapter { - resolver: Arc::new(resolver), - }); - - let sink_provider = Arc::new(FolderWSSinkDataProviderAdapter(composite_sink_provider)); + let ws_data_provider = Arc::new(WSDataProvider::new(folder_id, Arc::new(rev_manager.clone()))); + let resolver = Arc::new(FolderConflictResolver { folder_pad }); + let conflict_controller = + ConflictController::::new(user_id, resolver, Arc::new(ws_data_provider.clone()), rev_manager); + let ws_data_stream = Arc::new(FolderRevisionWSDataStream::new(conflict_controller)); + let ws_data_sink = Arc::new(FolderWSDataSink(ws_data_provider)); let ping_duration = Duration::from_millis(FOLDER_SYNC_INTERVAL_IN_MILLIS); Arc::new(RevisionWebSocketManager::new( "Folder", folder_id, web_socket, - sink_provider, - ws_stream_consumer, + ws_data_sink, + ws_data_stream, ping_duration, )) } -pub(crate) struct FolderWSSinkDataProviderAdapter(Arc); -impl RevisionWSSinkDataProvider for FolderWSSinkDataProviderAdapter { +pub(crate) struct FolderWSDataSink(Arc); +impl RevisionWSDataIterator for FolderWSDataSink { fn next(&self) -> FutureResult, FlowyError> { let sink_provider = self.0.clone(); FutureResult::new(async move { sink_provider.next().await }) } } -struct FolderRevisionResolveTarget { +struct FolderConflictResolver { folder_pad: Arc>, } -impl ResolverTarget for FolderRevisionResolveTarget { +impl ConflictResolver for FolderConflictResolver { fn compose_delta(&self, delta: Delta) -> BoxResultFuture { let folder_pad = self.folder_pad.clone(); Box::pin(async move { @@ -101,18 +93,26 @@ impl ResolverTarget for FolderRevisionResolveTarget { } } -struct FolderWSStreamConsumerAdapter { - resolver: Arc>, +struct FolderRevisionWSDataStream { + conflict_controller: Arc>, } -impl RevisionWSSteamConsumer for FolderWSStreamConsumerAdapter { +impl FolderRevisionWSDataStream { + pub fn new(conflict_controller: ConflictController) -> Self { + Self { + conflict_controller: Arc::new(conflict_controller), + } + } +} + +impl RevisionWSDataStream for FolderRevisionWSDataStream { fn receive_push_revision(&self, bytes: Bytes) -> BoxResultFuture<(), FlowyError> { - let resolver = self.resolver.clone(); + let resolver = self.conflict_controller.clone(); Box::pin(async move { resolver.receive_bytes(bytes).await }) } fn receive_ack(&self, id: String, ty: ServerRevisionWSDataType) -> BoxResultFuture<(), FlowyError> { - let resolver = self.resolver.clone(); + let resolver = self.conflict_controller.clone(); Box::pin(async move { resolver.ack_revision(id, ty).await }) } @@ -122,7 +122,7 @@ impl RevisionWSSteamConsumer for FolderWSStreamConsumerAdapter { } fn pull_revisions_in_range(&self, range: RevisionRange) -> BoxResultFuture<(), FlowyError> { - let resolver = self.resolver.clone(); + let resolver = self.conflict_controller.clone(); Box::pin(async move { resolver.send_revisions(range).await }) } } diff --git a/frontend/rust-lib/flowy-folder/src/services/workspace/event_handler.rs b/frontend/rust-lib/flowy-folder/src/services/workspace/event_handler.rs index cd44966273..5b464f25e4 100644 --- a/frontend/rust-lib/flowy-folder/src/services/workspace/event_handler.rs +++ b/frontend/rust-lib/flowy-folder/src/services/workspace/event_handler.rs @@ -10,13 +10,13 @@ use flowy_folder_data_model::entities::{ workspace::{CurrentWorkspaceSetting, RepeatedWorkspace, WorkspaceId, *}, }; -use lib_dispatch::prelude::{data_result, Data, DataResult, Unit}; +use lib_dispatch::prelude::{data_result, AppData, Data, DataResult}; use std::{convert::TryInto, sync::Arc}; #[tracing::instrument(skip(data, controller), err)] pub(crate) async fn create_workspace_handler( data: Data, - controller: Unit>, + controller: AppData>, ) -> DataResult { let controller = controller.get_ref().clone(); let params: CreateWorkspaceParams = data.into_inner().try_into()?; @@ -26,7 +26,7 @@ pub(crate) async fn create_workspace_handler( #[tracing::instrument(skip(controller), err)] pub(crate) async fn read_workspace_apps_handler( - controller: Unit>, + controller: AppData>, ) -> DataResult { let repeated_app = controller.read_current_workspace_apps().await?; data_result(repeated_app) @@ -35,7 +35,7 @@ pub(crate) async fn read_workspace_apps_handler( #[tracing::instrument(skip(data, controller), err)] pub(crate) async fn open_workspace_handler( data: Data, - controller: Unit>, + controller: AppData>, ) -> DataResult { let params: WorkspaceId = data.into_inner(); let workspaces = controller.open_workspace(params).await?; @@ -45,7 +45,7 @@ pub(crate) async fn open_workspace_handler( #[tracing::instrument(skip(data, folder), err)] pub(crate) async fn read_workspaces_handler( data: Data, - folder: Unit>, + folder: AppData>, ) -> DataResult { let params: WorkspaceId = data.into_inner(); let user_id = folder.user.user_id()?; @@ -71,7 +71,7 @@ pub(crate) async fn read_workspaces_handler( #[tracing::instrument(skip(folder), err)] pub async fn read_cur_workspace_handler( - folder: Unit>, + folder: AppData>, ) -> DataResult { let workspace_id = get_current_workspace()?; let user_id = folder.user.user_id()?; @@ -96,7 +96,7 @@ pub async fn read_cur_workspace_handler( #[tracing::instrument(level = "trace", skip(folder_manager), err)] fn read_workspaces_on_server( - folder_manager: Unit>, + folder_manager: AppData>, user_id: String, params: WorkspaceId, ) -> Result<(), FlowyError> { diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs b/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs index 73605eef69..09935c7248 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs @@ -1,4 +1,4 @@ -use flowy_collaboration::entities::document_info::DocumentInfo; +use flowy_collaboration::entities::document_info::BlockInfo; use flowy_folder::event_map::FolderEvent::*; use flowy_folder_data_model::entities::view::{RepeatedViewId, ViewId}; use flowy_folder_data_model::entities::workspace::WorkspaceId; @@ -159,14 +159,14 @@ pub async fn delete_view(sdk: &FlowySDKTest, view_ids: Vec) { .await; } -pub async fn open_document(sdk: &FlowySDKTest, view_id: &str) -> DocumentInfo { +pub async fn open_document(sdk: &FlowySDKTest, view_id: &str) -> BlockInfo { let view_id: ViewId = view_id.into(); FolderEventBuilder::new(sdk.clone()) .event(OpenView) .payload(view_id) .async_send() .await - .parse::() + .parse::() } pub async fn read_trash(sdk: &FlowySDKTest) -> RepeatedTrash { diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs index df2d6259d5..eb05dd894b 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs @@ -1,5 +1,5 @@ use crate::helper::*; -use flowy_collaboration::entities::{document_info::DocumentInfo, revision::RevisionState}; +use flowy_collaboration::entities::{document_info::BlockInfo, revision::RevisionState}; use flowy_folder::{errors::ErrorCode, services::folder_editor::FolderEditor}; use flowy_folder_data_model::entities::{ app::{App, RepeatedApp}, @@ -58,7 +58,7 @@ pub struct FolderTest { pub app: App, pub view: View, pub trash: Vec, - pub document_info: Option, + pub document_info: Option, // pub folder_editor: } diff --git a/frontend/rust-lib/flowy-net/src/handlers/mod.rs b/frontend/rust-lib/flowy-net/src/handlers/mod.rs index 62d248748c..bb2f58fb4c 100644 --- a/frontend/rust-lib/flowy-net/src/handlers/mod.rs +++ b/frontend/rust-lib/flowy-net/src/handlers/mod.rs @@ -1,12 +1,12 @@ use crate::{entities::NetworkState, ws::connection::FlowyWebSocketConnect}; use flowy_error::FlowyError; -use lib_dispatch::prelude::{Data, Unit}; +use lib_dispatch::prelude::{AppData, Data}; use std::sync::Arc; #[tracing::instrument(skip(data, ws_manager))] pub async fn update_network_ty( data: Data, - ws_manager: Unit>, + ws_manager: AppData>, ) -> Result<(), FlowyError> { let network_state = data.into_inner(); ws_manager.update_network_type(&network_state.ty); diff --git a/frontend/rust-lib/flowy-net/src/http_server/document.rs b/frontend/rust-lib/flowy-net/src/http_server/document.rs index e4d8722ca8..3e2f4af69a 100644 --- a/frontend/rust-lib/flowy-net/src/http_server/document.rs +++ b/frontend/rust-lib/flowy-net/src/http_server/document.rs @@ -2,45 +2,45 @@ use crate::{ configuration::*, request::{HttpRequestBuilder, ResponseMiddleware}, }; -use flowy_collaboration::entities::document_info::{CreateDocParams, DocumentId, DocumentInfo, ResetDocumentParams}; -use flowy_document::DocumentCloudService; +use flowy_collaboration::entities::document_info::{BlockId, BlockInfo, CreateBlockParams, ResetDocumentParams}; +use flowy_document::BlockCloudService; use flowy_error::FlowyError; use http_flowy::response::FlowyResponse; use lazy_static::lazy_static; use lib_infra::future::FutureResult; use std::sync::Arc; -pub struct DocumentHttpCloudService { +pub struct BlockHttpCloudService { config: ClientServerConfiguration, } -impl DocumentHttpCloudService { +impl BlockHttpCloudService { pub fn new(config: ClientServerConfiguration) -> Self { Self { config } } } -impl DocumentCloudService for DocumentHttpCloudService { - fn create_document(&self, token: &str, params: CreateDocParams) -> FutureResult<(), FlowyError> { +impl BlockCloudService for BlockHttpCloudService { + fn create_block(&self, token: &str, params: CreateBlockParams) -> FutureResult<(), FlowyError> { let token = token.to_owned(); let url = self.config.doc_url(); FutureResult::new(async move { create_document_request(&token, params, &url).await }) } - fn read_document(&self, token: &str, params: DocumentId) -> FutureResult, FlowyError> { + fn read_block(&self, token: &str, params: BlockId) -> FutureResult, FlowyError> { let token = token.to_owned(); let url = self.config.doc_url(); FutureResult::new(async move { read_document_request(&token, params, &url).await }) } - fn update_document(&self, token: &str, params: ResetDocumentParams) -> FutureResult<(), FlowyError> { + fn update_block(&self, token: &str, params: ResetDocumentParams) -> FutureResult<(), FlowyError> { let token = token.to_owned(); let url = self.config.doc_url(); FutureResult::new(async move { reset_doc_request(&token, params, &url).await }) } } -pub async fn create_document_request(token: &str, params: CreateDocParams, url: &str) -> Result<(), FlowyError> { +pub async fn create_document_request(token: &str, params: CreateBlockParams, url: &str) -> Result<(), FlowyError> { let _ = request_builder() .post(&url.to_owned()) .header(HEADER_TOKEN, token) @@ -50,11 +50,7 @@ pub async fn create_document_request(token: &str, params: CreateDocParams, url: Ok(()) } -pub async fn read_document_request( - token: &str, - params: DocumentId, - url: &str, -) -> Result, FlowyError> { +pub async fn read_document_request(token: &str, params: BlockId, url: &str) -> Result, FlowyError> { let doc = request_builder() .get(&url.to_owned()) .header(HEADER_TOKEN, token) diff --git a/frontend/rust-lib/flowy-net/src/local_server/persistence.rs b/frontend/rust-lib/flowy-net/src/local_server/persistence.rs index 8a0a8dcff0..db23fbf2ef 100644 --- a/frontend/rust-lib/flowy-net/src/local_server/persistence.rs +++ b/frontend/rust-lib/flowy-net/src/local_server/persistence.rs @@ -1,5 +1,5 @@ use flowy_collaboration::{ - entities::{document_info::DocumentInfo, folder_info::FolderInfo}, + entities::{document_info::BlockInfo, folder_info::FolderInfo}, errors::CollaborateError, protobuf::{RepeatedRevision as RepeatedRevisionPB, Revision as RevisionPB}, server_document::*, @@ -111,7 +111,7 @@ impl FolderCloudPersistence for LocalDocumentCloudPersistence { } impl DocumentCloudPersistence for LocalDocumentCloudPersistence { - fn read_document(&self, doc_id: &str) -> BoxResultFuture { + fn read_document(&self, doc_id: &str) -> BoxResultFuture { let storage = self.storage.clone(); let doc_id = doc_id.to_owned(); Box::pin(async move { @@ -127,7 +127,7 @@ impl DocumentCloudPersistence for LocalDocumentCloudPersistence { &self, doc_id: &str, repeated_revision: RepeatedRevisionPB, - ) -> BoxResultFuture, CollaborateError> { + ) -> BoxResultFuture, CollaborateError> { let doc_id = doc_id.to_owned(); let storage = self.storage.clone(); Box::pin(async move { diff --git a/frontend/rust-lib/flowy-net/src/local_server/server.rs b/frontend/rust-lib/flowy-net/src/local_server/server.rs index 22df42c64e..363df41777 100644 --- a/frontend/rust-lib/flowy-net/src/local_server/server.rs +++ b/frontend/rust-lib/flowy-net/src/local_server/server.rs @@ -4,7 +4,7 @@ use bytes::Bytes; use flowy_collaboration::{ client_document::default::initial_delta_string, entities::{ - document_info::{CreateDocParams, DocumentId, DocumentInfo, ResetDocumentParams}, + document_info::{BlockId, BlockInfo, CreateBlockParams, ResetDocumentParams}, ws_data::{ClientRevisionWSData, ClientRevisionWSDataType}, }, errors::CollaborateError, @@ -248,7 +248,7 @@ impl RevisionUser for LocalRevisionUser { } } -use flowy_document::DocumentCloudService; +use flowy_document::BlockCloudService; use flowy_folder_data_model::entities::{ app::{App, AppId, CreateAppParams, RepeatedApp, UpdateAppParams}, trash::{RepeatedTrash, RepeatedTrashId}, @@ -406,13 +406,13 @@ impl UserCloudService for LocalServer { } } -impl DocumentCloudService for LocalServer { - fn create_document(&self, _token: &str, _params: CreateDocParams) -> FutureResult<(), FlowyError> { +impl BlockCloudService for LocalServer { + fn create_block(&self, _token: &str, _params: CreateBlockParams) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } - fn read_document(&self, _token: &str, params: DocumentId) -> FutureResult, FlowyError> { - let doc = DocumentInfo { + fn read_block(&self, _token: &str, params: BlockId) -> FutureResult, FlowyError> { + let doc = BlockInfo { doc_id: params.value, text: initial_delta_string(), rev_id: 0, @@ -421,7 +421,7 @@ impl DocumentCloudService for LocalServer { FutureResult::new(async { Ok(Some(doc)) }) } - fn update_document(&self, _token: &str, _params: ResetDocumentParams) -> FutureResult<(), FlowyError> { + fn update_block(&self, _token: &str, _params: ResetDocumentParams) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } } diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs index 641e6631dc..5de869609c 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs @@ -3,11 +3,11 @@ use flowy_collaboration::entities::ws_data::ClientRevisionWSData; use flowy_database::ConnectionPool; use flowy_document::{ errors::{internal_error, FlowyError}, - DocumentCloudService, DocumentUser, FlowyDocumentManager, + BlockCloudService, BlockManager, BlockUser, }; use flowy_net::ClientServerConfiguration; use flowy_net::{ - http_server::document::DocumentHttpCloudService, local_server::LocalServer, ws::connection::FlowyWebSocketConnect, + http_server::document::BlockHttpCloudService, local_server::LocalServer, ws::connection::FlowyWebSocketConnect, }; use flowy_sync::{RevisionWebSocket, WSStateReceiver}; use flowy_user::services::UserSession; @@ -23,15 +23,15 @@ impl DocumentDepsResolver { ws_conn: Arc, user_session: Arc, server_config: &ClientServerConfiguration, - ) -> Arc { + ) -> Arc { let user = Arc::new(DocumentUserImpl(user_session)); - let ws_sender = Arc::new(DocumentWebSocketImpl(ws_conn.clone())); - let cloud_service: Arc = match local_server { - None => Arc::new(DocumentHttpCloudService::new(server_config.clone())), + let ws_sender = Arc::new(BlockWebSocket(ws_conn.clone())); + let cloud_service: Arc = match local_server { + None => Arc::new(BlockHttpCloudService::new(server_config.clone())), Some(local_server) => local_server, }; - let manager = Arc::new(FlowyDocumentManager::new(cloud_service, user, ws_sender)); + let manager = Arc::new(BlockManager::new(cloud_service, user, ws_sender)); let receiver = Arc::new(DocumentWSMessageReceiverImpl(manager.clone())); ws_conn.add_ws_message_receiver(receiver).unwrap(); @@ -40,7 +40,7 @@ impl DocumentDepsResolver { } struct DocumentUserImpl(Arc); -impl DocumentUser for DocumentUserImpl { +impl BlockUser for DocumentUserImpl { fn user_dir(&self) -> Result { let dir = self.0.user_dir().map_err(|e| FlowyError::unauthorized().context(e))?; @@ -64,8 +64,8 @@ impl DocumentUser for DocumentUserImpl { } } -struct DocumentWebSocketImpl(Arc); -impl RevisionWebSocket for DocumentWebSocketImpl { +struct BlockWebSocket(Arc); +impl RevisionWebSocket for BlockWebSocket { fn send(&self, data: ClientRevisionWSData) -> BoxResultFuture<(), FlowyError> { let bytes: Bytes = data.try_into().unwrap(); let msg = WebSocketRawMessage { @@ -90,7 +90,7 @@ impl RevisionWebSocket for DocumentWebSocketImpl { } } -struct DocumentWSMessageReceiverImpl(Arc); +struct DocumentWSMessageReceiverImpl(Arc); impl WSMessageReceiver for DocumentWSMessageReceiverImpl { fn source(&self) -> WSChannel { WSChannel::Document diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs index 68a5a1011e..cfa0f88fb5 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs @@ -1,7 +1,7 @@ use bytes::Bytes; use flowy_collaboration::entities::ws_data::ClientRevisionWSData; use flowy_database::ConnectionPool; -use flowy_document::FlowyDocumentManager; +use flowy_document::BlockManager; use flowy_folder::{ controller::FolderManager, errors::{internal_error, FlowyError}, @@ -24,12 +24,12 @@ impl FolderDepsResolver { local_server: Option>, user_session: Arc, server_config: &ClientServerConfiguration, - document_manager: &Arc, + document_manager: &Arc, ws_conn: Arc, ) -> Arc { let user: Arc = Arc::new(WorkspaceUserImpl(user_session.clone())); let database: Arc = Arc::new(WorkspaceDatabaseImpl(user_session)); - let web_socket = Arc::new(FolderWebSocketImpl(ws_conn.clone())); + let web_socket = Arc::new(FolderWebSocket(ws_conn.clone())); let cloud_service: Arc = match local_server { None => Arc::new(FolderHttpCloudService::new(server_config.clone())), Some(local_server) => local_server, @@ -78,8 +78,8 @@ impl WorkspaceUser for WorkspaceUserImpl { } } -struct FolderWebSocketImpl(Arc); -impl RevisionWebSocket for FolderWebSocketImpl { +struct FolderWebSocket(Arc); +impl RevisionWebSocket for FolderWebSocket { fn send(&self, data: ClientRevisionWSData) -> BoxResultFuture<(), FlowyError> { let bytes: Bytes = data.try_into().unwrap(); let msg = WebSocketRawMessage { diff --git a/frontend/rust-lib/flowy-sdk/src/lib.rs b/frontend/rust-lib/flowy-sdk/src/lib.rs index 779af9a53d..6002243117 100644 --- a/frontend/rust-lib/flowy-sdk/src/lib.rs +++ b/frontend/rust-lib/flowy-sdk/src/lib.rs @@ -3,7 +3,7 @@ pub mod module; pub use flowy_net::get_client_server_configuration; use crate::deps_resolve::*; -use flowy_document::FlowyDocumentManager; +use flowy_document::BlockManager; use flowy_folder::{controller::FolderManager, errors::FlowyError}; use flowy_net::ClientServerConfiguration; use flowy_net::{ @@ -85,7 +85,7 @@ pub struct FlowySDK { #[allow(dead_code)] config: FlowySDKConfig, pub user_session: Arc, - pub document_manager: Arc, + pub document_manager: Arc, pub folder_manager: Arc, pub dispatcher: Arc, pub ws_conn: Arc, diff --git a/frontend/rust-lib/flowy-sync/Cargo.toml b/frontend/rust-lib/flowy-sync/Cargo.toml index 2aadd7b3be..0d7476eda3 100644 --- a/frontend/rust-lib/flowy-sync/Cargo.toml +++ b/frontend/rust-lib/flowy-sync/Cargo.toml @@ -26,7 +26,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = {version = "1.0"} futures-util = "0.3.15" async-stream = "0.3.2" - +async-trait = "0.1.52" [features] flowy_unit_test = ["lib-ot/flowy_unit_test"] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-sync/src/cache/mod.rs b/frontend/rust-lib/flowy-sync/src/cache/mod.rs index 586a705977..b32ec43c81 100644 --- a/frontend/rust-lib/flowy-sync/src/cache/mod.rs +++ b/frontend/rust-lib/flowy-sync/src/cache/mod.rs @@ -18,15 +18,15 @@ use tokio::task::spawn_blocking; pub const REVISION_WRITE_INTERVAL_IN_MILLIS: u64 = 600; -pub struct RevisionCache { +pub struct RevisionPersistence { user_id: String, object_id: String, disk_cache: Arc>, memory_cache: Arc, sync_seq: RwLock, } -impl RevisionCache { - pub fn new(user_id: &str, object_id: &str, pool: Arc) -> RevisionCache { +impl RevisionPersistence { + pub fn new(user_id: &str, object_id: &str, pool: Arc) -> RevisionPersistence { let disk_cache = Arc::new(SQLitePersistence::new(user_id, pool)); let memory_cache = Arc::new(RevisionMemoryCache::new(object_id, Arc::new(disk_cache.clone()))); let object_id = object_id.to_owned(); diff --git a/frontend/rust-lib/flowy-sync/src/conflict_resolve.rs b/frontend/rust-lib/flowy-sync/src/conflict_resolve.rs index d294fb3f0d..ec3f897e54 100644 --- a/frontend/rust-lib/flowy-sync/src/conflict_resolve.rs +++ b/frontend/rust-lib/flowy-sync/src/conflict_resolve.rs @@ -15,7 +15,7 @@ use std::{convert::TryFrom, sync::Arc}; pub type DeltaMD5 = String; -pub trait ResolverTarget +pub trait ConflictResolver where T: Attributes + Send + Sync, { @@ -24,35 +24,35 @@ where fn reset_delta(&self, delta: Delta) -> BoxResultFuture; } -pub trait ResolverRevisionSink: Send + Sync + 'static { +pub trait ConflictRevisionSink: Send + Sync + 'static { fn send(&self, revisions: Vec) -> BoxResultFuture<(), FlowyError>; fn ack(&self, rev_id: String, ty: ServerRevisionWSDataType) -> BoxResultFuture<(), FlowyError>; } -pub struct RevisionConflictResolver +pub struct ConflictController where T: Attributes + Send + Sync, { user_id: String, - target: Arc + Send + Sync>, - rev_sink: Arc, + resolver: Arc + Send + Sync>, + rev_sink: Arc, rev_manager: Arc, } -impl RevisionConflictResolver +impl ConflictController where T: Attributes + Send + Sync + DeserializeOwned + serde::Serialize, { pub fn new( user_id: &str, - target: Arc + Send + Sync>, - rev_sink: Arc, + resolver: Arc + Send + Sync>, + rev_sink: Arc, rev_manager: Arc, ) -> Self { let user_id = user_id.to_owned(); Self { user_id, - target, + resolver, rev_sink, rev_manager, } @@ -104,20 +104,20 @@ where let TransformDeltas { client_prime, server_prime, - } = self.target.transform_delta(new_delta).await?; + } = self.resolver.transform_delta(new_delta).await?; match server_prime { None => { // The server_prime is None means the client local revisions conflict with the // // server, and it needs to override the client delta. - let md5 = self.target.reset_delta(client_prime).await?; + let md5 = self.resolver.reset_delta(client_prime).await?; let repeated_revision = RepeatedRevision::new(revisions); assert_eq!(repeated_revision.last().unwrap().md5, md5); let _ = self.rev_manager.reset_object(repeated_revision).await?; Ok(None) } Some(server_prime) => { - let md5 = self.target.compose_delta(client_prime.clone()).await?; + let md5 = self.resolver.compose_delta(client_prime.clone()).await?; for revision in &revisions { let _ = self.rev_manager.add_remote_revision(revision).await?; } diff --git a/frontend/rust-lib/flowy-sync/src/rev_manager.rs b/frontend/rust-lib/flowy-sync/src/rev_manager.rs index 19944905fe..468872428a 100644 --- a/frontend/rust-lib/flowy-sync/src/rev_manager.rs +++ b/frontend/rust-lib/flowy-sync/src/rev_manager.rs @@ -1,11 +1,10 @@ -use crate::RevisionCache; +use crate::{RevisionPersistence, WSDataProviderDataSource}; use flowy_collaboration::{ entities::revision::{RepeatedRevision, Revision, RevisionRange, RevisionState}, util::{pair_rev_id_from_revisions, RevIdCounter}, }; use flowy_error::{FlowyError, FlowyResult}; use lib_infra::future::FutureResult; - use std::sync::Arc; pub trait RevisionCloudService: Send + Sync { @@ -25,14 +24,14 @@ pub struct RevisionManager { pub object_id: String, user_id: String, rev_id_counter: RevIdCounter, - rev_cache: Arc, + rev_persistence: Arc, #[cfg(feature = "flowy_unit_test")] rev_ack_notifier: tokio::sync::broadcast::Sender, } impl RevisionManager { - pub fn new(user_id: &str, object_id: &str, rev_cache: Arc) -> Self { + pub fn new(user_id: &str, object_id: &str, rev_persistence: Arc) -> Self { let rev_id_counter = RevIdCounter::new(0); #[cfg(feature = "flowy_unit_test")] let (revision_ack_notifier, _) = tokio::sync::broadcast::channel(1); @@ -41,7 +40,7 @@ impl RevisionManager { object_id: object_id.to_string(), user_id: user_id.to_owned(), rev_id_counter, - rev_cache, + rev_persistence, #[cfg(feature = "flowy_unit_test")] rev_ack_notifier: revision_ack_notifier, @@ -57,7 +56,7 @@ impl RevisionManager { object_id: self.object_id.clone(), user_id: self.user_id.clone(), cloud, - rev_cache: self.rev_cache.clone(), + rev_cache: self.rev_persistence.clone(), } .load() .await?; @@ -68,7 +67,7 @@ impl RevisionManager { #[tracing::instrument(level = "debug", skip(self, revisions), err)] pub async fn reset_object(&self, revisions: RepeatedRevision) -> FlowyResult<()> { let rev_id = pair_rev_id_from_revisions(&revisions).1; - let _ = self.rev_cache.reset(revisions.into_inner()).await?; + let _ = self.rev_persistence.reset(revisions.into_inner()).await?; self.rev_id_counter.set(rev_id); Ok(()) } @@ -79,7 +78,7 @@ impl RevisionManager { return Err(FlowyError::internal().context("Delta data should be empty")); } - let _ = self.rev_cache.add_ack_revision(revision).await?; + let _ = self.rev_persistence.add_ack_revision(revision).await?; self.rev_id_counter.set(revision.rev_id); Ok(()) } @@ -92,14 +91,14 @@ impl RevisionManager { if revision.delta_data.is_empty() { return Err(FlowyError::internal().context("Delta data should be empty")); } - let rev_id = self.rev_cache.add_sync_revision::(revision).await?; + let rev_id = self.rev_persistence.add_sync_revision::(revision).await?; self.rev_id_counter.set(rev_id); Ok(()) } #[tracing::instrument(level = "debug", skip(self), err)] pub async fn ack_revision(&self, rev_id: i64) -> Result<(), FlowyError> { - if self.rev_cache.ack_revision(rev_id).await.is_ok() { + if self.rev_persistence.ack_revision(rev_id).await.is_ok() { #[cfg(feature = "flowy_unit_test")] let _ = self.rev_ack_notifier.send(rev_id); } @@ -117,23 +116,39 @@ impl RevisionManager { } pub async fn get_revisions_in_range(&self, range: RevisionRange) -> Result, FlowyError> { - let revisions = self.rev_cache.revisions_in_range(&range).await?; + let revisions = self.rev_persistence.revisions_in_range(&range).await?; Ok(revisions) } pub async fn next_sync_revision(&self) -> FlowyResult> { - Ok(self.rev_cache.next_sync_revision().await?) + Ok(self.rev_persistence.next_sync_revision().await?) } pub async fn get_revision(&self, rev_id: i64) -> Option { - self.rev_cache.get(rev_id).await.map(|record| record.revision) + self.rev_persistence.get(rev_id).await.map(|record| record.revision) + } +} + +impl WSDataProviderDataSource for Arc { + fn next_revision(&self) -> FutureResult, FlowyError> { + let rev_manager = self.clone(); + FutureResult::new(async move { rev_manager.next_sync_revision().await }) + } + + fn ack_revision(&self, rev_id: i64) -> FutureResult<(), FlowyError> { + let rev_manager = self.clone(); + FutureResult::new(async move { (*rev_manager).ack_revision(rev_id).await }) + } + + fn current_rev_id(&self) -> i64 { + self.rev_id() } } #[cfg(feature = "flowy_unit_test")] impl RevisionManager { - pub async fn revision_cache(&self) -> Arc { - self.rev_cache.clone() + pub async fn revision_cache(&self) -> Arc { + self.rev_persistence.clone() } pub fn ack_notify(&self) -> tokio::sync::broadcast::Receiver { self.rev_ack_notifier.subscribe() @@ -144,7 +159,7 @@ struct RevisionLoader { object_id: String, user_id: String, cloud: Arc, - rev_cache: Arc, + rev_cache: Arc, } impl RevisionLoader { diff --git a/frontend/rust-lib/flowy-sync/src/ws_manager.rs b/frontend/rust-lib/flowy-sync/src/ws_manager.rs index 0cd26b9f1d..a151a58038 100644 --- a/frontend/rust-lib/flowy-sync/src/ws_manager.rs +++ b/frontend/rust-lib/flowy-sync/src/ws_manager.rs @@ -1,5 +1,6 @@ -use crate::{ResolverRevisionSink, RevisionManager}; +use crate::ConflictRevisionSink; use async_stream::stream; + use bytes::Bytes; use flowy_collaboration::entities::{ revision::{RevId, Revision, RevisionRange}, @@ -20,7 +21,7 @@ use tokio::{ }; // The consumer consumes the messages pushed by the web socket. -pub trait RevisionWSSteamConsumer: Send + Sync { +pub trait RevisionWSDataStream: Send + Sync { fn receive_push_revision(&self, bytes: Bytes) -> BoxResultFuture<(), FlowyError>; fn receive_ack(&self, id: String, ty: ServerRevisionWSDataType) -> BoxResultFuture<(), FlowyError>; fn receive_new_user_connect(&self, new_user: NewDocumentUser) -> BoxResultFuture<(), FlowyError>; @@ -29,7 +30,7 @@ pub trait RevisionWSSteamConsumer: Send + Sync { // The sink provides the data that will be sent through the web socket to the // backend. -pub trait RevisionWSSinkDataProvider: Send + Sync { +pub trait RevisionWSDataIterator: Send + Sync { fn next(&self) -> FutureResult, FlowyError>; } @@ -42,8 +43,8 @@ pub trait RevisionWebSocket: Send + Sync + 'static { pub struct RevisionWebSocketManager { pub object_name: String, pub object_id: String, - sink_provider: Arc, - stream_consumer: Arc, + ws_data_sink: Arc, + ws_data_stream: Arc, rev_web_socket: Arc, pub ws_passthrough_tx: Sender, ws_passthrough_rx: Option>, @@ -61,8 +62,8 @@ impl RevisionWebSocketManager { object_name: &str, object_id: &str, rev_web_socket: Arc, - sink_provider: Arc, - stream_consumer: Arc, + ws_data_sink: Arc, + ws_data_stream: Arc, ping_duration: Duration, ) -> Self { let (ws_passthrough_tx, ws_passthrough_rx) = mpsc::channel(1000); @@ -73,8 +74,8 @@ impl RevisionWebSocketManager { let mut manager = RevisionWebSocketManager { object_id, object_name, - sink_provider, - stream_consumer, + ws_data_sink, + ws_data_stream, rev_web_socket, ws_passthrough_tx, ws_passthrough_rx: Some(ws_passthrough_rx), @@ -86,11 +87,11 @@ impl RevisionWebSocketManager { } fn run(&mut self, ping_duration: Duration) { - let ws_msg_rx = self.ws_passthrough_rx.take().expect("Only take once"); + let ws_passthrough_rx = self.ws_passthrough_rx.take().expect("Only take once"); let sink = RevisionWSSink::new( &self.object_id, &self.object_name, - self.sink_provider.clone(), + self.ws_data_sink.clone(), self.rev_web_socket.clone(), self.stop_sync_tx.subscribe(), ping_duration, @@ -98,8 +99,8 @@ impl RevisionWebSocketManager { let stream = RevisionWSStream::new( &self.object_name, &self.object_id, - self.stream_consumer.clone(), - ws_msg_rx, + self.ws_data_stream.clone(), + ws_passthrough_rx, self.stop_sync_tx.subscribe(), ); tokio::spawn(sink.run()); @@ -115,6 +116,22 @@ impl RevisionWebSocketManager { tracing::trace!("{} stop sync", self.object_id) } } + + #[tracing::instrument(level = "debug", skip(self, data), err)] + pub async fn receive_ws_data(&self, data: ServerRevisionWSData) -> Result<(), FlowyError> { + let _ = self.ws_passthrough_tx.send(data).await.map_err(|e| { + let err_msg = format!("{} passthrough error: {}", self.object_id, e); + FlowyError::internal().context(err_msg) + })?; + Ok(()) + } + + pub fn connect_state_changed(&self, state: WSConnectState) { + match self.state_passthrough_tx.send(state) { + Ok(_) => {} + Err(e) => tracing::error!("{}", e), + } + } } impl std::ops::Drop for RevisionWebSocketManager { @@ -126,7 +143,7 @@ impl std::ops::Drop for RevisionWebSocketManager { pub struct RevisionWSStream { object_name: String, object_id: String, - consumer: Arc, + consumer: Arc, ws_msg_rx: Option>, stop_rx: Option, } @@ -147,7 +164,7 @@ impl RevisionWSStream { pub fn new( object_name: &str, object_id: &str, - consumer: Arc, + consumer: Arc, ws_msg_rx: mpsc::Receiver, stop_rx: SinkStopRx, ) -> Self { @@ -229,8 +246,8 @@ type SinkStopTx = broadcast::Sender<()>; pub struct RevisionWSSink { object_id: String, object_name: String, - provider: Arc, - ws_sender: Arc, + provider: Arc, + rev_web_socket: Arc, stop_rx: Option, ping_duration: Duration, } @@ -239,8 +256,8 @@ impl RevisionWSSink { pub fn new( object_id: &str, object_name: &str, - provider: Arc, - ws_sender: Arc, + provider: Arc, + rev_web_socket: Arc, stop_rx: SinkStopRx, ping_duration: Duration, ) -> Self { @@ -248,7 +265,7 @@ impl RevisionWSSink { object_id: object_id.to_owned(), object_name: object_name.to_owned(), provider, - ws_sender, + rev_web_socket, stop_rx: Some(stop_rx), ping_duration, } @@ -294,7 +311,7 @@ impl RevisionWSSink { } Some(data) => { tracing::trace!("[{}]: send {}:{}-{:?}", self, data.object_id, data.id(), data.ty); - self.ws_sender.send(data).await + self.rev_web_socket.send(data).await } } } @@ -325,49 +342,55 @@ enum Source { Revision, } -#[derive(Clone)] -pub struct CompositeWSSinkDataProvider { - object_id: String, - container: Arc>>, - rev_manager: Arc, - source: Arc>, +pub trait WSDataProviderDataSource: Send + Sync { + fn next_revision(&self) -> FutureResult, FlowyError>; + fn ack_revision(&self, rev_id: i64) -> FutureResult<(), FlowyError>; + fn current_rev_id(&self) -> i64; } -impl CompositeWSSinkDataProvider { - pub fn new(object_id: &str, rev_manager: Arc) -> Self { - CompositeWSSinkDataProvider { +#[derive(Clone)] +pub struct WSDataProvider { + object_id: String, + rev_ws_data_list: Arc>>, + data_source: Arc, + current_source: Arc>, +} + +impl WSDataProvider { + pub fn new(object_id: &str, data_source: Arc) -> Self { + WSDataProvider { object_id: object_id.to_owned(), - container: Arc::new(RwLock::new(VecDeque::new())), - rev_manager, - source: Arc::new(RwLock::new(Source::Custom)), + rev_ws_data_list: Arc::new(RwLock::new(VecDeque::new())), + data_source, + current_source: Arc::new(RwLock::new(Source::Custom)), } } pub async fn push_data(&self, data: ClientRevisionWSData) { - self.container.write().await.push_back(data); + self.rev_ws_data_list.write().await.push_back(data); } pub async fn next(&self) -> FlowyResult> { - let source = self.source.read().await.clone(); + let source = self.current_source.read().await.clone(); let data = match source { - Source::Custom => match self.container.read().await.front() { + Source::Custom => match self.rev_ws_data_list.read().await.front() { None => { - *self.source.write().await = Source::Revision; + *self.current_source.write().await = Source::Revision; Ok(None) } Some(data) => Ok(Some(data.clone())), }, Source::Revision => { - if !self.container.read().await.is_empty() { - *self.source.write().await = Source::Custom; + if !self.rev_ws_data_list.read().await.is_empty() { + *self.current_source.write().await = Source::Custom; return Ok(None); } - match self.rev_manager.next_sync_revision().await? { + match self.data_source.next_revision().await? { Some(rev) => Ok(Some(ClientRevisionWSData::from_revisions(&self.object_id, vec![rev]))), None => Ok(Some(ClientRevisionWSData::ping( &self.object_id, - self.rev_manager.rev_id(), + self.data_source.current_rev_id(), ))), } } @@ -376,10 +399,10 @@ impl CompositeWSSinkDataProvider { } pub async fn ack_data(&self, id: String, _ty: ServerRevisionWSDataType) -> FlowyResult<()> { - let source = self.source.read().await.clone(); + let source = self.current_source.read().await.clone(); match source { Source::Custom => { - let should_pop = match self.container.read().await.front() { + let should_pop = match self.rev_ws_data_list.read().await.front() { None => false, Some(val) => { let expected_id = val.id(); @@ -392,7 +415,7 @@ impl CompositeWSSinkDataProvider { } }; if should_pop { - let _ = self.container.write().await.pop_front(); + let _ = self.rev_ws_data_list.write().await.pop_front(); } Ok(()) } @@ -400,14 +423,14 @@ impl CompositeWSSinkDataProvider { let rev_id = id.parse::().map_err(|e| { FlowyError::internal().context(format!("Parse {} rev_id from {} failed. {}", self.object_id, id, e)) })?; - let _ = self.rev_manager.ack_revision(rev_id).await?; + let _ = self.data_source.ack_revision(rev_id).await?; Ok::<(), FlowyError>(()) } } } } -impl ResolverRevisionSink for Arc { +impl ConflictRevisionSink for Arc { fn send(&self, revisions: Vec) -> BoxResultFuture<(), FlowyError> { let sink = self.clone(); Box::pin(async move { diff --git a/frontend/rust-lib/flowy-user/src/handlers/auth_handler.rs b/frontend/rust-lib/flowy-user/src/handlers/auth_handler.rs index 171215f6f1..0285b2a442 100644 --- a/frontend/rust-lib/flowy-user/src/handlers/auth_handler.rs +++ b/frontend/rust-lib/flowy-user/src/handlers/auth_handler.rs @@ -8,7 +8,7 @@ use std::{convert::TryInto, sync::Arc}; #[tracing::instrument(name = "sign_in", skip(data, session), fields(email = %data.email), err)] pub async fn sign_in( data: Data, - session: Unit>, + session: AppData>, ) -> DataResult { let params: SignInParams = data.into_inner().try_into()?; let user_profile = session.sign_in(params).await?; @@ -26,7 +26,7 @@ pub async fn sign_in( )] pub async fn sign_up( data: Data, - session: Unit>, + session: AppData>, ) -> DataResult { let params: SignUpParams = data.into_inner().try_into()?; let user_profile = session.sign_up(params).await?; diff --git a/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs b/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs index e3f32b1d39..1692faa9ac 100644 --- a/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs +++ b/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs @@ -7,25 +7,25 @@ use lib_dispatch::prelude::*; use std::{convert::TryInto, sync::Arc}; #[tracing::instrument(skip(session))] -pub async fn init_user_handler(session: Unit>) -> Result<(), FlowyError> { +pub async fn init_user_handler(session: AppData>) -> Result<(), FlowyError> { let _ = session.init_user().await?; Ok(()) } #[tracing::instrument(skip(session))] -pub async fn check_user_handler(session: Unit>) -> DataResult { +pub async fn check_user_handler(session: AppData>) -> DataResult { let user_profile = session.check_user().await?; data_result(user_profile) } #[tracing::instrument(skip(session))] -pub async fn get_user_profile_handler(session: Unit>) -> DataResult { +pub async fn get_user_profile_handler(session: AppData>) -> DataResult { let user_profile = session.user_profile().await?; data_result(user_profile) } #[tracing::instrument(name = "sign_out", skip(session))] -pub async fn sign_out(session: Unit>) -> Result<(), FlowyError> { +pub async fn sign_out(session: AppData>) -> Result<(), FlowyError> { let _ = session.sign_out().await?; Ok(()) } @@ -33,7 +33,7 @@ pub async fn sign_out(session: Unit>) -> Result<(), FlowyError> #[tracing::instrument(name = "update_user", skip(data, session))] pub async fn update_user_handler( data: Data, - session: Unit>, + session: AppData>, ) -> Result<(), FlowyError> { let params: UpdateUserParams = data.into_inner().try_into()?; session.update_user(params).await?; diff --git a/frontend/rust-lib/lib-dispatch/src/module/data.rs b/frontend/rust-lib/lib-dispatch/src/module/data.rs index 44acd305a7..59e9b91086 100644 --- a/frontend/rust-lib/lib-dispatch/src/module/data.rs +++ b/frontend/rust-lib/lib-dispatch/src/module/data.rs @@ -5,14 +5,14 @@ use crate::{ }; use std::{any::type_name, ops::Deref, sync::Arc}; -pub struct Unit(Arc); +pub struct AppData(Arc); -impl Unit +impl AppData where T: Send + Sync, { pub fn new(data: T) -> Self { - Unit(Arc::new(data)) + AppData(Arc::new(data)) } pub fn get_ref(&self) -> &T { @@ -20,7 +20,7 @@ where } } -impl Deref for Unit +impl Deref for AppData where T: ?Sized + Send + Sync, { @@ -31,25 +31,25 @@ where } } -impl Clone for Unit +impl Clone for AppData where T: ?Sized + Send + Sync, { - fn clone(&self) -> Unit { - Unit(self.0.clone()) + fn clone(&self) -> AppData { + AppData(self.0.clone()) } } -impl From> for Unit +impl From> for AppData where T: ?Sized + Send + Sync, { fn from(arc: Arc) -> Self { - Unit(arc) + AppData(arc) } } -impl FromRequest for Unit +impl FromRequest for AppData where T: ?Sized + Send + Sync + 'static, { @@ -58,7 +58,7 @@ where #[inline] fn from_request(req: &EventRequest, _: &mut Payload) -> Self::Future { - if let Some(data) = req.module_data::>() { + if let Some(data) = req.module_data::>() { ready(Ok(data.clone())) } else { let msg = format!("Failed to get the module data of type: {}", type_name::()); diff --git a/frontend/rust-lib/lib-dispatch/src/module/module.rs b/frontend/rust-lib/lib-dispatch/src/module/module.rs index bc3ba28dbc..22369197a0 100644 --- a/frontend/rust-lib/lib-dispatch/src/module/module.rs +++ b/frontend/rust-lib/lib-dispatch/src/module/module.rs @@ -13,7 +13,7 @@ use pin_project::pin_project; use crate::{ errors::{DispatchError, InternalError}, - module::{container::ModuleDataMap, Unit}, + module::{container::ModuleDataMap, AppData}, request::{payload::Payload, EventRequest, FromRequest}, response::{EventResponse, Responder}, service::{ @@ -75,7 +75,7 @@ impl Module { } pub fn data(mut self, data: D) -> Self { - Arc::get_mut(&mut self.module_data).unwrap().insert(Unit::new(data)); + Arc::get_mut(&mut self.module_data).unwrap().insert(AppData::new(data)); self } diff --git a/shared-lib/flowy-collaboration/src/entities/document_info.rs b/shared-lib/flowy-collaboration/src/entities/document_info.rs index 25e0983c52..5449dcd07a 100644 --- a/shared-lib/flowy-collaboration/src/entities/document_info.rs +++ b/shared-lib/flowy-collaboration/src/entities/document_info.rs @@ -6,7 +6,7 @@ use flowy_derive::ProtoBuf; use lib_ot::{errors::OTError, rich_text::RichTextDelta}; #[derive(ProtoBuf, Default, Debug, Clone)] -pub struct CreateDocParams { +pub struct CreateBlockParams { #[pb(index = 1)] pub id: String, @@ -15,7 +15,7 @@ pub struct CreateDocParams { } #[derive(ProtoBuf, Default, Debug, Clone, Eq, PartialEq)] -pub struct DocumentInfo { +pub struct BlockInfo { #[pb(index = 1)] pub doc_id: String, @@ -29,14 +29,14 @@ pub struct DocumentInfo { pub base_rev_id: i64, } -impl DocumentInfo { +impl BlockInfo { pub fn delta(&self) -> Result { let delta = RichTextDelta::from_bytes(&self.text)?; Ok(delta) } } -impl std::convert::TryFrom for DocumentInfo { +impl std::convert::TryFrom for BlockInfo { type Error = CollaborateError; fn try_from(revision: Revision) -> Result { @@ -48,7 +48,7 @@ impl std::convert::TryFrom for DocumentInfo { let delta = RichTextDelta::from_bytes(&revision.delta_data)?; let doc_json = delta.to_json(); - Ok(DocumentInfo { + Ok(BlockInfo { doc_id: revision.object_id, text: doc_json, rev_id: revision.rev_id, @@ -67,9 +67,9 @@ pub struct ResetDocumentParams { } #[derive(ProtoBuf, Default, Debug, Clone)] -pub struct DocumentDelta { +pub struct BlockDelta { #[pb(index = 1)] - pub doc_id: String, + pub block_id: String, #[pb(index = 2)] pub delta_json: String, @@ -88,20 +88,20 @@ pub struct NewDocUser { } #[derive(ProtoBuf, Default, Debug, Clone)] -pub struct DocumentId { +pub struct BlockId { #[pb(index = 1)] pub value: String, } -impl std::convert::From for DocumentId { - fn from(doc_id: String) -> Self { - DocumentId { value: doc_id } +impl std::convert::From for BlockId { + fn from(value: String) -> Self { + BlockId { value } } } -impl std::convert::From<&String> for DocumentId { +impl std::convert::From<&String> for BlockId { fn from(doc_id: &String) -> Self { - DocumentId { + BlockId { value: doc_id.to_owned(), } } diff --git a/shared-lib/flowy-collaboration/src/protobuf/model/document_info.rs b/shared-lib/flowy-collaboration/src/protobuf/model/document_info.rs index 1843f709d8..52b64df159 100644 --- a/shared-lib/flowy-collaboration/src/protobuf/model/document_info.rs +++ b/shared-lib/flowy-collaboration/src/protobuf/model/document_info.rs @@ -24,7 +24,7 @@ // const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2; #[derive(PartialEq,Clone,Default)] -pub struct CreateDocParams { +pub struct CreateBlockParams { // message fields pub id: ::std::string::String, pub revisions: ::protobuf::SingularPtrField, @@ -33,14 +33,14 @@ pub struct CreateDocParams { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a CreateDocParams { - fn default() -> &'a CreateDocParams { - ::default_instance() +impl<'a> ::std::default::Default for &'a CreateBlockParams { + fn default() -> &'a CreateBlockParams { + ::default_instance() } } -impl CreateDocParams { - pub fn new() -> CreateDocParams { +impl CreateBlockParams { + pub fn new() -> CreateBlockParams { ::std::default::Default::default() } @@ -104,7 +104,7 @@ impl CreateDocParams { } } -impl ::protobuf::Message for CreateDocParams { +impl ::protobuf::Message for CreateBlockParams { fn is_initialized(&self) -> bool { for v in &self.revisions { if !v.is_initialized() { @@ -187,8 +187,8 @@ impl ::protobuf::Message for CreateDocParams { Self::descriptor_static() } - fn new() -> CreateDocParams { - CreateDocParams::new() + fn new() -> CreateBlockParams { + CreateBlockParams::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -197,29 +197,29 @@ impl ::protobuf::Message for CreateDocParams { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "id", - |m: &CreateDocParams| { &m.id }, - |m: &mut CreateDocParams| { &mut m.id }, + |m: &CreateBlockParams| { &m.id }, + |m: &mut CreateBlockParams| { &mut m.id }, )); fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( "revisions", - |m: &CreateDocParams| { &m.revisions }, - |m: &mut CreateDocParams| { &mut m.revisions }, + |m: &CreateBlockParams| { &m.revisions }, + |m: &mut CreateBlockParams| { &mut m.revisions }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "CreateDocParams", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "CreateBlockParams", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static CreateDocParams { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(CreateDocParams::new) + fn default_instance() -> &'static CreateBlockParams { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(CreateBlockParams::new) } } -impl ::protobuf::Clear for CreateDocParams { +impl ::protobuf::Clear for CreateBlockParams { fn clear(&mut self) { self.id.clear(); self.revisions.clear(); @@ -227,20 +227,20 @@ impl ::protobuf::Clear for CreateDocParams { } } -impl ::std::fmt::Debug for CreateDocParams { +impl ::std::fmt::Debug for CreateBlockParams { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for CreateDocParams { +impl ::protobuf::reflect::ProtobufValue for CreateBlockParams { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } } #[derive(PartialEq,Clone,Default)] -pub struct DocumentInfo { +pub struct BlockInfo { // message fields pub doc_id: ::std::string::String, pub text: ::std::string::String, @@ -251,14 +251,14 @@ pub struct DocumentInfo { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a DocumentInfo { - fn default() -> &'a DocumentInfo { - ::default_instance() +impl<'a> ::std::default::Default for &'a BlockInfo { + fn default() -> &'a BlockInfo { + ::default_instance() } } -impl DocumentInfo { - pub fn new() -> DocumentInfo { +impl BlockInfo { + pub fn new() -> BlockInfo { ::std::default::Default::default() } @@ -345,7 +345,7 @@ impl DocumentInfo { } } -impl ::protobuf::Message for DocumentInfo { +impl ::protobuf::Message for BlockInfo { fn is_initialized(&self) -> bool { true } @@ -446,8 +446,8 @@ impl ::protobuf::Message for DocumentInfo { Self::descriptor_static() } - fn new() -> DocumentInfo { - DocumentInfo::new() + fn new() -> BlockInfo { + BlockInfo::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -456,39 +456,39 @@ impl ::protobuf::Message for DocumentInfo { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "doc_id", - |m: &DocumentInfo| { &m.doc_id }, - |m: &mut DocumentInfo| { &mut m.doc_id }, + |m: &BlockInfo| { &m.doc_id }, + |m: &mut BlockInfo| { &mut m.doc_id }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "text", - |m: &DocumentInfo| { &m.text }, - |m: &mut DocumentInfo| { &mut m.text }, + |m: &BlockInfo| { &m.text }, + |m: &mut BlockInfo| { &mut m.text }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt64>( "rev_id", - |m: &DocumentInfo| { &m.rev_id }, - |m: &mut DocumentInfo| { &mut m.rev_id }, + |m: &BlockInfo| { &m.rev_id }, + |m: &mut BlockInfo| { &mut m.rev_id }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt64>( "base_rev_id", - |m: &DocumentInfo| { &m.base_rev_id }, - |m: &mut DocumentInfo| { &mut m.base_rev_id }, + |m: &BlockInfo| { &m.base_rev_id }, + |m: &mut BlockInfo| { &mut m.base_rev_id }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "DocumentInfo", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "BlockInfo", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static DocumentInfo { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(DocumentInfo::new) + fn default_instance() -> &'static BlockInfo { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(BlockInfo::new) } } -impl ::protobuf::Clear for DocumentInfo { +impl ::protobuf::Clear for BlockInfo { fn clear(&mut self) { self.doc_id.clear(); self.text.clear(); @@ -498,13 +498,13 @@ impl ::protobuf::Clear for DocumentInfo { } } -impl ::std::fmt::Debug for DocumentInfo { +impl ::std::fmt::Debug for BlockInfo { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for DocumentInfo { +impl ::protobuf::reflect::ProtobufValue for BlockInfo { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -727,50 +727,50 @@ impl ::protobuf::reflect::ProtobufValue for ResetDocumentParams { } #[derive(PartialEq,Clone,Default)] -pub struct DocumentDelta { +pub struct BlockDelta { // message fields - pub doc_id: ::std::string::String, + pub block_id: ::std::string::String, pub delta_json: ::std::string::String, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a DocumentDelta { - fn default() -> &'a DocumentDelta { - ::default_instance() +impl<'a> ::std::default::Default for &'a BlockDelta { + fn default() -> &'a BlockDelta { + ::default_instance() } } -impl DocumentDelta { - pub fn new() -> DocumentDelta { +impl BlockDelta { + pub fn new() -> BlockDelta { ::std::default::Default::default() } - // string doc_id = 1; + // string block_id = 1; - pub fn get_doc_id(&self) -> &str { - &self.doc_id + pub fn get_block_id(&self) -> &str { + &self.block_id } - pub fn clear_doc_id(&mut self) { - self.doc_id.clear(); + pub fn clear_block_id(&mut self) { + self.block_id.clear(); } // Param is passed by value, moved - pub fn set_doc_id(&mut self, v: ::std::string::String) { - self.doc_id = v; + pub fn set_block_id(&mut self, v: ::std::string::String) { + self.block_id = v; } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_doc_id(&mut self) -> &mut ::std::string::String { - &mut self.doc_id + pub fn mut_block_id(&mut self) -> &mut ::std::string::String { + &mut self.block_id } // Take field - pub fn take_doc_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.doc_id, ::std::string::String::new()) + pub fn take_block_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.block_id, ::std::string::String::new()) } // string delta_json = 2; @@ -800,7 +800,7 @@ impl DocumentDelta { } } -impl ::protobuf::Message for DocumentDelta { +impl ::protobuf::Message for BlockDelta { fn is_initialized(&self) -> bool { true } @@ -810,7 +810,7 @@ impl ::protobuf::Message for DocumentDelta { let (field_number, wire_type) = is.read_tag_unpack()?; match field_number { 1 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.doc_id)?; + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.block_id)?; }, 2 => { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.delta_json)?; @@ -827,8 +827,8 @@ impl ::protobuf::Message for DocumentDelta { #[allow(unused_variables)] fn compute_size(&self) -> u32 { let mut my_size = 0; - if !self.doc_id.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.doc_id); + if !self.block_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.block_id); } if !self.delta_json.is_empty() { my_size += ::protobuf::rt::string_size(2, &self.delta_json); @@ -839,8 +839,8 @@ impl ::protobuf::Message for DocumentDelta { } fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { - if !self.doc_id.is_empty() { - os.write_string(1, &self.doc_id)?; + if !self.block_id.is_empty() { + os.write_string(1, &self.block_id)?; } if !self.delta_json.is_empty() { os.write_string(2, &self.delta_json)?; @@ -875,8 +875,8 @@ impl ::protobuf::Message for DocumentDelta { Self::descriptor_static() } - fn new() -> DocumentDelta { - DocumentDelta::new() + fn new() -> BlockDelta { + BlockDelta::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -884,44 +884,44 @@ impl ::protobuf::Message for DocumentDelta { descriptor.get(|| { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "doc_id", - |m: &DocumentDelta| { &m.doc_id }, - |m: &mut DocumentDelta| { &mut m.doc_id }, + "block_id", + |m: &BlockDelta| { &m.block_id }, + |m: &mut BlockDelta| { &mut m.block_id }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "delta_json", - |m: &DocumentDelta| { &m.delta_json }, - |m: &mut DocumentDelta| { &mut m.delta_json }, + |m: &BlockDelta| { &m.delta_json }, + |m: &mut BlockDelta| { &mut m.delta_json }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "DocumentDelta", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "BlockDelta", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static DocumentDelta { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(DocumentDelta::new) + fn default_instance() -> &'static BlockDelta { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(BlockDelta::new) } } -impl ::protobuf::Clear for DocumentDelta { +impl ::protobuf::Clear for BlockDelta { fn clear(&mut self) { - self.doc_id.clear(); + self.block_id.clear(); self.delta_json.clear(); self.unknown_fields.clear(); } } -impl ::std::fmt::Debug for DocumentDelta { +impl ::std::fmt::Debug for BlockDelta { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for DocumentDelta { +impl ::protobuf::reflect::ProtobufValue for BlockDelta { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -1164,7 +1164,7 @@ impl ::protobuf::reflect::ProtobufValue for NewDocUser { } #[derive(PartialEq,Clone,Default)] -pub struct DocumentId { +pub struct BlockId { // message fields pub value: ::std::string::String, // special fields @@ -1172,14 +1172,14 @@ pub struct DocumentId { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a DocumentId { - fn default() -> &'a DocumentId { - ::default_instance() +impl<'a> ::std::default::Default for &'a BlockId { + fn default() -> &'a BlockId { + ::default_instance() } } -impl DocumentId { - pub fn new() -> DocumentId { +impl BlockId { + pub fn new() -> BlockId { ::std::default::Default::default() } @@ -1210,7 +1210,7 @@ impl DocumentId { } } -impl ::protobuf::Message for DocumentId { +impl ::protobuf::Message for BlockId { fn is_initialized(&self) -> bool { true } @@ -1276,8 +1276,8 @@ impl ::protobuf::Message for DocumentId { Self::descriptor_static() } - fn new() -> DocumentId { - DocumentId::new() + fn new() -> BlockId { + BlockId::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -1286,56 +1286,56 @@ impl ::protobuf::Message for DocumentId { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "value", - |m: &DocumentId| { &m.value }, - |m: &mut DocumentId| { &mut m.value }, + |m: &BlockId| { &m.value }, + |m: &mut BlockId| { &mut m.value }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "DocumentId", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "BlockId", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static DocumentId { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(DocumentId::new) + fn default_instance() -> &'static BlockId { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(BlockId::new) } } -impl ::protobuf::Clear for DocumentId { +impl ::protobuf::Clear for BlockId { fn clear(&mut self) { self.value.clear(); self.unknown_fields.clear(); } } -impl ::std::fmt::Debug for DocumentId { +impl ::std::fmt::Debug for BlockId { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for DocumentId { +impl ::protobuf::reflect::ProtobufValue for BlockId { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x13document_info.proto\x1a\x0erevision.proto\"R\n\x0fCreateDocParams\ - \x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12/\n\trevisions\x18\x02\x20\ - \x01(\x0b2\x11.RepeatedRevisionR\trevisions\"p\n\x0cDocumentInfo\x12\x15\ + \n\x13document_info.proto\x1a\x0erevision.proto\"T\n\x11CreateBlockParam\ + s\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12/\n\trevisions\x18\x02\ + \x20\x01(\x0b2\x11.RepeatedRevisionR\trevisions\"m\n\tBlockInfo\x12\x15\ \n\x06doc_id\x18\x01\x20\x01(\tR\x05docId\x12\x12\n\x04text\x18\x02\x20\ \x01(\tR\x04text\x12\x15\n\x06rev_id\x18\x03\x20\x01(\x03R\x05revId\x12\ \x1e\n\x0bbase_rev_id\x18\x04\x20\x01(\x03R\tbaseRevId\"]\n\x13ResetDocu\ mentParams\x12\x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05docId\x12/\n\trevi\ - sions\x18\x02\x20\x01(\x0b2\x11.RepeatedRevisionR\trevisions\"E\n\rDocum\ - entDelta\x12\x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05docId\x12\x1d\n\ndel\ - ta_json\x18\x02\x20\x01(\tR\tdeltaJson\"S\n\nNewDocUser\x12\x17\n\x07use\ - r_id\x18\x01\x20\x01(\tR\x06userId\x12\x15\n\x06rev_id\x18\x02\x20\x01(\ - \x03R\x05revId\x12\x15\n\x06doc_id\x18\x03\x20\x01(\tR\x05docId\"\"\n\nD\ - ocumentId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05valueb\x06proto3\ + sions\x18\x02\x20\x01(\x0b2\x11.RepeatedRevisionR\trevisions\"F\n\nBlock\ + Delta\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12\x1d\n\nde\ + lta_json\x18\x02\x20\x01(\tR\tdeltaJson\"S\n\nNewDocUser\x12\x17\n\x07us\ + er_id\x18\x01\x20\x01(\tR\x06userId\x12\x15\n\x06rev_id\x18\x02\x20\x01(\ + \x03R\x05revId\x12\x15\n\x06doc_id\x18\x03\x20\x01(\tR\x05docId\"\x1f\n\ + \x07BlockId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05valueb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-collaboration/src/protobuf/proto/document_info.proto b/shared-lib/flowy-collaboration/src/protobuf/proto/document_info.proto index a56c597152..4e234478f2 100644 --- a/shared-lib/flowy-collaboration/src/protobuf/proto/document_info.proto +++ b/shared-lib/flowy-collaboration/src/protobuf/proto/document_info.proto @@ -1,11 +1,11 @@ syntax = "proto3"; import "revision.proto"; -message CreateDocParams { +message CreateBlockParams { string id = 1; RepeatedRevision revisions = 2; } -message DocumentInfo { +message BlockInfo { string doc_id = 1; string text = 2; int64 rev_id = 3; @@ -15,8 +15,8 @@ message ResetDocumentParams { string doc_id = 1; RepeatedRevision revisions = 2; } -message DocumentDelta { - string doc_id = 1; +message BlockDelta { + string block_id = 1; string delta_json = 2; } message NewDocUser { @@ -24,6 +24,6 @@ message NewDocUser { int64 rev_id = 2; string doc_id = 3; } -message DocumentId { +message BlockId { string value = 1; } diff --git a/shared-lib/flowy-collaboration/src/server_document/document_manager.rs b/shared-lib/flowy-collaboration/src/server_document/document_manager.rs index e204d43ae4..864840e9b5 100644 --- a/shared-lib/flowy-collaboration/src/server_document/document_manager.rs +++ b/shared-lib/flowy-collaboration/src/server_document/document_manager.rs @@ -1,5 +1,5 @@ use crate::{ - entities::{document_info::DocumentInfo, ws_data::ServerRevisionWSDataBuilder}, + entities::{document_info::BlockInfo, ws_data::ServerRevisionWSDataBuilder}, errors::{internal_error, CollaborateError, CollaborateResult}, protobuf::{ClientRevisionWSData, RepeatedRevision as RepeatedRevisionPB, Revision as RevisionPB}, server_document::document_pad::ServerDocument, @@ -18,13 +18,13 @@ use tokio::{ }; pub trait DocumentCloudPersistence: Send + Sync + Debug { - fn read_document(&self, doc_id: &str) -> BoxResultFuture; + fn read_document(&self, doc_id: &str) -> BoxResultFuture; fn create_document( &self, doc_id: &str, repeated_revision: RepeatedRevisionPB, - ) -> BoxResultFuture, CollaborateError>; + ) -> BoxResultFuture, CollaborateError>; fn read_document_revisions( &self, @@ -181,7 +181,7 @@ impl ServerDocumentManager { } } - async fn create_document_handler(&self, doc: DocumentInfo) -> Result, CollaborateError> { + async fn create_document_handler(&self, doc: BlockInfo) -> Result, CollaborateError> { let persistence = self.persistence.clone(); let handle = spawn_blocking(|| OpenDocumentHandler::new(doc, persistence)) .await @@ -205,7 +205,7 @@ struct OpenDocumentHandler { } impl OpenDocumentHandler { - fn new(doc: DocumentInfo, persistence: Arc) -> Result { + fn new(doc: BlockInfo, persistence: Arc) -> Result { let doc_id = doc.doc_id.clone(); let (sender, receiver) = mpsc::channel(1000); let users = DashMap::new(); diff --git a/shared-lib/flowy-collaboration/src/util.rs b/shared-lib/flowy-collaboration/src/util.rs index 2af1a071b2..f5f45f7f53 100644 --- a/shared-lib/flowy-collaboration/src/util.rs +++ b/shared-lib/flowy-collaboration/src/util.rs @@ -1,12 +1,12 @@ use crate::{ entities::{ - document_info::DocumentInfo, + document_info::BlockInfo, folder_info::{FolderDelta, FolderInfo}, revision::{RepeatedRevision, Revision}, }, errors::{CollaborateError, CollaborateResult}, protobuf::{ - DocumentInfo as DocumentInfoPB, FolderInfo as FolderInfoPB, RepeatedRevision as RepeatedRevisionPB, + BlockInfo as BlockInfoPB, FolderInfo as FolderInfoPB, RepeatedRevision as RepeatedRevisionPB, Revision as RevisionPB, }, }; @@ -199,11 +199,11 @@ pub fn make_folder_pb_from_revisions_pb( pub fn make_document_info_from_revisions_pb( doc_id: &str, revisions: RepeatedRevisionPB, -) -> Result, CollaborateError> { +) -> Result, CollaborateError> { match make_document_info_pb_from_revisions_pb(doc_id, revisions)? { None => Ok(None), Some(pb) => { - let document_info: DocumentInfo = pb.try_into().map_err(|e| { + let document_info: BlockInfo = pb.try_into().map_err(|e| { CollaborateError::internal().context(format!("Deserialize document info from pb failed: {}", e)) })?; Ok(Some(document_info)) @@ -215,7 +215,7 @@ pub fn make_document_info_from_revisions_pb( pub fn make_document_info_pb_from_revisions_pb( doc_id: &str, mut revisions: RepeatedRevisionPB, -) -> Result, CollaborateError> { +) -> Result, CollaborateError> { let revisions = revisions.take_items(); if revisions.is_empty() { return Ok(None); @@ -237,12 +237,12 @@ pub fn make_document_info_pb_from_revisions_pb( } let text = document_delta.to_json(); - let mut document_info = DocumentInfoPB::new(); - document_info.set_doc_id(doc_id.to_owned()); - document_info.set_text(text); - document_info.set_base_rev_id(base_rev_id); - document_info.set_rev_id(rev_id); - Ok(Some(document_info)) + let mut block_info = BlockInfoPB::new(); + block_info.set_doc_id(doc_id.to_owned()); + block_info.set_text(text); + block_info.set_base_rev_id(base_rev_id); + block_info.set_rev_id(rev_id); + Ok(Some(block_info)) } #[inline] diff --git a/shared-lib/flowy-folder-data-model/src/entities/share.rs b/shared-lib/flowy-folder-data-model/src/entities/share.rs index dfd5f95910..61dade5113 100644 --- a/shared-lib/flowy-folder-data-model/src/entities/share.rs +++ b/shared-lib/flowy-folder-data-model/src/entities/share.rs @@ -32,7 +32,7 @@ impl std::convert::From for ExportType { #[derive(Default, ProtoBuf)] pub struct ExportPayload { #[pb(index = 1)] - pub doc_id: String, + pub view_id: String, #[pb(index = 2)] pub export_type: ExportType, @@ -40,7 +40,7 @@ pub struct ExportPayload { #[derive(Default, Debug)] pub struct ExportParams { - pub doc_id: String, + pub view_id: String, pub export_type: ExportType, } @@ -48,7 +48,7 @@ impl TryInto for ExportPayload { type Error = ErrorCode; fn try_into(self) -> Result { Ok(ExportParams { - doc_id: self.doc_id, + view_id: self.view_id, export_type: self.export_type, }) } diff --git a/shared-lib/flowy-folder-data-model/src/protobuf/model/share.rs b/shared-lib/flowy-folder-data-model/src/protobuf/model/share.rs index e500c411e0..a020837fb0 100644 --- a/shared-lib/flowy-folder-data-model/src/protobuf/model/share.rs +++ b/shared-lib/flowy-folder-data-model/src/protobuf/model/share.rs @@ -26,7 +26,7 @@ #[derive(PartialEq,Clone,Default)] pub struct ExportPayload { // message fields - pub doc_id: ::std::string::String, + pub view_id: ::std::string::String, pub export_type: ExportType, // special fields pub unknown_fields: ::protobuf::UnknownFields, @@ -44,30 +44,30 @@ impl ExportPayload { ::std::default::Default::default() } - // string doc_id = 1; + // string view_id = 1; - pub fn get_doc_id(&self) -> &str { - &self.doc_id + pub fn get_view_id(&self) -> &str { + &self.view_id } - pub fn clear_doc_id(&mut self) { - self.doc_id.clear(); + pub fn clear_view_id(&mut self) { + self.view_id.clear(); } // Param is passed by value, moved - pub fn set_doc_id(&mut self, v: ::std::string::String) { - self.doc_id = v; + pub fn set_view_id(&mut self, v: ::std::string::String) { + self.view_id = v; } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_doc_id(&mut self) -> &mut ::std::string::String { - &mut self.doc_id + pub fn mut_view_id(&mut self) -> &mut ::std::string::String { + &mut self.view_id } // Take field - pub fn take_doc_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.doc_id, ::std::string::String::new()) + pub fn take_view_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.view_id, ::std::string::String::new()) } // .ExportType export_type = 2; @@ -96,7 +96,7 @@ impl ::protobuf::Message for ExportPayload { let (field_number, wire_type) = is.read_tag_unpack()?; match field_number { 1 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.doc_id)?; + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.view_id)?; }, 2 => { ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.export_type, 2, &mut self.unknown_fields)? @@ -113,8 +113,8 @@ impl ::protobuf::Message for ExportPayload { #[allow(unused_variables)] fn compute_size(&self) -> u32 { let mut my_size = 0; - if !self.doc_id.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.doc_id); + if !self.view_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.view_id); } if self.export_type != ExportType::Text { my_size += ::protobuf::rt::enum_size(2, self.export_type); @@ -125,8 +125,8 @@ impl ::protobuf::Message for ExportPayload { } fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { - if !self.doc_id.is_empty() { - os.write_string(1, &self.doc_id)?; + if !self.view_id.is_empty() { + os.write_string(1, &self.view_id)?; } if self.export_type != ExportType::Text { os.write_enum(2, ::protobuf::ProtobufEnum::value(&self.export_type))?; @@ -170,9 +170,9 @@ impl ::protobuf::Message for ExportPayload { descriptor.get(|| { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "doc_id", - |m: &ExportPayload| { &m.doc_id }, - |m: &mut ExportPayload| { &mut m.doc_id }, + "view_id", + |m: &ExportPayload| { &m.view_id }, + |m: &mut ExportPayload| { &mut m.view_id }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( "export_type", @@ -195,7 +195,7 @@ impl ::protobuf::Message for ExportPayload { impl ::protobuf::Clear for ExportPayload { fn clear(&mut self) { - self.doc_id.clear(); + self.view_id.clear(); self.export_type = ExportType::Text; self.unknown_fields.clear(); } @@ -457,11 +457,11 @@ impl ::protobuf::reflect::ProtobufValue for ExportType { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0bshare.proto\"T\n\rExportPayload\x12\x15\n\x06doc_id\x18\x01\x20\ - \x01(\tR\x05docId\x12,\n\x0bexport_type\x18\x02\x20\x01(\x0e2\x0b.Export\ - TypeR\nexportType\"N\n\nExportData\x12\x12\n\x04data\x18\x01\x20\x01(\tR\ - \x04data\x12,\n\x0bexport_type\x18\x02\x20\x01(\x0e2\x0b.ExportTypeR\nex\ - portType*.\n\nExportType\x12\x08\n\x04Text\x10\0\x12\x0c\n\x08Markdown\ + \n\x0bshare.proto\"V\n\rExportPayload\x12\x17\n\x07view_id\x18\x01\x20\ + \x01(\tR\x06viewId\x12,\n\x0bexport_type\x18\x02\x20\x01(\x0e2\x0b.Expor\ + tTypeR\nexportType\"N\n\nExportData\x12\x12\n\x04data\x18\x01\x20\x01(\t\ + R\x04data\x12,\n\x0bexport_type\x18\x02\x20\x01(\x0e2\x0b.ExportTypeR\ne\ + xportType*.\n\nExportType\x12\x08\n\x04Text\x10\0\x12\x0c\n\x08Markdown\ \x10\x01\x12\x08\n\x04Link\x10\x02b\x06proto3\ "; diff --git a/shared-lib/flowy-folder-data-model/src/protobuf/proto/share.proto b/shared-lib/flowy-folder-data-model/src/protobuf/proto/share.proto index 3f82853ac8..d58ed2a9cb 100644 --- a/shared-lib/flowy-folder-data-model/src/protobuf/proto/share.proto +++ b/shared-lib/flowy-folder-data-model/src/protobuf/proto/share.proto @@ -1,7 +1,7 @@ syntax = "proto3"; message ExportPayload { - string doc_id = 1; + string view_id = 1; ExportType export_type = 2; } message ExportData { From 01985848f90d89e0c3f354b90b9e8b55e45e3dc6 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 26 Feb 2022 11:03:42 +0800 Subject: [PATCH 02/12] refactor: rename structs --- frontend/rust-lib/dart-ffi/Cargo.toml | 4 +- .../src/{editor.rs => block_editor.rs} | 16 +++---- frontend/rust-lib/flowy-document/src/lib.rs | 2 +- .../rust-lib/flowy-document/src/manager.rs | 48 +++++++++---------- frontend/rust-lib/flowy-document/src/queue.rs | 12 ++--- .../rust-lib/flowy-document/src/web_socket.rs | 4 +- .../tests/document/edit_script.rs | 2 +- .../rust-lib/flowy-folder/src/controller.rs | 8 ++-- .../src/services/folder_editor.rs | 12 ++--- .../src/services/persistence/mod.rs | 9 ++-- .../services/persistence/version_2/v2_impl.rs | 4 +- .../flowy-folder/tests/workspace/script.rs | 4 +- .../src/deps_resolve/document_deps.rs | 6 +-- frontend/rust-lib/flowy-sync/src/cache/mod.rs | 10 ++-- 14 files changed, 72 insertions(+), 69 deletions(-) rename frontend/rust-lib/flowy-document/src/{editor.rs => block_editor.rs} (94%) diff --git a/frontend/rust-lib/dart-ffi/Cargo.toml b/frontend/rust-lib/dart-ffi/Cargo.toml index 96755db623..046fd85668 100644 --- a/frontend/rust-lib/dart-ffi/Cargo.toml +++ b/frontend/rust-lib/dart-ffi/Cargo.toml @@ -7,8 +7,8 @@ edition = "2018" [lib] name = "dart_ffi" # this value will change depending on the target os -# default staticlib -crate-type = ["staticlib"] +# default cdylib +crate-type = ["cdylib"] [dependencies] diff --git a/frontend/rust-lib/flowy-document/src/editor.rs b/frontend/rust-lib/flowy-document/src/block_editor.rs similarity index 94% rename from frontend/rust-lib/flowy-document/src/editor.rs rename to frontend/rust-lib/flowy-document/src/block_editor.rs index 36099cffa3..0f582d28c1 100644 --- a/frontend/rust-lib/flowy-document/src/editor.rs +++ b/frontend/rust-lib/flowy-document/src/block_editor.rs @@ -1,8 +1,8 @@ -use crate::queue::DocumentRevisionCompact; -use crate::web_socket::{make_document_ws_manager, EditorCommandSender}; +use crate::queue::BlockRevisionCompact; +use crate::web_socket::{make_block_ws_manager, EditorCommandSender}; use crate::{ errors::FlowyError, - queue::{EditorCommand, EditorCommandQueue}, + queue::{EditBlockQueue, EditorCommand}, BlockUser, }; use bytes::Bytes; @@ -41,7 +41,7 @@ impl ClientBlockEditor { cloud_service: Arc, ) -> FlowyResult> { let document_info = rev_manager - .load::(cloud_service) + .load::(cloud_service) .await?; let delta = document_info.delta()?; let rev_manager = Arc::new(rev_manager); @@ -49,7 +49,7 @@ impl ClientBlockEditor { let user_id = user.user_id()?; let edit_cmd_tx = spawn_edit_queue(user, rev_manager.clone(), delta); - let ws_manager = make_document_ws_manager( + let ws_manager = make_block_ws_manager( doc_id.clone(), user_id.clone(), edit_cmd_tx.clone(), @@ -176,7 +176,7 @@ impl ClientBlockEditor { impl std::ops::Drop for ClientBlockEditor { fn drop(&mut self) { - tracing::trace!("{} ClientDocumentEditor was dropped", self.doc_id) + tracing::trace!("{} ClientBlockEditor was dropped", self.doc_id) } } @@ -187,8 +187,8 @@ fn spawn_edit_queue( delta: RichTextDelta, ) -> EditorCommandSender { let (sender, receiver) = mpsc::channel(1000); - let actor = EditorCommandQueue::new(user, rev_manager, delta, receiver); - tokio::spawn(actor.run()); + let edit_queue = EditBlockQueue::new(user, rev_manager, delta, receiver); + tokio::spawn(edit_queue.run()); sender } diff --git a/frontend/rust-lib/flowy-document/src/lib.rs b/frontend/rust-lib/flowy-document/src/lib.rs index eeea94bdb1..018bd94599 100644 --- a/frontend/rust-lib/flowy-document/src/lib.rs +++ b/frontend/rust-lib/flowy-document/src/lib.rs @@ -1,4 +1,4 @@ -pub mod editor; +pub mod block_editor; pub mod manager; mod queue; mod web_socket; diff --git a/frontend/rust-lib/flowy-document/src/manager.rs b/frontend/rust-lib/flowy-document/src/manager.rs index f98cf2af02..f07558c8f4 100644 --- a/frontend/rust-lib/flowy-document/src/manager.rs +++ b/frontend/rust-lib/flowy-document/src/manager.rs @@ -1,4 +1,4 @@ -use crate::{editor::ClientBlockEditor, errors::FlowyError, BlockCloudService}; +use crate::{block_editor::ClientBlockEditor, errors::FlowyError, BlockCloudService}; use bytes::Bytes; use dashmap::DashMap; use flowy_collaboration::entities::{ @@ -22,27 +22,27 @@ pub trait BlockUser: Send + Sync { pub struct BlockManager { cloud_service: Arc, rev_web_socket: Arc, - block_handlers: Arc, - document_user: Arc, + block_editors: Arc, + block_user: Arc, } impl BlockManager { pub fn new( cloud_service: Arc, - document_user: Arc, + block_user: Arc, rev_web_socket: Arc, ) -> Self { - let block_handlers = Arc::new(BlockEditorHandlers::new()); + let block_handlers = Arc::new(BlockEditors::new()); Self { cloud_service, rev_web_socket, - block_handlers, - document_user, + block_editors: block_handlers, + block_user, } } pub fn init(&self) -> FlowyResult<()> { - listen_ws_state_changed(self.rev_web_socket.clone(), self.block_handlers.clone()); + listen_ws_state_changed(self.rev_web_socket.clone(), self.block_editors.clone()); Ok(()) } @@ -58,7 +58,7 @@ impl BlockManager { pub fn close_block>(&self, block_id: T) -> Result<(), FlowyError> { let block_id = block_id.as_ref(); tracing::Span::current().record("block_id", &block_id); - self.block_handlers.remove(block_id); + self.block_editors.remove(block_id); Ok(()) } @@ -66,7 +66,7 @@ impl BlockManager { pub fn delete>(&self, doc_id: T) -> Result<(), FlowyError> { let doc_id = doc_id.as_ref(); tracing::Span::current().record("doc_id", &doc_id); - self.block_handlers.remove(doc_id); + self.block_editors.remove(doc_id); Ok(()) } @@ -83,7 +83,7 @@ impl BlockManager { pub async fn reset_with_revisions>(&self, doc_id: T, revisions: RepeatedRevision) -> FlowyResult<()> { let doc_id = doc_id.as_ref().to_owned(); - let db_pool = self.document_user.db_pool()?; + let db_pool = self.block_user.db_pool()?; let rev_manager = self.make_rev_manager(&doc_id, db_pool)?; let _ = rev_manager.reset_object(revisions).await?; Ok(()) @@ -92,7 +92,7 @@ impl BlockManager { pub async fn receive_ws_data(&self, data: Bytes) { let result: Result = data.try_into(); match result { - Ok(data) => match self.block_handlers.get(&data.object_id) { + Ok(data) => match self.block_editors.get(&data.object_id) { None => tracing::error!("Can't find any source handler for {:?}-{:?}", data.object_id, data.ty), Some(block_editor) => match block_editor.receive_ws_data(data).await { Ok(_) => {} @@ -108,9 +108,9 @@ impl BlockManager { impl BlockManager { async fn get_block_editor(&self, block_id: &str) -> FlowyResult> { - match self.block_handlers.get(block_id) { + match self.block_editors.get(block_id) { None => { - let db_pool = self.document_user.db_pool()?; + let db_pool = self.block_user.db_pool()?; self.make_block_editor(block_id, db_pool).await } Some(editor) => Ok(editor), @@ -122,32 +122,32 @@ impl BlockManager { block_id: &str, pool: Arc, ) -> Result, FlowyError> { - let user = self.document_user.clone(); - let token = self.document_user.token()?; + let user = self.block_user.clone(); + let token = self.block_user.token()?; let rev_manager = self.make_rev_manager(block_id, pool.clone())?; - let cloud_service = Arc::new(DocumentRevisionCloudServiceImpl { + let cloud_service = Arc::new(BlockRevisionCloudService { token, server: self.cloud_service.clone(), }); let doc_editor = ClientBlockEditor::new(block_id, user, rev_manager, self.rev_web_socket.clone(), cloud_service).await?; - self.block_handlers.insert(block_id, &doc_editor); + self.block_editors.insert(block_id, &doc_editor); Ok(doc_editor) } fn make_rev_manager(&self, doc_id: &str, pool: Arc) -> Result { - let user_id = self.document_user.user_id()?; + let user_id = self.block_user.user_id()?; let rev_persistence = Arc::new(RevisionPersistence::new(&user_id, doc_id, pool)); Ok(RevisionManager::new(&user_id, doc_id, rev_persistence)) } } -struct DocumentRevisionCloudServiceImpl { +struct BlockRevisionCloudService { token: String, server: Arc, } -impl RevisionCloudService for DocumentRevisionCloudServiceImpl { +impl RevisionCloudService for BlockRevisionCloudService { #[tracing::instrument(level = "trace", skip(self))] fn fetch_object(&self, user_id: &str, object_id: &str) -> FutureResult, FlowyError> { let params: BlockId = object_id.to_string().into(); @@ -170,11 +170,11 @@ impl RevisionCloudService for DocumentRevisionCloudServiceImpl { } } -pub struct BlockEditorHandlers { +pub struct BlockEditors { inner: DashMap>, } -impl BlockEditorHandlers { +impl BlockEditors { fn new() -> Self { Self { inner: DashMap::new() } } @@ -207,7 +207,7 @@ impl BlockEditorHandlers { } #[tracing::instrument(level = "trace", skip(web_socket, handlers))] -fn listen_ws_state_changed(web_socket: Arc, handlers: Arc) { +fn listen_ws_state_changed(web_socket: Arc, handlers: Arc) { tokio::spawn(async move { let mut notify = web_socket.subscribe_state_changed().await; while let Ok(state) = notify.recv().await { diff --git a/frontend/rust-lib/flowy-document/src/queue.rs b/frontend/rust-lib/flowy-document/src/queue.rs index 3d780933de..b23e486407 100644 --- a/frontend/rust-lib/flowy-document/src/queue.rs +++ b/frontend/rust-lib/flowy-document/src/queue.rs @@ -19,14 +19,14 @@ use tokio::sync::{oneshot, RwLock}; // The EditorCommandQueue executes each command that will alter the document in // serial. -pub(crate) struct EditorCommandQueue { +pub(crate) struct EditBlockQueue { document: Arc>, user: Arc, rev_manager: Arc, receiver: Option, } -impl EditorCommandQueue { +impl EditBlockQueue { pub(crate) fn new( user: Arc, rev_manager: Arc, @@ -187,17 +187,17 @@ impl EditorCommandQueue { ); let _ = self .rev_manager - .add_local_revision::(&revision) + .add_local_revision::(&revision) .await?; Ok(rev_id.into()) } } -pub(crate) struct DocumentRevisionCompact(); -impl RevisionCompact for DocumentRevisionCompact { +pub(crate) struct BlockRevisionCompact(); +impl RevisionCompact for BlockRevisionCompact { fn compact_revisions(user_id: &str, object_id: &str, mut revisions: Vec) -> FlowyResult { if revisions.is_empty() { - return Err(FlowyError::internal().context("Can't compact the empty document's revisions")); + return Err(FlowyError::internal().context("Can't compact the empty block's revisions")); } if revisions.len() == 1 { diff --git a/frontend/rust-lib/flowy-document/src/web_socket.rs b/frontend/rust-lib/flowy-document/src/web_socket.rs index 7798d74fa1..a01e48789b 100644 --- a/frontend/rust-lib/flowy-document/src/web_socket.rs +++ b/frontend/rust-lib/flowy-document/src/web_socket.rs @@ -22,7 +22,7 @@ use tokio::sync::{ pub(crate) type EditorCommandSender = Sender; pub(crate) type EditorCommandReceiver = Receiver; -pub(crate) async fn make_document_ws_manager( +pub(crate) async fn make_block_ws_manager( doc_id: String, user_id: String, edit_cmd_tx: EditorCommandSender, @@ -41,7 +41,7 @@ pub(crate) async fn make_document_ws_manager( let ws_data_sink = Arc::new(BlockWSDataSink(ws_data_provider)); let ping_duration = Duration::from_millis(DOCUMENT_SYNC_INTERVAL_IN_MILLIS); let ws_manager = Arc::new(RevisionWebSocketManager::new( - "Document", + "Block", &doc_id, rev_web_socket, ws_data_sink, diff --git a/frontend/rust-lib/flowy-document/tests/document/edit_script.rs b/frontend/rust-lib/flowy-document/tests/document/edit_script.rs index 9961812ec8..89d0119dfc 100644 --- a/frontend/rust-lib/flowy-document/tests/document/edit_script.rs +++ b/frontend/rust-lib/flowy-document/tests/document/edit_script.rs @@ -1,5 +1,5 @@ use flowy_collaboration::entities::revision::RevisionState; -use flowy_document::editor::ClientBlockEditor; +use flowy_document::block_editor::ClientBlockEditor; use flowy_document::DOCUMENT_SYNC_INTERVAL_IN_MILLIS; use flowy_test::{helper::ViewTest, FlowySDKTest}; use lib_ot::{core::Interval, rich_text::RichTextDelta}; diff --git a/frontend/rust-lib/flowy-folder/src/controller.rs b/frontend/rust-lib/flowy-folder/src/controller.rs index 68d2edd8d8..020c9d2ee8 100644 --- a/frontend/rust-lib/flowy-folder/src/controller.rs +++ b/frontend/rust-lib/flowy-folder/src/controller.rs @@ -17,7 +17,7 @@ use crate::{ errors::FlowyResult, event_map::{FolderCouldServiceV1, WorkspaceDatabase, WorkspaceUser}, services::{ - folder_editor::FolderEditor, persistence::FolderPersistence, set_current_workspace, AppController, + folder_editor::ClientFolderEditor, persistence::FolderPersistence, set_current_workspace, AppController, TrashController, ViewController, WorkspaceController, }, }; @@ -63,7 +63,7 @@ pub struct FolderManager { pub(crate) view_controller: Arc, pub(crate) trash_controller: Arc, web_socket: Arc, - folder_editor: Arc>>>, + folder_editor: Arc>>>, } impl FolderManager { @@ -162,7 +162,7 @@ impl FolderManager { let _ = self.persistence.initialize(user_id, &folder_id).await?; let pool = self.persistence.db_pool()?; - let folder_editor = FolderEditor::new(user_id, &folder_id, token, pool, self.web_socket.clone()).await?; + let folder_editor = ClientFolderEditor::new(user_id, &folder_id, token, pool, self.web_socket.clone()).await?; *self.folder_editor.write().await = Some(Arc::new(folder_editor)); let _ = self.app_controller.initialize()?; @@ -219,7 +219,7 @@ impl DefaultFolderBuilder { #[cfg(feature = "flowy_unit_test")] impl FolderManager { - pub async fn folder_editor(&self) -> Arc { + pub async fn folder_editor(&self) -> Arc { self.folder_editor.read().await.clone().unwrap() } } diff --git a/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs b/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs index 29365e71b0..985998498f 100644 --- a/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs +++ b/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs @@ -17,7 +17,7 @@ use lib_sqlite::ConnectionPool; use parking_lot::RwLock; use std::sync::Arc; -pub struct FolderEditor { +pub struct ClientFolderEditor { user_id: String, pub(crate) folder_id: FolderId, pub(crate) folder: Arc>, @@ -25,7 +25,7 @@ pub struct FolderEditor { ws_manager: Arc, } -impl FolderEditor { +impl ClientFolderEditor { pub async fn new( user_id: &str, folder_id: &FolderId, @@ -35,7 +35,7 @@ impl FolderEditor { ) -> FlowyResult { let rev_persistence = Arc::new(RevisionPersistence::new(user_id, folder_id.as_ref(), pool)); let mut rev_manager = RevisionManager::new(user_id, folder_id.as_ref(), rev_persistence); - let cloud = Arc::new(FolderRevisionCloudServiceImpl { + let cloud = Arc::new(FolderRevisionCloudService { token: token.to_string(), }); let folder = Arc::new(RwLock::new( @@ -109,12 +109,12 @@ impl RevisionObjectBuilder for FolderPadBuilder { } } -struct FolderRevisionCloudServiceImpl { +struct FolderRevisionCloudService { #[allow(dead_code)] token: String, } -impl RevisionCloudService for FolderRevisionCloudServiceImpl { +impl RevisionCloudService for FolderRevisionCloudService { #[tracing::instrument(level = "trace", skip(self))] fn fetch_object(&self, _user_id: &str, _object_id: &str) -> FutureResult, FlowyError> { FutureResult::new(async move { Ok(vec![]) }) @@ -122,7 +122,7 @@ impl RevisionCloudService for FolderRevisionCloudServiceImpl { } #[cfg(feature = "flowy_unit_test")] -impl FolderEditor { +impl ClientFolderEditor { pub fn rev_manager(&self) -> Arc { self.rev_manager.clone() } diff --git a/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs b/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs index bd77a50d8f..f4ceec5b88 100644 --- a/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs +++ b/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs @@ -13,7 +13,7 @@ pub use version_1::{app_sql::*, trash_sql::*, v1_impl::V1Transaction, view_sql:: use crate::{ controller::FolderId, event_map::WorkspaceDatabase, - services::{folder_editor::FolderEditor, persistence::migration::FolderMigration}, + services::{folder_editor::ClientFolderEditor, persistence::migration::FolderMigration}, }; use flowy_error::{FlowyError, FlowyResult}; use flowy_folder_data_model::entities::{ @@ -50,11 +50,14 @@ pub trait FolderPersistenceTransaction { pub struct FolderPersistence { database: Arc, - folder_editor: Arc>>>, + folder_editor: Arc>>>, } impl FolderPersistence { - pub fn new(database: Arc, folder_editor: Arc>>>) -> Self { + pub fn new( + database: Arc, + folder_editor: Arc>>>, + ) -> Self { Self { database, folder_editor, diff --git a/frontend/rust-lib/flowy-folder/src/services/persistence/version_2/v2_impl.rs b/frontend/rust-lib/flowy-folder/src/services/persistence/version_2/v2_impl.rs index 88b9131fe1..80fd0bb6bb 100644 --- a/frontend/rust-lib/flowy-folder/src/services/persistence/version_2/v2_impl.rs +++ b/frontend/rust-lib/flowy-folder/src/services/persistence/version_2/v2_impl.rs @@ -1,5 +1,5 @@ use crate::services::{ - folder_editor::FolderEditor, + folder_editor::ClientFolderEditor, persistence::{AppChangeset, FolderPersistenceTransaction, ViewChangeset, WorkspaceChangeset}, }; use flowy_error::{FlowyError, FlowyResult}; @@ -11,7 +11,7 @@ use flowy_folder_data_model::entities::{ }; use std::sync::Arc; -impl FolderPersistenceTransaction for FolderEditor { +impl FolderPersistenceTransaction for ClientFolderEditor { fn create_workspace(&self, _user_id: &str, workspace: Workspace) -> FlowyResult<()> { if let Some(change) = self.folder.write().create_workspace(workspace)? { let _ = self.apply_change(change)?; diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs index eb05dd894b..8d4b258ccc 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs @@ -1,6 +1,6 @@ use crate::helper::*; use flowy_collaboration::entities::{document_info::BlockInfo, revision::RevisionState}; -use flowy_folder::{errors::ErrorCode, services::folder_editor::FolderEditor}; +use flowy_folder::{errors::ErrorCode, services::folder_editor::ClientFolderEditor}; use flowy_folder_data_model::entities::{ app::{App, RepeatedApp}, trash::Trash, @@ -95,7 +95,7 @@ impl FolderTest { pub async fn run_script(&mut self, script: FolderScript) { let sdk = &self.sdk; - let folder_editor: Arc = sdk.folder_manager.folder_editor().await; + let folder_editor: Arc = sdk.folder_manager.folder_editor().await; let rev_manager = folder_editor.rev_manager(); let cache = rev_manager.revision_cache().await; diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs index 5de869609c..1c1c8f7d4a 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs @@ -24,7 +24,7 @@ impl DocumentDepsResolver { user_session: Arc, server_config: &ClientServerConfiguration, ) -> Arc { - let user = Arc::new(DocumentUserImpl(user_session)); + let user = Arc::new(BlockUserImpl(user_session)); let ws_sender = Arc::new(BlockWebSocket(ws_conn.clone())); let cloud_service: Arc = match local_server { None => Arc::new(BlockHttpCloudService::new(server_config.clone())), @@ -39,8 +39,8 @@ impl DocumentDepsResolver { } } -struct DocumentUserImpl(Arc); -impl BlockUser for DocumentUserImpl { +struct BlockUserImpl(Arc); +impl BlockUser for BlockUserImpl { fn user_dir(&self) -> Result { let dir = self.0.user_dir().map_err(|e| FlowyError::unauthorized().context(e))?; diff --git a/frontend/rust-lib/flowy-sync/src/cache/mod.rs b/frontend/rust-lib/flowy-sync/src/cache/mod.rs index b32ec43c81..a6b5be4102 100644 --- a/frontend/rust-lib/flowy-sync/src/cache/mod.rs +++ b/frontend/rust-lib/flowy-sync/src/cache/mod.rs @@ -23,7 +23,7 @@ pub struct RevisionPersistence { object_id: String, disk_cache: Arc>, memory_cache: Arc, - sync_seq: RwLock, + sync_seq: RwLock, } impl RevisionPersistence { pub fn new(user_id: &str, object_id: &str, pool: Arc) -> RevisionPersistence { @@ -31,7 +31,7 @@ impl RevisionPersistence { let memory_cache = Arc::new(RevisionMemoryCache::new(object_id, Arc::new(disk_cache.clone()))); let object_id = object_id.to_owned(); let user_id = user_id.to_owned(); - let sync_seq = RwLock::new(SyncSequence::new()); + let sync_seq = RwLock::new(RevisionSyncSequence::new()); Self { user_id, object_id, @@ -261,10 +261,10 @@ impl RevisionRecord { } #[derive(Default)] -struct SyncSequence(VecDeque); -impl SyncSequence { +struct RevisionSyncSequence(VecDeque); +impl RevisionSyncSequence { fn new() -> Self { - SyncSequence::default() + RevisionSyncSequence::default() } fn add(&mut self, new_rev_id: i64) -> FlowyResult<()> { From c843571e3dc5c5a645c2382ae3292c033358c639 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 26 Feb 2022 17:28:23 +0800 Subject: [PATCH 03/12] feat: add new view_type, kanban --- .../workspace/application/doc/doc_bloc.dart | 12 +++----- .../workspace/application/view/view_bloc.dart | 4 +-- .../app_flowy/lib/workspace/domain/image.dart | 4 ++- .../infrastructure/deps_resolver.dart | 8 ++--- .../infrastructure/repos/document_repo.dart | 29 ------------------- .../infrastructure/repos/view_repo.dart | 18 ++++++++++++ .../stack_page/doc/doc_stack_page.dart | 4 --- .../stack_page/trash/trash_page.dart | 4 +-- .../widgets/menu/widget/app/section/item.dart | 18 ++++++------ .../flowy-folder-data-model/view.pbenum.dart | 6 ++-- .../flowy-folder-data-model/view.pbjson.dart | 5 ++-- frontend/rust-lib/dart-ffi/Cargo.toml | 4 +-- .../persistence/version_1/view_sql.rs | 18 +++++++----- .../flowy-folder/tests/workspace/script.rs | 11 +++++-- frontend/rust-lib/flowy-sdk/src/lib.rs | 2 +- frontend/rust-lib/flowy-test/src/helper.rs | 2 +- .../flowy-collaboration/src/synchronizer.rs | 3 +- .../src/entities/view.rs | 6 ++-- .../src/protobuf/model/view.rs | 13 +++++---- .../src/protobuf/proto/view.proto | 3 +- .../src/user_default.rs | 2 +- 21 files changed, 87 insertions(+), 89 deletions(-) delete mode 100644 frontend/app_flowy/lib/workspace/infrastructure/repos/document_repo.dart diff --git a/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart b/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart index 6b977a79e0..6f2d634af5 100644 --- a/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart @@ -1,9 +1,7 @@ import 'dart:convert'; -import 'package:app_flowy/workspace/infrastructure/repos/document_repo.dart'; import 'package:app_flowy/workspace/infrastructure/repos/trash_repo.dart'; import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/trash.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flutter_quill/flutter_quill.dart' show Document, Delta; import 'package:flowy_sdk/log.dart'; @@ -16,15 +14,13 @@ part 'doc_bloc.freezed.dart'; typedef FlutterQuillDocument = Document; class DocumentBloc extends Bloc { - final View view; - final DocumentRepository repo; + final ViewRepository repo; final ViewListener listener; final TrashRepo trashRepo; late FlutterQuillDocument document; StreamSubscription? _subscription; DocumentBloc({ - required this.view, required this.repo, required this.listener, required this.trashRepo, @@ -41,12 +37,12 @@ class DocumentBloc extends Bloc { emit(state.copyWith(isDeleted: false)); }, deletePermanently: (DeletePermanently value) async { - final result = await trashRepo.deleteViews([Tuple2(view.id, TrashType.TrashView)]); + final result = await trashRepo.deleteViews([Tuple2(repo.view.id, TrashType.TrashView)]); final newState = result.fold((l) => state.copyWith(forceClose: true), (r) => state); emit(newState); }, restorePage: (RestorePage value) async { - final result = await trashRepo.putback(view.id); + final result = await trashRepo.putback(repo.view.id); final newState = result.fold((l) => state.copyWith(isDeleted: false), (r) => state); emit(newState); }, @@ -107,7 +103,7 @@ class DocumentBloc extends Bloc { void _composeDelta(Delta composedDelta, Delta documentDelta) async { final json = jsonEncode(composedDelta.toJson()); - Log.debug("doc_id: $view.id - Send json: $json"); + Log.debug("doc_id: $repo.view.id - Send json: $json"); final result = await repo.composeDelta(data: json); result.fold((rustDoc) { diff --git a/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart b/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart index 4bdc939e9a..f9feaab52f 100644 --- a/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart @@ -7,12 +7,12 @@ import 'package:freezed_annotation/freezed_annotation.dart'; part 'view_bloc.freezed.dart'; -class ViewBloc extends Bloc { +class ViewMenuBloc extends Bloc { final ViewRepository repo; final ViewListener listener; - ViewBloc({ + ViewMenuBloc({ required this.repo, required this.listener, }) : super(ViewState.init(repo.view)) { diff --git a/frontend/app_flowy/lib/workspace/domain/image.dart b/frontend/app_flowy/lib/workspace/domain/image.dart index bc10a98697..ef9ab183e0 100644 --- a/frontend/app_flowy/lib/workspace/domain/image.dart +++ b/frontend/app_flowy/lib/workspace/domain/image.dart @@ -17,7 +17,9 @@ extension SvgViewType on View { String _imageNameForViewType(ViewType type) { switch (type) { - case ViewType.Doc: + case ViewType.QuillDocument: + return "file_icon"; + case ViewType.Kanban: return "file_icon"; default: return "file_icon"; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/deps_resolver.dart b/frontend/app_flowy/lib/workspace/infrastructure/deps_resolver.dart index 43502772af..8983c4e41e 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/deps_resolver.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/deps_resolver.dart @@ -9,7 +9,6 @@ import 'package:app_flowy/workspace/application/view/view_bloc.dart'; import 'package:app_flowy/workspace/application/workspace/welcome_bloc.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/infrastructure/repos/app_repo.dart'; -import 'package:app_flowy/workspace/infrastructure/repos/document_repo.dart'; import 'package:app_flowy/workspace/infrastructure/repos/trash_repo.dart'; import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart'; import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart'; @@ -48,8 +47,8 @@ class HomeDepsResolver { (view, _) => ViewListener(view: view), ); - getIt.registerFactoryParam( - (view, _) => ViewBloc( + getIt.registerFactoryParam( + (view, _) => ViewMenuBloc( repo: ViewRepository(view: view), listener: getIt(param1: view), ), @@ -82,8 +81,7 @@ class HomeDepsResolver { // Doc getIt.registerFactoryParam( (view, _) => DocumentBloc( - view: view, - repo: DocumentRepository(docId: view.id), + repo: ViewRepository(view: view), listener: getIt(param1: view), trashRepo: getIt(), ), diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/document_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/document_repo.dart deleted file mode 100644 index 4c01afe8ec..0000000000 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/document_repo.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/dispatch/dispatch.dart'; -import 'package:flowy_sdk/protobuf/flowy-collaboration/document_info.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; - -class DocumentRepository { - final String docId; - DocumentRepository({ - required this.docId, - }); - - Future> openDocument() { - final request = ViewId(value: docId); - return FolderEventOpenView(request).send(); - } - - Future> composeDelta({required String data}) { - final request = BlockDelta.create() - ..blockId = docId - ..deltaJson = data; - return FolderEventApplyDocDelta(request).send(); - } - - Future> closeDocument() { - final request = ViewId(value: docId); - return FolderEventCloseView(request).send(); - } -} diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart index 407b7d62fb..2be27dce94 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart @@ -3,6 +3,7 @@ import 'dart:typed_data'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-collaboration/document_info.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart'; @@ -45,6 +46,23 @@ class ViewRepository { final request = ViewId(value: view.id); return FolderEventDuplicateView(request).send(); } + + Future> openDocument() { + final request = ViewId(value: view.id); + return FolderEventOpenView(request).send(); + } + + Future> composeDelta({required String data}) { + final request = BlockDelta.create() + ..blockId = view.id + ..deltaJson = data; + return FolderEventApplyDocDelta(request).send(); + } + + Future> closeDocument() { + final request = ViewId(value: view.id); + return FolderEventCloseView(request).send(); + } } typedef DeleteNotifierValue = Either; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart index 8094a81f73..c6d7d5c275 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart @@ -64,10 +64,6 @@ class DocStackContext extends HomeStackContext { @override ValueNotifier get isUpdated => _isUpdated; - // List get navigationItems => naviStacks.map((stack) { - // return NavigationItemImpl(context: stack); - // }).toList(); - List _makeNavigationItems() { return [ this, diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart index e005bca21d..1b0038dd89 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart @@ -35,9 +35,7 @@ class TrashStackContext extends HomeStackContext { HomeStackType get type => HomeStackType.trash; @override - Widget buildWidget() { - return const TrashStackPage(key: ValueKey('TrashStackPage')); - } + Widget buildWidget() => const TrashStackPage(key: ValueKey('TrashStackPage')); @override List get navigationItems => [this]; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart index cec56381f3..41da630923 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart @@ -36,12 +36,12 @@ class ViewSectionItem extends StatelessWidget { final theme = context.watch(); return MultiBlocProvider( providers: [ - BlocProvider(create: (ctx) => getIt(param1: view)..add(const ViewEvent.initial())), + BlocProvider(create: (ctx) => getIt(param1: view)..add(const ViewEvent.initial())), ], - child: BlocBuilder( + child: BlocBuilder( builder: (context, state) { return InkWell( - onTap: () => onSelected(context.read().state.view), + onTap: () => onSelected(context.read().state.view), child: FlowyHover( config: HoverDisplayConfig(hoverColor: theme.bg3), builder: (_, onHover) => _render(context, onHover, state, theme.iconColor), @@ -63,9 +63,9 @@ class ViewSectionItem extends StatelessWidget { if (onHover || state.isEditing) { children.add( ViewDisclosureButton( - onTap: () => context.read().add(const ViewEvent.setIsEditing(true)), + onTap: () => context.read().add(const ViewEvent.setIsEditing(true)), onSelected: (action) { - context.read().add(const ViewEvent.setIsEditing(false)); + context.read().add(const ViewEvent.setIsEditing(false)); _handleAction(context, action); }, ), @@ -87,18 +87,18 @@ class ViewSectionItem extends StatelessWidget { case ViewDisclosureAction.rename: TextFieldDialog( title: LocaleKeys.disclosureAction_rename.tr(), - value: context.read().state.view.name, + value: context.read().state.view.name, confirm: (newValue) { - context.read().add(ViewEvent.rename(newValue)); + context.read().add(ViewEvent.rename(newValue)); }, ).show(context); break; case ViewDisclosureAction.delete: - context.read().add(const ViewEvent.delete()); + context.read().add(const ViewEvent.delete()); break; case ViewDisclosureAction.duplicate: - context.read().add(const ViewEvent.duplicate()); + context.read().add(const ViewEvent.duplicate()); break; } }); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbenum.dart index 66b3e7fa16..9d5df0abe2 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbenum.dart @@ -11,11 +11,13 @@ import 'package:protobuf/protobuf.dart' as $pb; class ViewType extends $pb.ProtobufEnum { static const ViewType Blank = ViewType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Blank'); - static const ViewType Doc = ViewType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Doc'); + static const ViewType QuillDocument = ViewType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'QuillDocument'); + static const ViewType Kanban = ViewType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Kanban'); static const $core.List values = [ Blank, - Doc, + QuillDocument, + Kanban, ]; static final $core.Map<$core.int, ViewType> _byValue = $pb.ProtobufEnum.initByValue(values); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart index 27f0c2a46d..04200a8398 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart @@ -13,12 +13,13 @@ const ViewType$json = const { '1': 'ViewType', '2': const [ const {'1': 'Blank', '2': 0}, - const {'1': 'Doc', '2': 1}, + const {'1': 'QuillDocument', '2': 1}, + const {'1': 'Kanban', '2': 2}, ], }; /// Descriptor for `ViewType`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List viewTypeDescriptor = $convert.base64Decode('CghWaWV3VHlwZRIJCgVCbGFuaxAAEgcKA0RvYxAB'); +final $typed_data.Uint8List viewTypeDescriptor = $convert.base64Decode('CghWaWV3VHlwZRIJCgVCbGFuaxAAEhEKDVF1aWxsRG9jdW1lbnQQARIKCgZLYW5iYW4QAg=='); @$core.Deprecated('Use viewDescriptor instead') const View$json = const { '1': 'View', diff --git a/frontend/rust-lib/dart-ffi/Cargo.toml b/frontend/rust-lib/dart-ffi/Cargo.toml index 046fd85668..96755db623 100644 --- a/frontend/rust-lib/dart-ffi/Cargo.toml +++ b/frontend/rust-lib/dart-ffi/Cargo.toml @@ -7,8 +7,8 @@ edition = "2018" [lib] name = "dart_ffi" # this value will change depending on the target os -# default cdylib -crate-type = ["cdylib"] +# default staticlib +crate-type = ["staticlib"] [dependencies] diff --git a/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs b/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs index ad0edbf547..d8610f6208 100644 --- a/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs +++ b/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs @@ -127,8 +127,9 @@ pub(crate) struct ViewTable { impl ViewTable { pub fn new(view: View) -> Self { let view_type = match view.view_type { - ViewType::Blank => ViewTableType::Docs, - ViewType::Doc => ViewTableType::Docs, + ViewType::Kanban => ViewTableType::Kanban, + ViewType::QuillDocument => ViewTableType::QuillDocument, + ViewType::Blank => ViewTableType::QuillDocument, }; ViewTable { @@ -150,7 +151,8 @@ impl ViewTable { impl std::convert::From for View { fn from(table: ViewTable) -> Self { let view_type = match table.view_type { - ViewTableType::Docs => ViewType::Doc, + ViewTableType::QuillDocument => ViewType::QuillDocument, + ViewTableType::Kanban => ViewType::Kanban, }; View { @@ -215,22 +217,24 @@ impl ViewChangeset { #[repr(i32)] #[sql_type = "Integer"] pub enum ViewTableType { - Docs = 0, + QuillDocument = 0, + Kanban = 1, } impl std::default::Default for ViewTableType { fn default() -> Self { - ViewTableType::Docs + ViewTableType::QuillDocument } } impl std::convert::From for ViewTableType { fn from(value: i32) -> Self { match value { - 0 => ViewTableType::Docs, + 0 => ViewTableType::QuillDocument, + 1 => ViewTableType::Kanban, o => { log::error!("Unsupported view type {}, fallback to ViewType::Docs", o); - ViewTableType::Docs + ViewTableType::QuillDocument } } } diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs index 8d4b258ccc..1360c8e834 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs @@ -68,7 +68,14 @@ impl FolderTest { let _ = sdk.init_user().await; let mut workspace = create_workspace(&sdk, "FolderWorkspace", "Folder test workspace").await; let mut app = create_app(&sdk, &workspace.id, "Folder App", "Folder test app").await; - let view = create_view(&sdk, &app.id, "Folder View", "Folder test view", ViewType::Doc).await; + let view = create_view( + &sdk, + &app.id, + "Folder View", + "Folder test view", + ViewType::QuillDocument, + ) + .await; app.belongings = RepeatedView { items: vec![view.clone()], }; @@ -146,7 +153,7 @@ impl FolderTest { } FolderScript::CreateView { name, desc } => { - let view = create_view(sdk, &self.app.id, &name, &desc, ViewType::Doc).await; + let view = create_view(sdk, &self.app.id, &name, &desc, ViewType::QuillDocument).await; self.view = view; } FolderScript::AssertView(view) => { diff --git a/frontend/rust-lib/flowy-sdk/src/lib.rs b/frontend/rust-lib/flowy-sdk/src/lib.rs index 6002243117..b335c37767 100644 --- a/frontend/rust-lib/flowy-sdk/src/lib.rs +++ b/frontend/rust-lib/flowy-sdk/src/lib.rs @@ -67,7 +67,7 @@ fn crate_log_filter(level: String) -> String { filters.push(format!("flowy_folder={}", level)); filters.push(format!("flowy_user={}", level)); filters.push(format!("flowy_document={}", level)); - filters.push(format!("flowy_collaboration={}", level)); + // filters.push(format!("flowy_collaboration={}", level)); filters.push(format!("dart_notify={}", level)); filters.push(format!("lib_ot={}", level)); filters.push(format!("lib_ws={}", level)); diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index ee11346f1f..f5c165f5fc 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -88,7 +88,7 @@ async fn create_view(sdk: &FlowySDKTest, app_id: &str) -> View { name: "View A".to_string(), desc: "".to_string(), thumbnail: Some("http://1.png".to_string()), - view_type: ViewType::Doc, + view_type: ViewType::QuillDocument, }; let view = FolderEventBuilder::new(sdk.clone()) diff --git a/shared-lib/flowy-collaboration/src/synchronizer.rs b/shared-lib/flowy-collaboration/src/synchronizer.rs index 2f9603fec8..2141b84952 100644 --- a/shared-lib/flowy-collaboration/src/synchronizer.rs +++ b/shared-lib/flowy-collaboration/src/synchronizer.rs @@ -146,10 +146,9 @@ where let object_id = self.object_id.clone(); let server_rev_id = self.rev_id(); tracing::Span::current().record("server_rev_id", &server_rev_id); - match server_rev_id.cmp(&client_rev_id) { Ordering::Less => { - tracing::warn!("Client should not send ping and the server should pull the revisions from the client") + tracing::trace!("Client should not send ping and the server should pull the revisions from the client") } Ordering::Equal => tracing::trace!("{} is up to date.", object_id), Ordering::Greater => { diff --git a/shared-lib/flowy-folder-data-model/src/entities/view.rs b/shared-lib/flowy-folder-data-model/src/entities/view.rs index 03899bb9ef..b86be30b11 100644 --- a/shared-lib/flowy-folder-data-model/src/entities/view.rs +++ b/shared-lib/flowy-folder-data-model/src/entities/view.rs @@ -65,7 +65,8 @@ impl std::convert::From for Trash { #[derive(Eq, PartialEq, Debug, ProtoBuf_Enum, Clone, Serialize, Deserialize)] pub enum ViewType { Blank = 0, - Doc = 1, + QuillDocument = 1, + Kanban = 2, } impl std::default::Default for ViewType { @@ -77,8 +78,9 @@ impl std::default::Default for ViewType { impl std::convert::From for ViewType { fn from(val: i32) -> Self { match val { - 1 => ViewType::Doc, 0 => ViewType::Blank, + 1 => ViewType::QuillDocument, + 2 => ViewType::Kanban, _ => { log::error!("Invalid view type: {}", val); ViewType::Blank diff --git a/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs b/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs index 57d3e8ff3b..8f5b1c0fd0 100644 --- a/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs +++ b/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs @@ -2549,7 +2549,8 @@ impl ::protobuf::reflect::ProtobufValue for UpdateViewParams { #[derive(Clone,PartialEq,Eq,Debug,Hash)] pub enum ViewType { Blank = 0, - Doc = 1, + QuillDocument = 1, + Kanban = 2, } impl ::protobuf::ProtobufEnum for ViewType { @@ -2560,7 +2561,8 @@ impl ::protobuf::ProtobufEnum for ViewType { fn from_i32(value: i32) -> ::std::option::Option { match value { 0 => ::std::option::Option::Some(ViewType::Blank), - 1 => ::std::option::Option::Some(ViewType::Doc), + 1 => ::std::option::Option::Some(ViewType::QuillDocument), + 2 => ::std::option::Option::Some(ViewType::Kanban), _ => ::std::option::Option::None } } @@ -2568,7 +2570,8 @@ impl ::protobuf::ProtobufEnum for ViewType { fn values() -> &'static [Self] { static values: &'static [ViewType] = &[ ViewType::Blank, - ViewType::Doc, + ViewType::QuillDocument, + ViewType::Kanban, ]; values } @@ -2626,8 +2629,8 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \tR\x06viewId\x12\x14\n\x04name\x18\x02\x20\x01(\tH\0R\x04name\x12\x14\n\ \x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\x12\x1e\n\tthumbnail\x18\x04\ \x20\x01(\tH\x02R\tthumbnailB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\ - \x12\n\x10one_of_thumbnail*\x1e\n\x08ViewType\x12\t\n\x05Blank\x10\0\x12\ - \x07\n\x03Doc\x10\x01b\x06proto3\ + \x12\n\x10one_of_thumbnail*4\n\x08ViewType\x12\t\n\x05Blank\x10\0\x12\ + \x11\n\rQuillDocument\x10\x01\x12\n\n\x06Kanban\x10\x02b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto b/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto index 149b82178e..fc39c607be 100644 --- a/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto +++ b/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto @@ -50,5 +50,6 @@ message UpdateViewParams { } enum ViewType { Blank = 0; - Doc = 1; + QuillDocument = 1; + Kanban = 2; } diff --git a/shared-lib/flowy-folder-data-model/src/user_default.rs b/shared-lib/flowy-folder-data-model/src/user_default.rs index 3693de6846..9bef631ae4 100644 --- a/shared-lib/flowy-folder-data-model/src/user_default.rs +++ b/shared-lib/flowy-folder-data-model/src/user_default.rs @@ -49,7 +49,7 @@ fn create_default_view(app_id: String, time: chrono::DateTime) -> View { let view_id = uuid::Uuid::new_v4(); let name = "Read me".to_string(); let desc = "".to_string(); - let view_type = ViewType::Doc; + let view_type = ViewType::QuillDocument; View { id: view_id.to_string(), From d18e06a9efd7a92b81763993e80d710deaff6093 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 26 Feb 2022 18:28:09 +0800 Subject: [PATCH 04/12] feat: migrate ViewType::Doc to ViewType::QuillDocument --- .../domain/page_stack/page_stack.dart | 3 +- .../lib/workspace/domain/view_ext.dart | 16 +++---- .../stack_page/doc/doc_stack_page.dart | 4 +- .../src/entities/view.rs | 48 ++++++++++++++++++- 4 files changed, 58 insertions(+), 13 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart b/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart index 8c908d1a9a..bdb57cdf5c 100644 --- a/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart +++ b/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart @@ -19,7 +19,8 @@ abstract class NavigationItem { enum HomeStackType { blank, - doc, + document, + kanban, trash, } diff --git a/frontend/app_flowy/lib/workspace/domain/view_ext.dart b/frontend/app_flowy/lib/workspace/domain/view_ext.dart index 6950061820..fedbb55342 100644 --- a/frontend/app_flowy/lib/workspace/domain/view_ext.dart +++ b/frontend/app_flowy/lib/workspace/domain/view_ext.dart @@ -6,10 +6,10 @@ import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; extension ToHomeStackContext on View { HomeStackContext stackContext() { switch (viewType) { - case ViewType.Blank: - return BlankStackContext(); - case ViewType.Doc: - return DocStackContext(view: this); + case ViewType.QuillDocument: + return DocumentStackContext(view: this); + case ViewType.Kanban: + return DocumentStackContext(view: this); default: return BlankStackContext(); } @@ -19,10 +19,10 @@ extension ToHomeStackContext on View { extension ToHomeStackType on View { HomeStackType stackType() { switch (viewType) { - case ViewType.Blank: - return HomeStackType.blank; - case ViewType.Doc: - return HomeStackType.doc; + case ViewType.QuillDocument: + return HomeStackType.document; + case ViewType.Kanban: + return HomeStackType.kanban; default: return HomeStackType.blank; } diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart index c6d7d5c275..22ba839ed3 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart @@ -24,12 +24,12 @@ import 'package:provider/provider.dart'; import 'document_page.dart'; -class DocStackContext extends HomeStackContext { +class DocumentStackContext extends HomeStackContext { View _view; late ViewListener _listener; final ValueNotifier _isUpdated = ValueNotifier(0); - DocStackContext({required View view, Key? key}) : _view = view { + DocumentStackContext({required View view, Key? key}) : _view = view { _listener = getIt(param1: view); _listener.updatedNotifier.addPublishListener((result) { result.fold( diff --git a/shared-lib/flowy-folder-data-model/src/entities/view.rs b/shared-lib/flowy-folder-data-model/src/entities/view.rs index b86be30b11..c4fd818595 100644 --- a/shared-lib/flowy-folder-data-model/src/entities/view.rs +++ b/shared-lib/flowy-folder-data-model/src/entities/view.rs @@ -8,6 +8,8 @@ use crate::{ }, }; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; +use serde::de::Unexpected; +use serde::{de, de::Visitor, Deserializer}; use serde::{Deserialize, Serialize}; use std::convert::TryInto; @@ -62,7 +64,7 @@ impl std::convert::From for Trash { } } -#[derive(Eq, PartialEq, Debug, ProtoBuf_Enum, Clone, Serialize, Deserialize)] +#[derive(Eq, PartialEq, Debug, ProtoBuf_Enum, Clone, Serialize)] pub enum ViewType { Blank = 0, QuillDocument = 1, @@ -71,7 +73,7 @@ pub enum ViewType { impl std::default::Default for ViewType { fn default() -> Self { - ViewType::Blank + ViewType::QuillDocument } } @@ -277,3 +279,45 @@ impl TryInto for UpdateViewPayload { }) } } + +impl<'de> Deserialize<'de> for ViewType { + fn deserialize(deserializer: D) -> Result>::Error> + where + D: Deserializer<'de>, + { + struct ViewTypeVisitor(); + + impl<'de> Visitor<'de> for ViewTypeVisitor { + type Value = ViewType; + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("QuillDocument, Kanban, Blank") + } + + fn visit_str(self, s: &str) -> Result + where + E: de::Error, + { + let mut view_type = None; + match s { + "Doc" => { + view_type = Some(ViewType::QuillDocument); + } + "QuillDocument" => { + view_type = Some(ViewType::QuillDocument); + } + "Kanban" => { + view_type = Some(ViewType::Kanban); + } + "Blank" => { + view_type = Some(ViewType::Blank); + } + unknown => { + return Err(de::Error::invalid_value(Unexpected::Str(unknown), &self)); + } + } + Ok(view_type.unwrap()) + } + } + deserializer.deserialize_any(ViewTypeVisitor()) + } +} From 23ccfa54b5b01ab2785c60feceee3dc77af50d5e Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 26 Feb 2022 18:35:42 +0800 Subject: [PATCH 05/12] feat: config new ViewType --- .../lib/workspace/domain/view_ext.dart | 24 +++++++++++++++++++ .../menu/widget/app/header/add_button.dart | 5 ++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/domain/view_ext.dart b/frontend/app_flowy/lib/workspace/domain/view_ext.dart index fedbb55342..a15fcec351 100644 --- a/frontend/app_flowy/lib/workspace/domain/view_ext.dart +++ b/frontend/app_flowy/lib/workspace/domain/view_ext.dart @@ -28,3 +28,27 @@ extension ToHomeStackType on View { } } } + +extension ViewTypeExtension on ViewType { + String displayName() { + switch (this) { + case ViewType.QuillDocument: + return "Doc"; + case ViewType.Kanban: + return "Kanban"; + default: + return ""; + } + } + + bool enable() { + switch (this) { + case ViewType.QuillDocument: + return true; + case ViewType.Kanban: + return false; + default: + return false; + } + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart index 106638e2c2..dbb0c6c24f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/workspace/domain/view_ext.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -41,7 +42,7 @@ class ActionList { const ActionList({required this.anchorContext, required this.onSelected}); void show(BuildContext buildContext) { - final items = ViewType.values.where((element) => element != ViewType.Blank).map((ty) { + final items = ViewType.values.where((element) => element.enable()).map((ty) { return CreateItem( viewType: ty, onSelected: (viewType) { @@ -83,7 +84,7 @@ class CreateItem extends StatelessWidget { return GestureDetector( onTap: () => onSelected(viewType), child: FlowyText.medium( - viewType.name, + viewType.displayName(), color: theme.textColor, fontSize: 12, ).padding(horizontal: 10, vertical: 6), From 74831964a6590d35b4b1dfbb9c35c089dc4837d9 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 28 Feb 2022 16:00:43 +0800 Subject: [PATCH 06/12] feat: update view properties --- .../app_flowy/lib/workspace/domain/image.dart | 4 +- .../lib/workspace/domain/view_ext.dart | 16 +- .../flowy-folder-data-model/view.pb.dart | 36 ++-- .../flowy-folder-data-model/view.pbenum.dart | 10 +- .../flowy-folder-data-model/view.pbjson.dart | 14 +- .../rust-lib/flowy-document/src/manager.rs | 3 +- .../rust-lib/flowy-folder/src/controller.rs | 8 +- .../persistence/version_1/view_sql.rs | 21 ++- .../src/services/view/controller.rs | 31 ++-- .../flowy-folder/tests/workspace/script.rs | 11 +- frontend/rust-lib/flowy-test/src/helper.rs | 2 +- .../src/entities/view.rs | 51 +++--- .../src/parser/view/mod.rs | 2 + .../src/parser/view/view_ext.rs | 16 ++ .../src/protobuf/model/view.rs | 165 +++++++++++------- .../src/protobuf/proto/view.proto | 8 +- .../src/user_default.rs | 2 +- 17 files changed, 225 insertions(+), 175 deletions(-) create mode 100644 shared-lib/flowy-folder-data-model/src/parser/view/view_ext.rs diff --git a/frontend/app_flowy/lib/workspace/domain/image.dart b/frontend/app_flowy/lib/workspace/domain/image.dart index ef9ab183e0..a841e424c7 100644 --- a/frontend/app_flowy/lib/workspace/domain/image.dart +++ b/frontend/app_flowy/lib/workspace/domain/image.dart @@ -17,9 +17,9 @@ extension SvgViewType on View { String _imageNameForViewType(ViewType type) { switch (type) { - case ViewType.QuillDocument: + case ViewType.RichText: return "file_icon"; - case ViewType.Kanban: + case ViewType.Plugin: return "file_icon"; default: return "file_icon"; diff --git a/frontend/app_flowy/lib/workspace/domain/view_ext.dart b/frontend/app_flowy/lib/workspace/domain/view_ext.dart index a15fcec351..c0c31e8840 100644 --- a/frontend/app_flowy/lib/workspace/domain/view_ext.dart +++ b/frontend/app_flowy/lib/workspace/domain/view_ext.dart @@ -6,9 +6,9 @@ import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; extension ToHomeStackContext on View { HomeStackContext stackContext() { switch (viewType) { - case ViewType.QuillDocument: + case ViewType.RichText: return DocumentStackContext(view: this); - case ViewType.Kanban: + case ViewType.Plugin: return DocumentStackContext(view: this); default: return BlankStackContext(); @@ -19,9 +19,9 @@ extension ToHomeStackContext on View { extension ToHomeStackType on View { HomeStackType stackType() { switch (viewType) { - case ViewType.QuillDocument: + case ViewType.RichText: return HomeStackType.document; - case ViewType.Kanban: + case ViewType.PlainText: return HomeStackType.kanban; default: return HomeStackType.blank; @@ -32,9 +32,9 @@ extension ToHomeStackType on View { extension ViewTypeExtension on ViewType { String displayName() { switch (this) { - case ViewType.QuillDocument: + case ViewType.RichText: return "Doc"; - case ViewType.Kanban: + case ViewType.Plugin: return "Kanban"; default: return ""; @@ -43,9 +43,9 @@ extension ViewTypeExtension on ViewType { bool enable() { switch (this) { - case ViewType.QuillDocument: + case ViewType.RichText: return true; - case ViewType.Kanban: + case ViewType.Plugin: return false; default: return false; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart index a0b3b4e16b..bbbf6ba927 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart @@ -20,7 +20,7 @@ class View extends $pb.GeneratedMessage { ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'belongToId') ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc') - ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewType', $pb.PbFieldType.OE, defaultOrMaker: ViewType.Blank, valueOf: ViewType.valueOf, enumValues: ViewType.values) + ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewType', $pb.PbFieldType.OE, defaultOrMaker: ViewType.RichText, valueOf: ViewType.valueOf, enumValues: ViewType.values) ..aInt64(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'version') ..aOM(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'belongings', subBuilder: RepeatedView.create) ..aInt64(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'modifiedTime') @@ -232,7 +232,8 @@ class CreateViewPayload extends $pb.GeneratedMessage { ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc') ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail') - ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewType', $pb.PbFieldType.OE, defaultOrMaker: ViewType.Blank, valueOf: ViewType.valueOf, enumValues: ViewType.values) + ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewType', $pb.PbFieldType.OE, defaultOrMaker: ViewType.RichText, valueOf: ViewType.valueOf, enumValues: ViewType.values) + ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ext') ..hasRequiredFields = false ; @@ -243,6 +244,7 @@ class CreateViewPayload extends $pb.GeneratedMessage { $core.String? desc, $core.String? thumbnail, ViewType? viewType, + $core.String? ext, }) { final _result = create(); if (belongToId != null) { @@ -260,6 +262,9 @@ class CreateViewPayload extends $pb.GeneratedMessage { if (viewType != null) { _result.viewType = viewType; } + if (ext != null) { + _result.ext = ext; + } return _result; } factory CreateViewPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -330,6 +335,15 @@ class CreateViewPayload extends $pb.GeneratedMessage { $core.bool hasViewType() => $_has(4); @$pb.TagNumber(5) void clearViewType() => clearField(5); + + @$pb.TagNumber(6) + $core.String get ext => $_getSZ(5); + @$pb.TagNumber(6) + set ext($core.String v) { $_setString(5, v); } + @$pb.TagNumber(6) + $core.bool hasExt() => $_has(5); + @$pb.TagNumber(6) + void clearExt() => clearField(6); } class CreateViewParams extends $pb.GeneratedMessage { @@ -338,8 +352,8 @@ class CreateViewParams extends $pb.GeneratedMessage { ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc') ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail') - ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewType', $pb.PbFieldType.OE, defaultOrMaker: ViewType.Blank, valueOf: ViewType.valueOf, enumValues: ViewType.values) - ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewData') + ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewType', $pb.PbFieldType.OE, defaultOrMaker: ViewType.RichText, valueOf: ViewType.valueOf, enumValues: ViewType.values) + ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ext') ..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId') ..hasRequiredFields = false ; @@ -351,7 +365,7 @@ class CreateViewParams extends $pb.GeneratedMessage { $core.String? desc, $core.String? thumbnail, ViewType? viewType, - $core.String? viewData, + $core.String? ext, $core.String? viewId, }) { final _result = create(); @@ -370,8 +384,8 @@ class CreateViewParams extends $pb.GeneratedMessage { if (viewType != null) { _result.viewType = viewType; } - if (viewData != null) { - _result.viewData = viewData; + if (ext != null) { + _result.ext = ext; } if (viewId != null) { _result.viewId = viewId; @@ -445,13 +459,13 @@ class CreateViewParams extends $pb.GeneratedMessage { void clearViewType() => clearField(5); @$pb.TagNumber(6) - $core.String get viewData => $_getSZ(5); + $core.String get ext => $_getSZ(5); @$pb.TagNumber(6) - set viewData($core.String v) { $_setString(5, v); } + set ext($core.String v) { $_setString(5, v); } @$pb.TagNumber(6) - $core.bool hasViewData() => $_has(5); + $core.bool hasExt() => $_has(5); @$pb.TagNumber(6) - void clearViewData() => clearField(6); + void clearExt() => clearField(6); @$pb.TagNumber(7) $core.String get viewId => $_getSZ(6); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbenum.dart index 9d5df0abe2..03fcc13afb 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbenum.dart @@ -10,14 +10,12 @@ import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; class ViewType extends $pb.ProtobufEnum { - static const ViewType Blank = ViewType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Blank'); - static const ViewType QuillDocument = ViewType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'QuillDocument'); - static const ViewType Kanban = ViewType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Kanban'); + static const ViewType RichText = ViewType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'RichText'); + static const ViewType PlainText = ViewType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PlainText'); static const $core.List values = [ - Blank, - QuillDocument, - Kanban, + RichText, + PlainText, ]; static final $core.Map<$core.int, ViewType> _byValue = $pb.ProtobufEnum.initByValue(values); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart index 04200a8398..a855f4f6d0 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart @@ -12,14 +12,13 @@ import 'dart:typed_data' as $typed_data; const ViewType$json = const { '1': 'ViewType', '2': const [ - const {'1': 'Blank', '2': 0}, - const {'1': 'QuillDocument', '2': 1}, - const {'1': 'Kanban', '2': 2}, + const {'1': 'RichText', '2': 0}, + const {'1': 'PlainText', '2': 1}, ], }; /// Descriptor for `ViewType`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List viewTypeDescriptor = $convert.base64Decode('CghWaWV3VHlwZRIJCgVCbGFuaxAAEhEKDVF1aWxsRG9jdW1lbnQQARIKCgZLYW5iYW4QAg=='); +final $typed_data.Uint8List viewTypeDescriptor = $convert.base64Decode('CghWaWV3VHlwZRIMCghSaWNoVGV4dBAAEg0KCVBsYWluVGV4dBAB'); @$core.Deprecated('Use viewDescriptor instead') const View$json = const { '1': 'View', @@ -57,6 +56,7 @@ const CreateViewPayload$json = const { const {'1': 'desc', '3': 3, '4': 1, '5': 9, '10': 'desc'}, const {'1': 'thumbnail', '3': 4, '4': 1, '5': 9, '9': 0, '10': 'thumbnail'}, const {'1': 'view_type', '3': 5, '4': 1, '5': 14, '6': '.ViewType', '10': 'viewType'}, + const {'1': 'ext', '3': 6, '4': 1, '5': 9, '10': 'ext'}, ], '8': const [ const {'1': 'one_of_thumbnail'}, @@ -64,7 +64,7 @@ const CreateViewPayload$json = const { }; /// Descriptor for `CreateViewPayload`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List createViewPayloadDescriptor = $convert.base64Decode('ChFDcmVhdGVWaWV3UGF5bG9hZBIgCgxiZWxvbmdfdG9faWQYASABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEh4KCXRodW1ibmFpbBgEIAEoCUgAUgl0aHVtYm5haWwSJgoJdmlld190eXBlGAUgASgOMgkuVmlld1R5cGVSCHZpZXdUeXBlQhIKEG9uZV9vZl90aHVtYm5haWw='); +final $typed_data.Uint8List createViewPayloadDescriptor = $convert.base64Decode('ChFDcmVhdGVWaWV3UGF5bG9hZBIgCgxiZWxvbmdfdG9faWQYASABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEh4KCXRodW1ibmFpbBgEIAEoCUgAUgl0aHVtYm5haWwSJgoJdmlld190eXBlGAUgASgOMgkuVmlld1R5cGVSCHZpZXdUeXBlEhAKA2V4dBgGIAEoCVIDZXh0QhIKEG9uZV9vZl90aHVtYm5haWw='); @$core.Deprecated('Use createViewParamsDescriptor instead') const CreateViewParams$json = const { '1': 'CreateViewParams', @@ -74,13 +74,13 @@ const CreateViewParams$json = const { const {'1': 'desc', '3': 3, '4': 1, '5': 9, '10': 'desc'}, const {'1': 'thumbnail', '3': 4, '4': 1, '5': 9, '10': 'thumbnail'}, const {'1': 'view_type', '3': 5, '4': 1, '5': 14, '6': '.ViewType', '10': 'viewType'}, - const {'1': 'view_data', '3': 6, '4': 1, '5': 9, '10': 'viewData'}, + const {'1': 'ext', '3': 6, '4': 1, '5': 9, '10': 'ext'}, const {'1': 'view_id', '3': 7, '4': 1, '5': 9, '10': 'viewId'}, ], }; /// Descriptor for `CreateViewParams`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSJgoJdmlld190eXBlGAUgASgOMgkuVmlld1R5cGVSCHZpZXdUeXBlEhsKCXZpZXdfZGF0YRgGIAEoCVIIdmlld0RhdGESFwoHdmlld19pZBgHIAEoCVIGdmlld0lk'); +final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSJgoJdmlld190eXBlGAUgASgOMgkuVmlld1R5cGVSCHZpZXdUeXBlEhAKA2V4dBgGIAEoCVIDZXh0EhcKB3ZpZXdfaWQYByABKAlSBnZpZXdJZA=='); @$core.Deprecated('Use viewIdDescriptor instead') const ViewId$json = const { '1': 'ViewId', diff --git a/frontend/rust-lib/flowy-document/src/manager.rs b/frontend/rust-lib/flowy-document/src/manager.rs index f07558c8f4..6f6ecf15c5 100644 --- a/frontend/rust-lib/flowy-document/src/manager.rs +++ b/frontend/rust-lib/flowy-document/src/manager.rs @@ -81,9 +81,10 @@ impl BlockManager { }) } - pub async fn reset_with_revisions>(&self, doc_id: T, revisions: RepeatedRevision) -> FlowyResult<()> { + pub async fn create_block>(&self, doc_id: T, revisions: RepeatedRevision) -> FlowyResult<()> { let doc_id = doc_id.as_ref().to_owned(); let db_pool = self.block_user.db_pool()?; + // Maybe we could save the block to disk without creating the RevisionManager let rev_manager = self.make_rev_manager(&doc_id, db_pool)?; let _ = rev_manager.reset_object(revisions).await?; Ok(()) diff --git a/frontend/rust-lib/flowy-folder/src/controller.rs b/frontend/rust-lib/flowy-folder/src/controller.rs index 020c9d2ee8..22c146f4f2 100644 --- a/frontend/rust-lib/flowy-folder/src/controller.rs +++ b/frontend/rust-lib/flowy-folder/src/controller.rs @@ -8,6 +8,7 @@ use lazy_static::lazy_static; use flowy_collaboration::{client_folder::FolderPad, entities::ws_data::ServerRevisionWSData}; use flowy_document::BlockManager; +use flowy_collaboration::entities::revision::{RepeatedRevision, Revision}; use std::{collections::HashMap, convert::TryInto, fmt::Formatter, sync::Arc}; use tokio::sync::RwLock as TokioRwLock; @@ -201,9 +202,10 @@ impl DefaultFolderBuilder { initial_delta().to_json() }; view_controller.set_latest_view(view); - let _ = view_controller - .create_view_document_content(&view.id, view_data) - .await?; + let delta_data = Bytes::from(view_data); + let repeated_revision: RepeatedRevision = + Revision::initial_revision(user_id, &view.id, delta_data).into(); + let _ = view_controller.create_view(&view.id, repeated_revision).await?; } } let folder = FolderPad::new(vec![workspace.clone()], vec![])?; diff --git a/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs b/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs index d8610f6208..a819629c95 100644 --- a/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs +++ b/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs @@ -127,9 +127,8 @@ pub(crate) struct ViewTable { impl ViewTable { pub fn new(view: View) -> Self { let view_type = match view.view_type { - ViewType::Kanban => ViewTableType::Kanban, - ViewType::QuillDocument => ViewTableType::QuillDocument, - ViewType::Blank => ViewTableType::QuillDocument, + ViewType::RichText => ViewTableType::RichText, + ViewType::PlainText => ViewTableType::Text, }; ViewTable { @@ -151,8 +150,8 @@ impl ViewTable { impl std::convert::From for View { fn from(table: ViewTable) -> Self { let view_type = match table.view_type { - ViewTableType::QuillDocument => ViewType::QuillDocument, - ViewTableType::Kanban => ViewType::Kanban, + ViewTableType::RichText => ViewType::RichText, + ViewTableType::Text => ViewType::PlainText, }; View { @@ -217,24 +216,24 @@ impl ViewChangeset { #[repr(i32)] #[sql_type = "Integer"] pub enum ViewTableType { - QuillDocument = 0, - Kanban = 1, + RichText = 0, + Text = 1, } impl std::default::Default for ViewTableType { fn default() -> Self { - ViewTableType::QuillDocument + ViewTableType::RichText } } impl std::convert::From for ViewTableType { fn from(value: i32) -> Self { match value { - 0 => ViewTableType::QuillDocument, - 1 => ViewTableType::Kanban, + 0 => ViewTableType::RichText, + 1 => ViewTableType::Text, o => { log::error!("Unsupported view type {}, fallback to ViewType::Docs", o); - ViewTableType::QuillDocument + ViewTableType::Text } } } diff --git a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs index 16bbe54949..748a27513b 100644 --- a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs +++ b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs @@ -24,6 +24,7 @@ use crate::{ use flowy_database::kv::KV; use flowy_document::BlockManager; use flowy_folder_data_model::entities::share::{ExportData, ExportParams}; +use flowy_folder_data_model::entities::view::ViewType; use lib_infra::uuid_string; const LATEST_VIEW_ID: &str = "latest_view_id"; @@ -61,43 +62,33 @@ impl ViewController { #[tracing::instrument(level = "trace", skip(self, params), fields(name = %params.name), err)] pub(crate) async fn create_view_from_params(&self, params: CreateViewParams) -> Result { - let view_data = if params.view_data.is_empty() { + let view_data = if params.ext.is_empty() { initial_delta_string() } else { - params.view_data.clone() + params.ext.clone() }; let delta_data = Bytes::from(view_data); let user_id = self.user.user_id()?; let repeated_revision: RepeatedRevision = Revision::initial_revision(&user_id, ¶ms.view_id, delta_data).into(); - let _ = self - .block_manager - .reset_with_revisions(¶ms.view_id, repeated_revision) - .await?; + let _ = self.create_view(¶ms.view_id, repeated_revision).await?; let view = self.create_view_on_server(params).await?; let _ = self.create_view_on_local(view.clone()).await?; - Ok(view) } - #[tracing::instrument(level = "debug", skip(self, view_id, view_data), err)] - pub(crate) async fn create_view_document_content( + #[tracing::instrument(level = "debug", skip(self, view_id, view_type, repeated_revision), err)] + pub(crate) async fn create_view( &self, view_id: &str, - view_data: String, + repeated_revision: RepeatedRevision, + view_type: ViewType, ) -> Result<(), FlowyError> { - if view_data.is_empty() { + if repeated_revision.is_empty() { return Err(FlowyError::internal().context("The content of the view should not be empty")); } - - let delta_data = Bytes::from(view_data); - let user_id = self.user.user_id()?; - let repeated_revision: RepeatedRevision = Revision::initial_revision(&user_id, view_id, delta_data).into(); - let _ = self - .block_manager - .reset_with_revisions(view_id, repeated_revision) - .await?; + let _ = self.block_manager.create_block(view_id, repeated_revision).await?; Ok(()) } @@ -185,7 +176,7 @@ impl ViewController { desc: view.desc.clone(), thumbnail: "".to_owned(), view_type: view.view_type.clone(), - view_data: document_json, + ext: document_json, view_id: uuid_string(), }; diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs index 1360c8e834..70fa19eedd 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs @@ -68,14 +68,7 @@ impl FolderTest { let _ = sdk.init_user().await; let mut workspace = create_workspace(&sdk, "FolderWorkspace", "Folder test workspace").await; let mut app = create_app(&sdk, &workspace.id, "Folder App", "Folder test app").await; - let view = create_view( - &sdk, - &app.id, - "Folder View", - "Folder test view", - ViewType::QuillDocument, - ) - .await; + let view = create_view(&sdk, &app.id, "Folder View", "Folder test view", ViewType::RichText).await; app.belongings = RepeatedView { items: vec![view.clone()], }; @@ -153,7 +146,7 @@ impl FolderTest { } FolderScript::CreateView { name, desc } => { - let view = create_view(sdk, &self.app.id, &name, &desc, ViewType::QuillDocument).await; + let view = create_view(sdk, &self.app.id, &name, &desc, ViewType::RichText).await; self.view = view; } FolderScript::AssertView(view) => { diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index f5c165f5fc..6f87c226cd 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -88,7 +88,7 @@ async fn create_view(sdk: &FlowySDKTest, app_id: &str) -> View { name: "View A".to_string(), desc: "".to_string(), thumbnail: Some("http://1.png".to_string()), - view_type: ViewType::QuillDocument, + view_type: ViewType::RichText, }; let view = FolderEventBuilder::new(sdk.clone()) diff --git a/shared-lib/flowy-folder-data-model/src/entities/view.rs b/shared-lib/flowy-folder-data-model/src/entities/view.rs index c4fd818595..0a6b03a41d 100644 --- a/shared-lib/flowy-folder-data-model/src/entities/view.rs +++ b/shared-lib/flowy-folder-data-model/src/entities/view.rs @@ -4,7 +4,7 @@ use crate::{ impl_def_and_def_mut, parser::{ app::AppIdentify, - view::{ViewDesc, ViewIdentify, ViewName, ViewThumbnail}, + view::{ViewDesc, ViewExtensionData, ViewIdentify, ViewName, ViewThumbnail}, }, }; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; @@ -66,26 +66,24 @@ impl std::convert::From for Trash { #[derive(Eq, PartialEq, Debug, ProtoBuf_Enum, Clone, Serialize)] pub enum ViewType { - Blank = 0, - QuillDocument = 1, - Kanban = 2, + RichText = 0, + PlainText = 1, } impl std::default::Default for ViewType { fn default() -> Self { - ViewType::QuillDocument + ViewType::PlainText } } impl std::convert::From for ViewType { fn from(val: i32) -> Self { match val { - 0 => ViewType::Blank, - 1 => ViewType::QuillDocument, - 2 => ViewType::Kanban, + 0 => ViewType::RichText, + 1 => ViewType::PlainText, _ => { log::error!("Invalid view type: {}", val); - ViewType::Blank + ViewType::PlainText } } } @@ -107,6 +105,9 @@ pub struct CreateViewPayload { #[pb(index = 5)] pub view_type: ViewType, + + #[pb(index = 6)] + pub ext: String, } #[derive(Default, ProtoBuf, Debug, Clone)] @@ -126,9 +127,8 @@ pub struct CreateViewParams { #[pb(index = 5)] pub view_type: ViewType, - // ViewType::Doc -> Delta string #[pb(index = 6)] - pub view_data: String, + pub ext: String, #[pb(index = 7)] pub view_id: String, @@ -141,7 +141,7 @@ impl CreateViewParams { desc: String, view_type: ViewType, thumbnail: String, - view_data: String, + ext: String, view_id: String, ) -> Self { Self { @@ -150,7 +150,7 @@ impl CreateViewParams { desc, thumbnail, view_type, - view_data, + ext, view_id, } } @@ -162,8 +162,8 @@ impl TryInto for CreateViewPayload { fn try_into(self) -> Result { let name = ViewName::parse(self.name)?.0; let belong_to_id = AppIdentify::parse(self.belong_to_id)?.0; - let view_data = "".to_string(); let view_id = uuid::Uuid::new_v4().to_string(); + let ext = ViewExtensionData::parse(self.ext)?.0; let thumbnail = match self.thumbnail { None => "".to_string(), Some(thumbnail) => ViewThumbnail::parse(thumbnail)?.0, @@ -175,7 +175,7 @@ impl TryInto for CreateViewPayload { self.desc, self.view_type, thumbnail, - view_data, + ext, view_id, )) } @@ -290,32 +290,27 @@ impl<'de> Deserialize<'de> for ViewType { impl<'de> Visitor<'de> for ViewTypeVisitor { type Value = ViewType; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("QuillDocument, Kanban, Blank") + formatter.write_str("Plugin, RichText") } fn visit_str(self, s: &str) -> Result where E: de::Error, { - let mut view_type = None; + let view_type; match s { - "Doc" => { - view_type = Some(ViewType::QuillDocument); + "Doc" | "RichText" => { + // Rename ViewType::Doc to ViewType::RichText, So we need to migrate the ViewType manually. + view_type = ViewType::RichText; } - "QuillDocument" => { - view_type = Some(ViewType::QuillDocument); - } - "Kanban" => { - view_type = Some(ViewType::Kanban); - } - "Blank" => { - view_type = Some(ViewType::Blank); + "Plugin" => { + view_type = ViewType::PlainText; } unknown => { return Err(de::Error::invalid_value(Unexpected::Str(unknown), &self)); } } - Ok(view_type.unwrap()) + Ok(view_type) } } deserializer.deserialize_any(ViewTypeVisitor()) diff --git a/shared-lib/flowy-folder-data-model/src/parser/view/mod.rs b/shared-lib/flowy-folder-data-model/src/parser/view/mod.rs index 15b912dc7a..39d7b2385a 100644 --- a/shared-lib/flowy-folder-data-model/src/parser/view/mod.rs +++ b/shared-lib/flowy-folder-data-model/src/parser/view/mod.rs @@ -1,11 +1,13 @@ mod delta_data; mod view_desc; +mod view_ext; mod view_id; mod view_name; mod view_thumbnail; pub use delta_data::*; pub use view_desc::*; +pub use view_ext::*; pub use view_id::*; pub use view_name::*; pub use view_thumbnail::*; diff --git a/shared-lib/flowy-folder-data-model/src/parser/view/view_ext.rs b/shared-lib/flowy-folder-data-model/src/parser/view/view_ext.rs new file mode 100644 index 0000000000..1bb48711bc --- /dev/null +++ b/shared-lib/flowy-folder-data-model/src/parser/view/view_ext.rs @@ -0,0 +1,16 @@ +use crate::errors::ErrorCode; + +#[derive(Debug)] +pub struct ViewExtensionData(pub String); + +impl ViewExtensionData { + pub fn parse(s: String) -> Result { + Ok(Self(s)) + } +} + +impl AsRef for ViewExtensionData { + fn as_ref(&self) -> &str { + &self.0 + } +} diff --git a/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs b/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs index 8f5b1c0fd0..9fefa85482 100644 --- a/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs +++ b/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs @@ -162,7 +162,7 @@ impl View { self.view_type } pub fn clear_view_type(&mut self) { - self.view_type = ViewType::Blank; + self.view_type = ViewType::RichText; } // Param is passed by value, moved @@ -326,7 +326,7 @@ impl ::protobuf::Message for View { if !self.desc.is_empty() { my_size += ::protobuf::rt::string_size(4, &self.desc); } - if self.view_type != ViewType::Blank { + if self.view_type != ViewType::RichText { my_size += ::protobuf::rt::enum_size(5, self.view_type); } if self.version != 0 { @@ -360,7 +360,7 @@ impl ::protobuf::Message for View { if !self.desc.is_empty() { os.write_string(4, &self.desc)?; } - if self.view_type != ViewType::Blank { + if self.view_type != ViewType::RichText { os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.view_type))?; } if self.version != 0 { @@ -480,7 +480,7 @@ impl ::protobuf::Clear for View { self.belong_to_id.clear(); self.name.clear(); self.desc.clear(); - self.view_type = ViewType::Blank; + self.view_type = ViewType::RichText; self.version = 0; self.belongings.clear(); self.modified_time = 0; @@ -674,6 +674,7 @@ pub struct CreateViewPayload { pub name: ::std::string::String, pub desc: ::std::string::String, pub view_type: ViewType, + pub ext: ::std::string::String, // message oneof groups pub one_of_thumbnail: ::std::option::Option, // special fields @@ -831,13 +832,39 @@ impl CreateViewPayload { self.view_type } pub fn clear_view_type(&mut self) { - self.view_type = ViewType::Blank; + self.view_type = ViewType::RichText; } // Param is passed by value, moved pub fn set_view_type(&mut self, v: ViewType) { self.view_type = v; } + + // string ext = 6; + + + pub fn get_ext(&self) -> &str { + &self.ext + } + pub fn clear_ext(&mut self) { + self.ext.clear(); + } + + // Param is passed by value, moved + pub fn set_ext(&mut self, v: ::std::string::String) { + self.ext = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_ext(&mut self) -> &mut ::std::string::String { + &mut self.ext + } + + // Take field + pub fn take_ext(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.ext, ::std::string::String::new()) + } } impl ::protobuf::Message for CreateViewPayload { @@ -867,6 +894,9 @@ impl ::protobuf::Message for CreateViewPayload { 5 => { ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.view_type, 5, &mut self.unknown_fields)? }, + 6 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.ext)?; + }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; }, @@ -888,9 +918,12 @@ impl ::protobuf::Message for CreateViewPayload { if !self.desc.is_empty() { my_size += ::protobuf::rt::string_size(3, &self.desc); } - if self.view_type != ViewType::Blank { + if self.view_type != ViewType::RichText { my_size += ::protobuf::rt::enum_size(5, self.view_type); } + if !self.ext.is_empty() { + my_size += ::protobuf::rt::string_size(6, &self.ext); + } if let ::std::option::Option::Some(ref v) = self.one_of_thumbnail { match v { &CreateViewPayload_oneof_one_of_thumbnail::thumbnail(ref v) => { @@ -913,9 +946,12 @@ impl ::protobuf::Message for CreateViewPayload { if !self.desc.is_empty() { os.write_string(3, &self.desc)?; } - if self.view_type != ViewType::Blank { + if self.view_type != ViewType::RichText { os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.view_type))?; } + if !self.ext.is_empty() { + os.write_string(6, &self.ext)?; + } if let ::std::option::Option::Some(ref v) = self.one_of_thumbnail { match v { &CreateViewPayload_oneof_one_of_thumbnail::thumbnail(ref v) => { @@ -986,6 +1022,11 @@ impl ::protobuf::Message for CreateViewPayload { |m: &CreateViewPayload| { &m.view_type }, |m: &mut CreateViewPayload| { &mut m.view_type }, )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "ext", + |m: &CreateViewPayload| { &m.ext }, + |m: &mut CreateViewPayload| { &mut m.ext }, + )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "CreateViewPayload", fields, @@ -1006,7 +1047,8 @@ impl ::protobuf::Clear for CreateViewPayload { self.name.clear(); self.desc.clear(); self.one_of_thumbnail = ::std::option::Option::None; - self.view_type = ViewType::Blank; + self.view_type = ViewType::RichText; + self.ext.clear(); self.unknown_fields.clear(); } } @@ -1031,7 +1073,7 @@ pub struct CreateViewParams { pub desc: ::std::string::String, pub thumbnail: ::std::string::String, pub view_type: ViewType, - pub view_data: ::std::string::String, + pub ext: ::std::string::String, pub view_id: ::std::string::String, // special fields pub unknown_fields: ::protobuf::UnknownFields, @@ -1160,7 +1202,7 @@ impl CreateViewParams { self.view_type } pub fn clear_view_type(&mut self) { - self.view_type = ViewType::Blank; + self.view_type = ViewType::RichText; } // Param is passed by value, moved @@ -1168,30 +1210,30 @@ impl CreateViewParams { self.view_type = v; } - // string view_data = 6; + // string ext = 6; - pub fn get_view_data(&self) -> &str { - &self.view_data + pub fn get_ext(&self) -> &str { + &self.ext } - pub fn clear_view_data(&mut self) { - self.view_data.clear(); + pub fn clear_ext(&mut self) { + self.ext.clear(); } // Param is passed by value, moved - pub fn set_view_data(&mut self, v: ::std::string::String) { - self.view_data = v; + pub fn set_ext(&mut self, v: ::std::string::String) { + self.ext = v; } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_view_data(&mut self) -> &mut ::std::string::String { - &mut self.view_data + pub fn mut_ext(&mut self) -> &mut ::std::string::String { + &mut self.ext } // Take field - pub fn take_view_data(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.view_data, ::std::string::String::new()) + pub fn take_ext(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.ext, ::std::string::String::new()) } // string view_id = 7; @@ -1246,7 +1288,7 @@ impl ::protobuf::Message for CreateViewParams { ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.view_type, 5, &mut self.unknown_fields)? }, 6 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.view_data)?; + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.ext)?; }, 7 => { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.view_id)?; @@ -1275,11 +1317,11 @@ impl ::protobuf::Message for CreateViewParams { if !self.thumbnail.is_empty() { my_size += ::protobuf::rt::string_size(4, &self.thumbnail); } - if self.view_type != ViewType::Blank { + if self.view_type != ViewType::RichText { my_size += ::protobuf::rt::enum_size(5, self.view_type); } - if !self.view_data.is_empty() { - my_size += ::protobuf::rt::string_size(6, &self.view_data); + if !self.ext.is_empty() { + my_size += ::protobuf::rt::string_size(6, &self.ext); } if !self.view_id.is_empty() { my_size += ::protobuf::rt::string_size(7, &self.view_id); @@ -1302,11 +1344,11 @@ impl ::protobuf::Message for CreateViewParams { if !self.thumbnail.is_empty() { os.write_string(4, &self.thumbnail)?; } - if self.view_type != ViewType::Blank { + if self.view_type != ViewType::RichText { os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.view_type))?; } - if !self.view_data.is_empty() { - os.write_string(6, &self.view_data)?; + if !self.ext.is_empty() { + os.write_string(6, &self.ext)?; } if !self.view_id.is_empty() { os.write_string(7, &self.view_id)?; @@ -1375,9 +1417,9 @@ impl ::protobuf::Message for CreateViewParams { |m: &mut CreateViewParams| { &mut m.view_type }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "view_data", - |m: &CreateViewParams| { &m.view_data }, - |m: &mut CreateViewParams| { &mut m.view_data }, + "ext", + |m: &CreateViewParams| { &m.ext }, + |m: &mut CreateViewParams| { &mut m.ext }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "view_id", @@ -1404,8 +1446,8 @@ impl ::protobuf::Clear for CreateViewParams { self.name.clear(); self.desc.clear(); self.thumbnail.clear(); - self.view_type = ViewType::Blank; - self.view_data.clear(); + self.view_type = ViewType::RichText; + self.ext.clear(); self.view_id.clear(); self.unknown_fields.clear(); } @@ -2548,9 +2590,8 @@ impl ::protobuf::reflect::ProtobufValue for UpdateViewParams { #[derive(Clone,PartialEq,Eq,Debug,Hash)] pub enum ViewType { - Blank = 0, - QuillDocument = 1, - Kanban = 2, + RichText = 0, + PlainText = 1, } impl ::protobuf::ProtobufEnum for ViewType { @@ -2560,18 +2601,16 @@ impl ::protobuf::ProtobufEnum for ViewType { fn from_i32(value: i32) -> ::std::option::Option { match value { - 0 => ::std::option::Option::Some(ViewType::Blank), - 1 => ::std::option::Option::Some(ViewType::QuillDocument), - 2 => ::std::option::Option::Some(ViewType::Kanban), + 0 => ::std::option::Option::Some(ViewType::RichText), + 1 => ::std::option::Option::Some(ViewType::PlainText), _ => ::std::option::Option::None } } fn values() -> &'static [Self] { static values: &'static [ViewType] = &[ - ViewType::Blank, - ViewType::QuillDocument, - ViewType::Kanban, + ViewType::RichText, + ViewType::PlainText, ]; values } @@ -2589,7 +2628,7 @@ impl ::std::marker::Copy for ViewType { impl ::std::default::Default for ViewType { fn default() -> Self { - ViewType::Blank + ViewType::RichText } } @@ -2608,29 +2647,29 @@ static file_descriptor_proto_data: &'static [u8] = b"\ gings\x18\x07\x20\x01(\x0b2\r.RepeatedViewR\nbelongings\x12#\n\rmodified\ _time\x18\x08\x20\x01(\x03R\x0cmodifiedTime\x12\x1f\n\x0bcreate_time\x18\ \t\x20\x01(\x03R\ncreateTime\"+\n\x0cRepeatedView\x12\x1b\n\x05items\x18\ - \x01\x20\x03(\x0b2\x05.ViewR\x05items\"\xb9\x01\n\x11CreateViewPayload\ + \x01\x20\x03(\x0b2\x05.ViewR\x05items\"\xcb\x01\n\x11CreateViewPayload\ \x12\x20\n\x0cbelong_to_id\x18\x01\x20\x01(\tR\nbelongToId\x12\x12\n\x04\ name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\ \x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\0R\tthumbnail\x12&\n\t\ - view_type\x18\x05\x20\x01(\x0e2\t.ViewTypeR\x08viewTypeB\x12\n\x10one_of\ - _thumbnail\"\xd8\x01\n\x10CreateViewParams\x12\x20\n\x0cbelong_to_id\x18\ - \x01\x20\x01(\tR\nbelongToId\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04na\ - me\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12\x1c\n\tthumbnail\ - \x18\x04\x20\x01(\tR\tthumbnail\x12&\n\tview_type\x18\x05\x20\x01(\x0e2\ - \t.ViewTypeR\x08viewType\x12\x1b\n\tview_data\x18\x06\x20\x01(\tR\x08vie\ - wData\x12\x17\n\x07view_id\x18\x07\x20\x01(\tR\x06viewId\"\x1e\n\x06View\ - Id\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"&\n\x0eRepeatedViewI\ - d\x12\x14\n\x05items\x18\x01\x20\x03(\tR\x05items\"\xaa\x01\n\x11UpdateV\ - iewPayload\x12\x17\n\x07view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\ - \x04name\x18\x02\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\ - \x01(\tH\x01R\x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthu\ - mbnailB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnai\ - l\"\xa9\x01\n\x10UpdateViewParams\x12\x17\n\x07view_id\x18\x01\x20\x01(\ - \tR\x06viewId\x12\x14\n\x04name\x18\x02\x20\x01(\tH\0R\x04name\x12\x14\n\ - \x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\x12\x1e\n\tthumbnail\x18\x04\ - \x20\x01(\tH\x02R\tthumbnailB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\ - \x12\n\x10one_of_thumbnail*4\n\x08ViewType\x12\t\n\x05Blank\x10\0\x12\ - \x11\n\rQuillDocument\x10\x01\x12\n\n\x06Kanban\x10\x02b\x06proto3\ + view_type\x18\x05\x20\x01(\x0e2\t.ViewTypeR\x08viewType\x12\x10\n\x03ext\ + \x18\x06\x20\x01(\tR\x03extB\x12\n\x10one_of_thumbnail\"\xcd\x01\n\x10Cr\ + eateViewParams\x12\x20\n\x0cbelong_to_id\x18\x01\x20\x01(\tR\nbelongToId\ + \x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\ + \x20\x01(\tR\x04desc\x12\x1c\n\tthumbnail\x18\x04\x20\x01(\tR\tthumbnail\ + \x12&\n\tview_type\x18\x05\x20\x01(\x0e2\t.ViewTypeR\x08viewType\x12\x10\ + \n\x03ext\x18\x06\x20\x01(\tR\x03ext\x12\x17\n\x07view_id\x18\x07\x20\ + \x01(\tR\x06viewId\"\x1e\n\x06ViewId\x12\x14\n\x05value\x18\x01\x20\x01(\ + \tR\x05value\"&\n\x0eRepeatedViewId\x12\x14\n\x05items\x18\x01\x20\x03(\ + \tR\x05items\"\xaa\x01\n\x11UpdateViewPayload\x12\x17\n\x07view_id\x18\ + \x01\x20\x01(\tR\x06viewId\x12\x14\n\x04name\x18\x02\x20\x01(\tH\0R\x04n\ + ame\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\x12\x1e\n\tthumbn\ + ail\x18\x04\x20\x01(\tH\x02R\tthumbnailB\r\n\x0bone_of_nameB\r\n\x0bone_\ + of_descB\x12\n\x10one_of_thumbnail\"\xa9\x01\n\x10UpdateViewParams\x12\ + \x17\n\x07view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\x04name\x18\ + \x02\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\ + \x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthumbnailB\r\n\ + \x0bone_of_nameB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnail*'\n\x08Vi\ + ewType\x12\x0c\n\x08RichText\x10\0\x12\r\n\tPlainText\x10\x01b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto b/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto index fc39c607be..503c027128 100644 --- a/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto +++ b/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto @@ -20,6 +20,7 @@ message CreateViewPayload { string desc = 3; oneof one_of_thumbnail { string thumbnail = 4; }; ViewType view_type = 5; + string ext = 6; } message CreateViewParams { string belong_to_id = 1; @@ -27,7 +28,7 @@ message CreateViewParams { string desc = 3; string thumbnail = 4; ViewType view_type = 5; - string view_data = 6; + string ext = 6; string view_id = 7; } message ViewId { @@ -49,7 +50,6 @@ message UpdateViewParams { oneof one_of_thumbnail { string thumbnail = 4; }; } enum ViewType { - Blank = 0; - QuillDocument = 1; - Kanban = 2; + RichText = 0; + PlainText = 1; } diff --git a/shared-lib/flowy-folder-data-model/src/user_default.rs b/shared-lib/flowy-folder-data-model/src/user_default.rs index 9bef631ae4..3ea164e0cd 100644 --- a/shared-lib/flowy-folder-data-model/src/user_default.rs +++ b/shared-lib/flowy-folder-data-model/src/user_default.rs @@ -49,7 +49,7 @@ fn create_default_view(app_id: String, time: chrono::DateTime) -> View { let view_id = uuid::Uuid::new_v4(); let name = "Read me".to_string(); let desc = "".to_string(); - let view_type = ViewType::QuillDocument; + let view_type = ViewType::RichText; View { id: view_id.to_string(), From 87474578362b54107c5e7618016033ed8a7209ce Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 28 Feb 2022 22:38:53 +0800 Subject: [PATCH 07/12] refactor: add plugins --- frontend/app_flowy/lib/plugin/plugin.dart | 60 +++ frontend/app_flowy/lib/plugin/src/runner.dart | 1 + .../app_flowy/lib/plugin/src/sandbox.dart | 40 ++ frontend/app_flowy/lib/startup/startup.dart | 3 + .../lib/startup/tasks/load_plugin.dart | 39 ++ .../app_flowy/lib/startup/tasks/prelude.dart | 3 +- .../tasks/{init_sdk.dart => rust_sdk.dart} | 0 .../workspace/application/app/app_bloc.dart | 5 +- .../workspace/application/menu/menu_bloc.dart | 12 +- .../application/menu/menu_bloc.freezed.dart | 131 +++--- .../workspace/application/view/view_bloc.dart | 1 - .../app_flowy/lib/workspace/domain/image.dart | 27 -- .../domain/page_stack/page_stack.dart | 53 +-- .../lib/workspace/domain/view_ext.dart | 54 +-- .../infrastructure/repos/app_repo.dart | 5 +- .../presentation/home/home_screen.dart | 4 +- .../presentation/home/navigation.dart | 6 +- .../stack_page/blank/blank_page.dart | 58 ++- .../stack_page/doc/doc_stack_page.dart | 73 +++- .../presentation/stack_page/home_stack.dart | 11 - .../stack_page/trash/trash_page.dart | 52 ++- .../presentation/widgets/home_top_bar.dart | 29 +- .../presentation/widgets/menu/menu.dart | 4 +- .../menu/widget/app/header/add_button.dart | 40 +- .../menu/widget/app/header/header.dart | 10 +- .../widgets/menu/widget/app/section/item.dart | 4 +- .../menu/widget/app/section/section.dart | 2 +- .../widgets/menu/widget/menu_trash.dart | 5 +- .../flowy-folder-data-model/view.pb.dart | 122 ++++-- .../flowy-folder-data-model/view.pbenum.dart | 14 +- .../flowy-folder-data-model/view.pbjson.dart | 29 +- frontend/rust-lib/flowy-document/src/queue.rs | 6 +- .../rust-lib/flowy-document/src/web_socket.rs | 25 +- .../src/services/folder_editor.rs | 4 +- .../persistence/version_1/view_sql.rs | 45 +- .../src/services/view/controller.rs | 18 +- .../flowy-folder/src/services/web_socket.rs | 28 +- .../flowy-folder/tests/workspace/helper.rs | 7 +- .../flowy-folder/tests/workspace/script.rs | 6 +- .../flowy-net/src/local_server/server.rs | 4 +- .../flowy-sync/src/conflict_resolve.rs | 8 +- frontend/rust-lib/flowy-test/src/helper.rs | 3 +- .../src/client_folder/builder.rs | 8 +- .../src/client_folder/folder_pad.rs | 16 +- .../src/entities/folder_info.rs | 4 +- .../src/server_folder/folder_manager.rs | 4 +- .../src/server_folder/folder_pad.rs | 13 +- .../src/entities/view.rs | 75 ++-- .../src/protobuf/model/view.rs | 405 ++++++++++++------ .../src/protobuf/proto/view.proto | 15 +- .../src/user_default.rs | 8 +- shared-lib/lib-ot/src/core/delta/builder.rs | 4 +- shared-lib/lib-ot/src/core/delta/delta.rs | 2 +- .../lib-ot/src/core/operation/builder.rs | 4 +- .../lib-ot/src/core/operation/operation.rs | 8 +- shared-lib/lib-ot/src/rich_text/attributes.rs | 3 +- .../lib-ot/src/rich_text/attributes_serde.rs | 2 +- 57 files changed, 975 insertions(+), 647 deletions(-) create mode 100644 frontend/app_flowy/lib/plugin/plugin.dart create mode 100644 frontend/app_flowy/lib/plugin/src/runner.dart create mode 100644 frontend/app_flowy/lib/plugin/src/sandbox.dart create mode 100644 frontend/app_flowy/lib/startup/tasks/load_plugin.dart rename frontend/app_flowy/lib/startup/tasks/{init_sdk.dart => rust_sdk.dart} (100%) delete mode 100644 frontend/app_flowy/lib/workspace/domain/image.dart diff --git a/frontend/app_flowy/lib/plugin/plugin.dart b/frontend/app_flowy/lib/plugin/plugin.dart new file mode 100644 index 0000000000..cc7894aab1 --- /dev/null +++ b/frontend/app_flowy/lib/plugin/plugin.dart @@ -0,0 +1,60 @@ +library flowy_plugin; + +import 'package:app_flowy/plugin/plugin.dart'; +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; +import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; +import 'package:flutter/widgets.dart'; + +export "./src/sandbox.dart"; + +typedef PluginType = String; + +typedef PluginDataType = ViewDataType; + +abstract class Plugin { + PluginType get pluginType; + + String get pluginId; + + bool get enable; + + void dispose(); + + PluginDisplay get display; +} + +abstract class PluginBuilder { + Plugin build(dynamic data); + + String get pluginName; + + PluginType get pluginType; + + ViewDataType get dataType; +} + +abstract class PluginDisplay with NavigationItem { + @override + Widget get leftBarItem; + + @override + Widget? get rightBarItem; + + List get navigationItems; + + Widget buildWidget(); +} + +void registerPlugin({required PluginBuilder builder}) { + getIt().registerPlugin(builder.pluginType, builder); +} + +Plugin makePlugin({required String pluginType, dynamic data}) { + final plugin = getIt().buildPlugin(pluginType, data); + return plugin; +} + +enum FlowyPluginException { + invalidData, +} diff --git a/frontend/app_flowy/lib/plugin/src/runner.dart b/frontend/app_flowy/lib/plugin/src/runner.dart new file mode 100644 index 0000000000..55df30f2c5 --- /dev/null +++ b/frontend/app_flowy/lib/plugin/src/runner.dart @@ -0,0 +1 @@ +class PluginRunner {} diff --git a/frontend/app_flowy/lib/plugin/src/sandbox.dart b/frontend/app_flowy/lib/plugin/src/sandbox.dart new file mode 100644 index 0000000000..02dd64d062 --- /dev/null +++ b/frontend/app_flowy/lib/plugin/src/sandbox.dart @@ -0,0 +1,40 @@ +import 'dart:collection'; + +import 'package:flutter/services.dart'; + +import '../plugin.dart'; +import 'runner.dart'; + +class PluginSandbox { + final LinkedHashMap _pluginMap = LinkedHashMap(); + late PluginRunner pluginRunner; + + PluginSandbox() { + pluginRunner = PluginRunner(); + } + + int indexOf(String pluginType) { + final index = _pluginMap.keys.toList().indexWhere((ty) => ty == pluginType); + if (index == -1) { + throw PlatformException(code: '-1', message: "Can't find the flowy plugin type: $pluginType"); + } + return index; + } + + Plugin buildPlugin(String pluginType, dynamic data) { + final index = indexOf(pluginType); + final plugin = _pluginMap[index]!.build(data); + return plugin; + } + + void registerPlugin(String pluginType, PluginBuilder builder) { + if (_pluginMap.containsKey(pluginType)) { + throw PlatformException(code: '-1', message: "$pluginType was registered before"); + } + _pluginMap[pluginType] = builder; + } + + List get supportPluginTypes => _pluginMap.keys.toList(); + + List get builders => _pluginMap.values.toList(); +} diff --git a/frontend/app_flowy/lib/startup/startup.dart b/frontend/app_flowy/lib/startup/startup.dart index 283a751c75..5799f33fb5 100644 --- a/frontend/app_flowy/lib/startup/startup.dart +++ b/frontend/app_flowy/lib/startup/startup.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/startup/tasks/prelude.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -41,6 +42,7 @@ class FlowyRunner { getIt().addTask(InitRustSDKTask()); if (!env.isTest()) { + getIt().addTask(PluginLoadTask()); getIt().addTask(InitAppWidgetTask()); getIt().addTask(InitPlatformServiceTask()); } @@ -58,6 +60,7 @@ Future initGetIt( getIt.registerFactory(() => f); getIt.registerLazySingleton(() => const FlowySDK()); getIt.registerLazySingleton(() => AppLauncher(env, getIt)); + getIt.registerSingleton(PluginSandbox()); await UserDepsResolver.resolve(getIt); await HomeDepsResolver.resolve(getIt); diff --git a/frontend/app_flowy/lib/startup/tasks/load_plugin.dart b/frontend/app_flowy/lib/startup/tasks/load_plugin.dart new file mode 100644 index 0000000000..c2d9b0cb8e --- /dev/null +++ b/frontend/app_flowy/lib/startup/tasks/load_plugin.dart @@ -0,0 +1,39 @@ +import 'package:app_flowy/plugin/plugin.dart'; +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dart'; +import 'package:app_flowy/workspace/presentation/stack_page/doc/doc_stack_page.dart'; +import 'package:app_flowy/workspace/presentation/stack_page/trash/trash_page.dart'; + +enum DefaultPluginEnum { + blank, + trash, +} + +extension FlowyDefaultPluginExt on DefaultPluginEnum { + String type() { + switch (this) { + case DefaultPluginEnum.blank: + return "Blank"; + case DefaultPluginEnum.trash: + return "Trash"; + } + } +} + +bool isDefaultPlugin(String pluginType) { + return DefaultPluginEnum.values.map((e) => e.type()).contains(pluginType); +} + +class PluginLoadTask extends LaunchTask { + @override + LaunchTaskType get type => LaunchTaskType.dataProcessing; + + @override + Future initialize(LaunchContext context) async { + registerPlugin(builder: DocumentPluginBuilder()); + + registerPlugin(builder: TrashPluginBuilder()); + + registerPlugin(builder: BlankPluginBuilder()); + } +} diff --git a/frontend/app_flowy/lib/startup/tasks/prelude.dart b/frontend/app_flowy/lib/startup/tasks/prelude.dart index f1551595ad..c381c17d31 100644 --- a/frontend/app_flowy/lib/startup/tasks/prelude.dart +++ b/frontend/app_flowy/lib/startup/tasks/prelude.dart @@ -1,3 +1,4 @@ export 'app_widget.dart'; -export 'init_sdk.dart'; +export 'rust_sdk.dart'; export 'platform_service.dart'; +export 'load_plugin.dart'; diff --git a/frontend/app_flowy/lib/startup/tasks/init_sdk.dart b/frontend/app_flowy/lib/startup/tasks/rust_sdk.dart similarity index 100% rename from frontend/app_flowy/lib/startup/tasks/init_sdk.dart rename to frontend/app_flowy/lib/startup/tasks/rust_sdk.dart diff --git a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart index ce5415d407..49539cb2d0 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/workspace/infrastructure/repos/app_repo.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart'; @@ -21,7 +22,7 @@ class AppBloc extends Bloc { ); await _fetchViews(emit); }, createView: (CreateView value) async { - final viewOrFailed = await repo.createView(name: value.name, desc: value.desc, viewType: value.viewType); + final viewOrFailed = await repo.createView(name: value.name, desc: value.desc, dataType: value.dataType); viewOrFailed.fold( (view) => emit(state.copyWith( latestCreatedView: view, @@ -95,7 +96,7 @@ class AppBloc extends Bloc { @freezed class AppEvent with _$AppEvent { const factory AppEvent.initial() = Initial; - const factory AppEvent.createView(String name, String desc, ViewType viewType) = CreateView; + const factory AppEvent.createView(String name, String desc, PluginDataType dataType) = CreateView; const factory AppEvent.delete() = Delete; const factory AppEvent.rename(String newName) = Rename; const factory AppEvent.didReceiveViews(List views) = ReceiveViews; diff --git a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart index a601e99721..23224af55b 100644 --- a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart @@ -1,7 +1,7 @@ import 'dart:async'; -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; +import 'package:app_flowy/plugin/plugin.dart'; +import 'package:app_flowy/startup/tasks/load_plugin.dart'; import 'package:app_flowy/workspace/infrastructure/repos/workspace_repo.dart'; -import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart'; @@ -26,7 +26,7 @@ class MenuBloc extends Bloc { emit(state.copyWith(isCollapse: !isCollapse)); }, openPage: (e) async { - emit(state.copyWith(stackContext: e.context)); + emit(state.copyWith(plugin: e.plugin)); }, createApp: (CreateApp event) async { await _performActionOnCreateApp(event, emit); @@ -82,7 +82,7 @@ class MenuBloc extends Bloc { class MenuEvent with _$MenuEvent { const factory MenuEvent.initial() = _Initial; const factory MenuEvent.collapse() = Collapse; - const factory MenuEvent.openPage(HomeStackContext context) = OpenPage; + const factory MenuEvent.openPage(Plugin plugin) = OpenPage; const factory MenuEvent.createApp(String name, {String? desc}) = CreateApp; const factory MenuEvent.didReceiveApps(Either, FlowyError> appsOrFail) = ReceiveApps; } @@ -93,13 +93,13 @@ class MenuState with _$MenuState { required bool isCollapse, required Option> apps, required Either successOrFailure, - required HomeStackContext stackContext, + required Plugin plugin, }) = _MenuState; factory MenuState.initial() => MenuState( isCollapse: false, apps: none(), successOrFailure: left(unit), - stackContext: BlankStackContext(), + plugin: makePlugin(pluginType: DefaultPluginEnum.blank.type()), ); } diff --git a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.freezed.dart b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.freezed.dart index 0eefbf12c8..4148412aee 100644 --- a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.freezed.dart +++ b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.freezed.dart @@ -25,9 +25,9 @@ class _$MenuEventTearOff { return const Collapse(); } - OpenPage openPage(HomeStackContext context) { + OpenPage openPage(Plugin plugin) { return OpenPage( - context, + plugin, ); } @@ -54,8 +54,7 @@ mixin _$MenuEvent { TResult when({ required TResult Function() initial, required TResult Function() collapse, - required TResult Function(HomeStackContext context) - openPage, + required TResult Function(Plugin plugin) openPage, required TResult Function(String name, String? desc) createApp, required TResult Function(Either, FlowyError> appsOrFail) didReceiveApps, @@ -65,7 +64,7 @@ mixin _$MenuEvent { TResult? whenOrNull({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(Plugin plugin)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, }) => @@ -74,7 +73,7 @@ mixin _$MenuEvent { TResult maybeWhen({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(Plugin plugin)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, required TResult orElse(), @@ -164,8 +163,7 @@ class _$_Initial implements _Initial { TResult when({ required TResult Function() initial, required TResult Function() collapse, - required TResult Function(HomeStackContext context) - openPage, + required TResult Function(Plugin plugin) openPage, required TResult Function(String name, String? desc) createApp, required TResult Function(Either, FlowyError> appsOrFail) didReceiveApps, @@ -178,7 +176,7 @@ class _$_Initial implements _Initial { TResult? whenOrNull({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(Plugin plugin)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, }) { @@ -190,7 +188,7 @@ class _$_Initial implements _Initial { TResult maybeWhen({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(Plugin plugin)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, required TResult orElse(), @@ -285,8 +283,7 @@ class _$Collapse implements Collapse { TResult when({ required TResult Function() initial, required TResult Function() collapse, - required TResult Function(HomeStackContext context) - openPage, + required TResult Function(Plugin plugin) openPage, required TResult Function(String name, String? desc) createApp, required TResult Function(Either, FlowyError> appsOrFail) didReceiveApps, @@ -299,7 +296,7 @@ class _$Collapse implements Collapse { TResult? whenOrNull({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(Plugin plugin)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, }) { @@ -311,7 +308,7 @@ class _$Collapse implements Collapse { TResult maybeWhen({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(Plugin plugin)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, required TResult orElse(), @@ -371,7 +368,7 @@ abstract class Collapse implements MenuEvent { abstract class $OpenPageCopyWith<$Res> { factory $OpenPageCopyWith(OpenPage value, $Res Function(OpenPage) then) = _$OpenPageCopyWithImpl<$Res>; - $Res call({HomeStackContext context}); + $Res call({Plugin plugin}); } /// @nodoc @@ -385,13 +382,13 @@ class _$OpenPageCopyWithImpl<$Res> extends _$MenuEventCopyWithImpl<$Res> @override $Res call({ - Object? context = freezed, + Object? plugin = freezed, }) { return _then(OpenPage( - context == freezed - ? _value.context - : context // ignore: cast_nullable_to_non_nullable - as HomeStackContext, + plugin == freezed + ? _value.plugin + : plugin // ignore: cast_nullable_to_non_nullable + as Plugin, )); } } @@ -399,27 +396,27 @@ class _$OpenPageCopyWithImpl<$Res> extends _$MenuEventCopyWithImpl<$Res> /// @nodoc class _$OpenPage implements OpenPage { - const _$OpenPage(this.context); + const _$OpenPage(this.plugin); @override - final HomeStackContext context; + final Plugin plugin; @override String toString() { - return 'MenuEvent.openPage(context: $context)'; + return 'MenuEvent.openPage(plugin: $plugin)'; } @override bool operator ==(dynamic other) { return identical(this, other) || (other is OpenPage && - (identical(other.context, context) || - const DeepCollectionEquality().equals(other.context, context))); + (identical(other.plugin, plugin) || + const DeepCollectionEquality().equals(other.plugin, plugin))); } @override int get hashCode => - runtimeType.hashCode ^ const DeepCollectionEquality().hash(context); + runtimeType.hashCode ^ const DeepCollectionEquality().hash(plugin); @JsonKey(ignore: true) @override @@ -431,13 +428,12 @@ class _$OpenPage implements OpenPage { TResult when({ required TResult Function() initial, required TResult Function() collapse, - required TResult Function(HomeStackContext context) - openPage, + required TResult Function(Plugin plugin) openPage, required TResult Function(String name, String? desc) createApp, required TResult Function(Either, FlowyError> appsOrFail) didReceiveApps, }) { - return openPage(context); + return openPage(plugin); } @override @@ -445,11 +441,11 @@ class _$OpenPage implements OpenPage { TResult? whenOrNull({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(Plugin plugin)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, }) { - return openPage?.call(context); + return openPage?.call(plugin); } @override @@ -457,13 +453,13 @@ class _$OpenPage implements OpenPage { TResult maybeWhen({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(Plugin plugin)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, required TResult orElse(), }) { if (openPage != null) { - return openPage(context); + return openPage(plugin); } return orElse(); } @@ -510,11 +506,9 @@ class _$OpenPage implements OpenPage { } abstract class OpenPage implements MenuEvent { - const factory OpenPage(HomeStackContext context) = - _$OpenPage; + const factory OpenPage(Plugin plugin) = _$OpenPage; - HomeStackContext get context => - throw _privateConstructorUsedError; + Plugin get plugin => throw _privateConstructorUsedError; @JsonKey(ignore: true) $OpenPageCopyWith get copyWith => throw _privateConstructorUsedError; @@ -595,8 +589,7 @@ class _$CreateApp implements CreateApp { TResult when({ required TResult Function() initial, required TResult Function() collapse, - required TResult Function(HomeStackContext context) - openPage, + required TResult Function(Plugin plugin) openPage, required TResult Function(String name, String? desc) createApp, required TResult Function(Either, FlowyError> appsOrFail) didReceiveApps, @@ -609,7 +602,7 @@ class _$CreateApp implements CreateApp { TResult? whenOrNull({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(Plugin plugin)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, }) { @@ -621,7 +614,7 @@ class _$CreateApp implements CreateApp { TResult maybeWhen({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(Plugin plugin)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, required TResult orElse(), @@ -750,8 +743,7 @@ class _$ReceiveApps implements ReceiveApps { TResult when({ required TResult Function() initial, required TResult Function() collapse, - required TResult Function(HomeStackContext context) - openPage, + required TResult Function(Plugin plugin) openPage, required TResult Function(String name, String? desc) createApp, required TResult Function(Either, FlowyError> appsOrFail) didReceiveApps, @@ -764,7 +756,7 @@ class _$ReceiveApps implements ReceiveApps { TResult? whenOrNull({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(Plugin plugin)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, }) { @@ -776,7 +768,7 @@ class _$ReceiveApps implements ReceiveApps { TResult maybeWhen({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(Plugin plugin)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, required TResult orElse(), @@ -847,12 +839,12 @@ class _$MenuStateTearOff { {required bool isCollapse, required Option> apps, required Either successOrFailure, - required HomeStackContext stackContext}) { + required Plugin plugin}) { return _MenuState( isCollapse: isCollapse, apps: apps, successOrFailure: successOrFailure, - stackContext: stackContext, + plugin: plugin, ); } } @@ -866,8 +858,7 @@ mixin _$MenuState { Option> get apps => throw _privateConstructorUsedError; Either get successOrFailure => throw _privateConstructorUsedError; - HomeStackContext get stackContext => - throw _privateConstructorUsedError; + Plugin get plugin => throw _privateConstructorUsedError; @JsonKey(ignore: true) $MenuStateCopyWith get copyWith => @@ -882,7 +873,7 @@ abstract class $MenuStateCopyWith<$Res> { {bool isCollapse, Option> apps, Either successOrFailure, - HomeStackContext stackContext}); + Plugin plugin}); } /// @nodoc @@ -898,7 +889,7 @@ class _$MenuStateCopyWithImpl<$Res> implements $MenuStateCopyWith<$Res> { Object? isCollapse = freezed, Object? apps = freezed, Object? successOrFailure = freezed, - Object? stackContext = freezed, + Object? plugin = freezed, }) { return _then(_value.copyWith( isCollapse: isCollapse == freezed @@ -913,10 +904,10 @@ class _$MenuStateCopyWithImpl<$Res> implements $MenuStateCopyWith<$Res> { ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable as Either, - stackContext: stackContext == freezed - ? _value.stackContext - : stackContext // ignore: cast_nullable_to_non_nullable - as HomeStackContext, + plugin: plugin == freezed + ? _value.plugin + : plugin // ignore: cast_nullable_to_non_nullable + as Plugin, )); } } @@ -931,7 +922,7 @@ abstract class _$MenuStateCopyWith<$Res> implements $MenuStateCopyWith<$Res> { {bool isCollapse, Option> apps, Either successOrFailure, - HomeStackContext stackContext}); + Plugin plugin}); } /// @nodoc @@ -948,7 +939,7 @@ class __$MenuStateCopyWithImpl<$Res> extends _$MenuStateCopyWithImpl<$Res> Object? isCollapse = freezed, Object? apps = freezed, Object? successOrFailure = freezed, - Object? stackContext = freezed, + Object? plugin = freezed, }) { return _then(_MenuState( isCollapse: isCollapse == freezed @@ -963,10 +954,10 @@ class __$MenuStateCopyWithImpl<$Res> extends _$MenuStateCopyWithImpl<$Res> ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable as Either, - stackContext: stackContext == freezed - ? _value.stackContext - : stackContext // ignore: cast_nullable_to_non_nullable - as HomeStackContext, + plugin: plugin == freezed + ? _value.plugin + : plugin // ignore: cast_nullable_to_non_nullable + as Plugin, )); } } @@ -978,7 +969,7 @@ class _$_MenuState implements _MenuState { {required this.isCollapse, required this.apps, required this.successOrFailure, - required this.stackContext}); + required this.plugin}); @override final bool isCollapse; @@ -987,11 +978,11 @@ class _$_MenuState implements _MenuState { @override final Either successOrFailure; @override - final HomeStackContext stackContext; + final Plugin plugin; @override String toString() { - return 'MenuState(isCollapse: $isCollapse, apps: $apps, successOrFailure: $successOrFailure, stackContext: $stackContext)'; + return 'MenuState(isCollapse: $isCollapse, apps: $apps, successOrFailure: $successOrFailure, plugin: $plugin)'; } @override @@ -1006,9 +997,8 @@ class _$_MenuState implements _MenuState { (identical(other.successOrFailure, successOrFailure) || const DeepCollectionEquality() .equals(other.successOrFailure, successOrFailure)) && - (identical(other.stackContext, stackContext) || - const DeepCollectionEquality() - .equals(other.stackContext, stackContext))); + (identical(other.plugin, plugin) || + const DeepCollectionEquality().equals(other.plugin, plugin))); } @override @@ -1017,7 +1007,7 @@ class _$_MenuState implements _MenuState { const DeepCollectionEquality().hash(isCollapse) ^ const DeepCollectionEquality().hash(apps) ^ const DeepCollectionEquality().hash(successOrFailure) ^ - const DeepCollectionEquality().hash(stackContext); + const DeepCollectionEquality().hash(plugin); @JsonKey(ignore: true) @override @@ -1030,7 +1020,7 @@ abstract class _MenuState implements MenuState { {required bool isCollapse, required Option> apps, required Either successOrFailure, - required HomeStackContext stackContext}) = _$_MenuState; + required Plugin plugin}) = _$_MenuState; @override bool get isCollapse => throw _privateConstructorUsedError; @@ -1040,8 +1030,7 @@ abstract class _MenuState implements MenuState { Either get successOrFailure => throw _privateConstructorUsedError; @override - HomeStackContext get stackContext => - throw _privateConstructorUsedError; + Plugin get plugin => throw _privateConstructorUsedError; @override @JsonKey(ignore: true) _$MenuStateCopyWith<_MenuState> get copyWith => diff --git a/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart b/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart index f9feaab52f..de20a9b939 100644 --- a/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart @@ -9,7 +9,6 @@ part 'view_bloc.freezed.dart'; class ViewMenuBloc extends Bloc { final ViewRepository repo; - final ViewListener listener; ViewMenuBloc({ diff --git a/frontend/app_flowy/lib/workspace/domain/image.dart b/frontend/app_flowy/lib/workspace/domain/image.dart deleted file mode 100644 index a841e424c7..0000000000 --- a/frontend/app_flowy/lib/workspace/domain/image.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; -import 'package:flutter/material.dart'; -import 'package:flowy_infra/image.dart'; - -AssetImage assetImageForViewType(ViewType type) { - final imageName = _imageNameForViewType(type); - return AssetImage('assets/images/$imageName'); -} - -extension SvgViewType on View { - Widget thumbnail({Color? iconColor}) { - final imageName = _imageNameForViewType(viewType); - final Widget widget = svg(imageName, color: iconColor); - return widget; - } -} - -String _imageNameForViewType(ViewType type) { - switch (type) { - case ViewType.RichText: - return "file_icon"; - case ViewType.Plugin: - return "file_icon"; - default: - return "file_icon"; - } -} diff --git a/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart b/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart index bdb57cdf5c..594711220e 100644 --- a/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart +++ b/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart @@ -1,3 +1,5 @@ +import 'package:app_flowy/plugin/plugin.dart'; +import 'package:app_flowy/startup/tasks/load_plugin.dart'; import 'package:flowy_infra/notifier.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -10,23 +12,13 @@ typedef NavigationCallback = void Function(String id); abstract class NavigationItem { Widget get leftBarItem; Widget? get rightBarItem => null; - String get identifier; NavigationCallback get action => (id) { getIt().setStackWithId(id); }; } -enum HomeStackType { - blank, - document, - kanban, - trash, -} - -List pages = HomeStackType.values.toList(); - -abstract class HomeStackContext with NavigationItem { +abstract class HomeStackContext with NavigationItem { List get navigationItems; @override @@ -35,40 +27,35 @@ abstract class HomeStackContext with NavigationItem { @override Widget? get rightBarItem; - @override - String get identifier; - ValueNotifier get isUpdated; - HomeStackType get type; - Widget buildWidget(); void dispose(); } class HomeStackNotifier extends ChangeNotifier { - HomeStackContext stackContext; + Plugin _plugin; PublishNotifier collapsedNotifier = PublishNotifier(); - Widget get titleWidget => stackContext.leftBarItem; + Widget get titleWidget => _plugin.display.leftBarItem; - HomeStackNotifier({HomeStackContext? context}) : stackContext = context ?? BlankStackContext(); + HomeStackNotifier({Plugin? plugin}) : _plugin = plugin ?? makePlugin(pluginType: DefaultPluginEnum.blank.type()); - set context(HomeStackContext context) { - if (stackContext.identifier == context.identifier) { + set plugin(Plugin newPlugin) { + if (newPlugin.pluginId == _plugin.pluginId) { return; } - stackContext.isUpdated.removeListener(notifyListeners); - stackContext.dispose(); + // stackContext.isUpdated.removeListener(notifyListeners); + _plugin.dispose(); - stackContext = context; - stackContext.isUpdated.addListener(notifyListeners); + _plugin = newPlugin; + // stackContext.isUpdated.addListener(notifyListeners); notifyListeners(); } - HomeStackContext get context => stackContext; + Plugin get plugin => _plugin; } // HomeStack is initialized as singleton to controll the page stack. @@ -77,13 +64,13 @@ class HomeStackManager { HomeStackManager(); Widget title() { - return _notifier.context.leftBarItem; + return _notifier.plugin.display.leftBarItem; } PublishNotifier get collapsedNotifier => _notifier.collapsedNotifier; - void setStack(HomeStackContext context) { - _notifier.context = context; + void setPlugin(Plugin newPlugin) { + _notifier.plugin = newPlugin; } void setStackWithId(String id) {} @@ -109,10 +96,10 @@ class HomeStackManager { ], child: Consumer(builder: (ctx, HomeStackNotifier notifier, child) { return FadingIndexedStack( - index: pages.indexOf(notifier.context.type), - children: HomeStackType.values.map((viewType) { - if (viewType == notifier.context.type) { - return notifier.context.buildWidget(); + index: getIt().indexOf(notifier.plugin.pluginType), + children: getIt().supportPluginTypes.map((pluginType) { + if (pluginType == notifier.plugin.pluginType) { + return notifier.plugin.display.buildWidget(); } else { return const BlankStackPage(); } diff --git a/frontend/app_flowy/lib/workspace/domain/view_ext.dart b/frontend/app_flowy/lib/workspace/domain/view_ext.dart index c0c31e8840..bb94947128 100644 --- a/frontend/app_flowy/lib/workspace/domain/view_ext.dart +++ b/frontend/app_flowy/lib/workspace/domain/view_ext.dart @@ -1,40 +1,18 @@ -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; -import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dart'; -import 'package:app_flowy/workspace/presentation/stack_page/doc/doc_stack_page.dart'; +import 'package:flowy_infra/image.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; +import 'package:flutter/material.dart'; -extension ToHomeStackContext on View { - HomeStackContext stackContext() { - switch (viewType) { - case ViewType.RichText: - return DocumentStackContext(view: this); - case ViewType.Plugin: - return DocumentStackContext(view: this); - default: - return BlankStackContext(); - } - } +enum FlowyPlugin { + editor, + kanban, } -extension ToHomeStackType on View { - HomeStackType stackType() { - switch (viewType) { - case ViewType.RichText: - return HomeStackType.document; - case ViewType.PlainText: - return HomeStackType.kanban; - default: - return HomeStackType.blank; - } - } -} - -extension ViewTypeExtension on ViewType { +extension FlowyPluginExtension on FlowyPlugin { String displayName() { switch (this) { - case ViewType.RichText: + case FlowyPlugin.editor: return "Doc"; - case ViewType.Plugin: + case FlowyPlugin.kanban: return "Kanban"; default: return ""; @@ -43,12 +21,24 @@ extension ViewTypeExtension on ViewType { bool enable() { switch (this) { - case ViewType.RichText: + case FlowyPlugin.editor: return true; - case ViewType.Plugin: + case FlowyPlugin.kanban: return false; default: return false; } } } + +extension ViewExtension on View { + Widget renderThumbnail({Color? iconColor}) { + String thumbnail = this.thumbnail; + if (thumbnail.isEmpty) { + thumbnail = "file_icon"; + } + + final Widget widget = svg(thumbnail, color: iconColor); + return widget; + } +} diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart index 050cf834fb..f443605365 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:typed_data'; +import 'package:app_flowy/plugin/plugin.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; @@ -26,13 +27,13 @@ class AppRepository { Future> createView({ required String name, required String desc, - required ViewType viewType, + required PluginDataType dataType, }) { final request = CreateViewPayload.create() ..belongToId = appId ..name = name ..desc = desc - ..viewType = viewType; + ..dataType = dataType; return FolderEventCreateView(request).send(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart b/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart index f46f6b8d80..5f1ff4d89b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/workspace/application/home/home_bloc.dart'; import 'package:app_flowy/workspace/application/home/home_listen_bloc.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; @@ -109,7 +110,8 @@ class _HomeScreenState extends State { Widget _buildHomeMenu({required HomeLayout layout, required BuildContext context}) { if (initialView == null && widget.workspaceSetting.hasLatestView()) { initialView = widget.workspaceSetting.latestView; - getIt().setStack(initialView!.stackContext()); + final plugin = makePlugin(pluginType: "RichText", data: initialView); + getIt().setPlugin(plugin); } HomeMenu homeMenu = HomeMenu( diff --git a/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart b/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart index 1b5ddacc90..a739976c1d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart @@ -17,8 +17,8 @@ class NavigationNotifier with ChangeNotifier { void update(HomeStackNotifier notifier) { bool shouldNotify = false; - if (navigationItems != notifier.context.navigationItems) { - navigationItems = notifier.context.navigationItems; + if (navigationItems != notifier.plugin.display.navigationItems) { + navigationItems = notifier.plugin.display.navigationItems; shouldNotify = true; } @@ -59,7 +59,7 @@ class FlowyNavigation extends StatelessWidget { create: (_) { final notifier = Provider.of(context, listen: false); return NavigationNotifier( - navigationItems: notifier.context.navigationItems, + navigationItems: notifier.plugin.display.navigationItems, collapasedNotifier: notifier.collapsedNotifier, ); }, diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart index 6f32b0f671..08db10bfa1 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart @@ -1,24 +1,60 @@ -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; +import 'package:app_flowy/startup/tasks/load_plugin.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pbenum.dart'; import 'package:flutter/material.dart'; -import 'package:app_flowy/generated/locale_keys.g.dart'; -class BlankStackContext extends HomeStackContext { - final ValueNotifier _isUpdated = ValueNotifier(false); +import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:app_flowy/plugin/plugin.dart'; +import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; + +class BlankPluginBuilder implements PluginBuilder { + @override + Plugin build(dynamic data) { + return BlankPagePlugin(pluginType: pluginType); + } @override - String get identifier => "1"; + String get pluginName => "Blank"; + @override + PluginType get pluginType => DefaultPluginEnum.blank.type(); + + @override + ViewDataType get dataType => ViewDataType.PlainText; +} + +class BlankPagePlugin implements Plugin { + late PluginType _pluginType; + BlankPagePlugin({ + required String pluginType, + }) { + _pluginType = pluginType; + } + + @override + void dispose() {} + + @override + PluginDisplay get display => BlankPagePluginDisplay(); + + @override + bool get enable => true; + + @override + String get pluginId => "BlankStack"; + + @override + PluginType get pluginType => _pluginType; +} + +class BlankPagePluginDisplay extends PluginDisplay { @override Widget get leftBarItem => FlowyText.medium(LocaleKeys.blankPageTitle.tr(), fontSize: 12); @override Widget? get rightBarItem => null; - @override - HomeStackType get type => HomeStackType.blank; - @override Widget buildWidget() { return const BlankStackPage(); @@ -26,12 +62,6 @@ class BlankStackContext extends HomeStackContext { @override List get navigationItems => [this]; - - @override - ValueNotifier get isUpdated => _isUpdated; - - @override - void dispose() {} } class BlankStackPage extends StatefulWidget { diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart index 22ba839ed3..9f2c9bd1bc 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart @@ -1,8 +1,8 @@ +import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/appearance.dart'; import 'package:app_flowy/workspace/application/doc/share_bloc.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; -import 'package:app_flowy/workspace/domain/view_ext.dart'; import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart'; import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart'; import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart'; @@ -24,12 +24,34 @@ import 'package:provider/provider.dart'; import 'document_page.dart'; -class DocumentStackContext extends HomeStackContext { - View _view; +class DocumentPluginBuilder implements PluginBuilder { + @override + Plugin build(dynamic data) { + if (data is View) { + return DocumentPlugin(pluginType: pluginType, view: data); + } else { + throw FlowyPluginException.invalidData; + } + } + + @override + String get pluginName => "Doc"; + + @override + PluginType get pluginType => "RichText"; + + @override + ViewDataType get dataType => ViewDataType.RichText; +} + +class DocumentPlugin implements Plugin { + late View _view; late ViewListener _listener; final ValueNotifier _isUpdated = ValueNotifier(0); + late PluginType _pluginType; - DocumentStackContext({required View view, Key? key}) : _view = view { + DocumentPlugin({required PluginType pluginType, required View view, Key? key}) : _view = view { + _pluginType = pluginType; _listener = getIt(param1: view); _listener.updatedNotifier.addPublishListener((result) { result.fold( @@ -43,37 +65,46 @@ class DocumentStackContext extends HomeStackContext { _listener.start(); } + @override + void dispose() { + _listener.close(); + } + + @override + PluginDisplay get display => DocumentPluginDisplay(view: _view); + + @override + bool get enable => true; + + @override + PluginType get pluginType => _pluginType; + + @override + String get pluginId => _view.id; +} + +class DocumentPluginDisplay extends PluginDisplay { + final View _view; + + DocumentPluginDisplay({required View view, Key? key}) : _view = view; + + @override + Widget buildWidget() => DocumentPage(view: _view, key: ValueKey(_view.id)); + @override Widget get leftBarItem => DocumentLeftBarItem(view: _view); @override Widget? get rightBarItem => DocumentShareButton(view: _view); - @override - String get identifier => _view.id; - - @override - HomeStackType get type => _view.stackType(); - - @override - Widget buildWidget() => DocumentPage(view: _view, key: ValueKey(_view.id)); - @override List get navigationItems => _makeNavigationItems(); - @override - ValueNotifier get isUpdated => _isUpdated; - List _makeNavigationItems() { return [ this, ]; } - - @override - void dispose() { - _listener.close(); - } } class DocumentLeftBarItem extends StatefulWidget { diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/home_stack.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/home_stack.dart index 77f8a8c2b7..486967f215 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/home_stack.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/home_stack.dart @@ -10,17 +10,6 @@ import 'package:fluttertoast/fluttertoast.dart'; late FToast fToast; -// [[diagram: HomeStack's widget structure]] -// -// ┌──────────────────┐ ┌───────────────┐ -// ┌──│BlankStackContext │──▶│BlankStackPage │ -// ┌──────────┐ ┌───────────────────┐ ┌─────────────────┐ │ └──────────────────┘ └───────────────┘ -// │HomeStack │─▶│ HomeStackManager │──▶│HomeStackContext │◀─┤ -// └──────────┘ └───────────────────┘ └─────────────────┘ │ ┌─────────────────┐ ┌────────────┐ -// └──│ DocStackContext │───▶│DocStackPage│ -// └─────────────────┘ └────────────┘ -// -// class HomeStack extends StatelessWidget { static GlobalKey scaffoldKey = GlobalKey(); // final Size size; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart index 1b0038dd89..436aea4ac0 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart @@ -1,4 +1,6 @@ +import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/startup/tasks/load_plugin.dart'; import 'package:app_flowy/workspace/application/trash/trash_bloc.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/presentation/stack_page/trash/widget/sizes.dart'; @@ -12,6 +14,7 @@ import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pbenum.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; @@ -19,32 +22,57 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'widget/trash_header.dart'; -class TrashStackContext extends HomeStackContext { - final ValueNotifier _isUpdated = ValueNotifier(false); +class TrashPluginBuilder implements PluginBuilder { + @override + Plugin build(dynamic data) { + return TrashPlugin(pluginType: pluginType); + } @override - String get identifier => "TrashStackContext"; + String get pluginName => "Trash"; + @override + PluginType get pluginType => DefaultPluginEnum.trash.type(); + + @override + ViewDataType get dataType => ViewDataType.PlainText; +} + +class TrashPlugin implements Plugin { + late PluginType _pluginType; + + TrashPlugin({required PluginType pluginType}) { + _pluginType = pluginType; + } + + @override + void dispose() {} + + @override + PluginDisplay get display => TrashPluginDisplay(); + + @override + bool get enable => true; + + @override + String get pluginId => "TrashStack"; + + @override + PluginType get pluginType => _pluginType; +} + +class TrashPluginDisplay extends PluginDisplay { @override Widget get leftBarItem => FlowyText.medium(LocaleKeys.trash_text.tr(), fontSize: 12); @override Widget? get rightBarItem => null; - @override - HomeStackType get type => HomeStackType.trash; - @override Widget buildWidget() => const TrashStackPage(key: ValueKey('TrashStackPage')); @override List get navigationItems => [this]; - - @override - ValueNotifier get isUpdated => _isUpdated; - - @override - void dispose() {} } class TrashStackPage extends StatefulWidget { diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart index 717ab2c139..0ac344cf69 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart @@ -1,13 +1,10 @@ -import 'package:app_flowy/workspace/domain/image.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/presentation/home/home_sizes.dart'; import 'package:app_flowy/workspace/presentation/home/navigation.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flutter/material.dart'; import 'package:flowy_infra_ui/style_widget/extension.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:provider/provider.dart'; class HomeTopBar extends StatelessWidget { @@ -28,7 +25,7 @@ class HomeTopBar extends StatelessWidget { value: Provider.of(context, listen: false), child: Consumer( builder: (BuildContext context, HomeStackNotifier notifier, Widget? child) { - return notifier.stackContext.rightBarItem ?? const SizedBox(); + return notifier.plugin.display.rightBarItem ?? const SizedBox(); }, ), ) // _renderMoreButton(), @@ -41,27 +38,3 @@ class HomeTopBar extends StatelessWidget { ); } } - -class HomeTitle extends StatelessWidget { - final String title; - final ViewType type; - - const HomeTitle({ - Key? key, - required this.title, - required this.type, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Flexible( - child: Row( - children: [ - Image(fit: BoxFit.scaleDown, width: 15, height: 15, image: assetImageForViewType(type)), - const HSpace(6), - FlowyText(title, fontSize: 16), - ], - ), - ); - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart index c2046fce39..f76f226795 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart @@ -70,9 +70,9 @@ class HomeMenu extends StatelessWidget { child: MultiBlocListener( listeners: [ BlocListener( - listenWhen: (p, c) => p.stackContext != c.stackContext, + listenWhen: (p, c) => p.plugin.pluginId != c.plugin.pluginId, listener: (context, state) { - getIt().setStack(state.stackContext); + getIt().setPlugin(state.plugin); }, ), BlocListener( diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart index dbb0c6c24f..90dc29d6c7 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart @@ -1,3 +1,6 @@ +import 'package:app_flowy/plugin/plugin.dart'; +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/startup/tasks/load_plugin.dart'; import 'package:app_flowy/workspace/domain/view_ext.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -5,13 +8,12 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; class AddButton extends StatelessWidget { - final Function(ViewType) onSelected; + final Function(PluginBuilder) onSelected; const AddButton({ Key? key, required this.onSelected, @@ -35,21 +37,29 @@ class AddButton extends StatelessWidget { } class ActionList { - final Function(ViewType) onSelected; + final Function(PluginBuilder) onSelected; final BuildContext anchorContext; final String _identifier = 'DisclosureButtonActionList'; const ActionList({required this.anchorContext, required this.onSelected}); void show(BuildContext buildContext) { - final items = ViewType.values.where((element) => element.enable()).map((ty) { - return CreateItem( - viewType: ty, - onSelected: (viewType) { + final items = getIt() + .builders + .where( + (builder) => !isDefaultPlugin(builder.pluginType), + ) + .map( + (pluginBuilder) { + return CreateItem( + pluginBuilder: pluginBuilder, + onSelected: (builder) { FlowyOverlay.of(buildContext).remove(_identifier); - onSelected(viewType); - }); - }).toList(); + onSelected(builder); + }, + ); + }, + ).toList(); ListOverlay.showWithAnchor( buildContext, @@ -65,11 +75,11 @@ class ActionList { } class CreateItem extends StatelessWidget { - final ViewType viewType; - final Function(ViewType) onSelected; + final PluginBuilder pluginBuilder; + final Function(PluginBuilder) onSelected; const CreateItem({ Key? key, - required this.viewType, + required this.pluginBuilder, required this.onSelected, }) : super(key: key); @@ -82,9 +92,9 @@ class CreateItem extends StatelessWidget { config: config, builder: (context, onHover) { return GestureDetector( - onTap: () => onSelected(viewType), + onTap: () => onSelected(pluginBuilder), child: FlowyText.medium( - viewType.displayName(), + pluginBuilder.pluginName, color: theme.textColor, fontSize: 12, ).padding(horizontal: 10, vertical: 6), diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart index 795de8d5a7..565b6af717 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart @@ -102,10 +102,12 @@ class MenuAppHeader extends StatelessWidget { return Tooltip( message: LocaleKeys.menuAppHeader_addPageTooltip.tr(), child: AddButton( - onSelected: (viewType) { - context - .read() - .add(AppEvent.createView(LocaleKeys.menuAppHeader_defaultNewPageName.tr(), "", viewType)); + onSelected: (pluginBuilder) { + context.read().add(AppEvent.createView( + LocaleKeys.menuAppHeader_defaultNewPageName.tr(), + "", + pluginBuilder.dataType, + )); }, ).padding(right: MenuAppSizes.headerPadding), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart index 41da630923..ad604a295a 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart @@ -1,6 +1,7 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/view/view_bloc.dart'; import 'package:app_flowy/workspace/domain/edit_action/view_edit.dart'; +import 'package:app_flowy/workspace/domain/view_ext.dart'; import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart'; import 'package:dartz/dartz.dart' as dartz; import 'package:easy_localization/easy_localization.dart'; @@ -12,7 +13,6 @@ import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; -import 'package:app_flowy/workspace/domain/image.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/widget/app/menu_app.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; @@ -55,7 +55,7 @@ class ViewSectionItem extends StatelessWidget { Widget _render(BuildContext context, bool onHover, ViewState state, Color iconColor) { List children = [ - SizedBox(width: 16, height: 16, child: state.view.thumbnail(iconColor: iconColor)), + SizedBox(width: 16, height: 16, child: state.view.renderThumbnail(iconColor: iconColor)), const HSpace(2), Expanded(child: FlowyText.regular(state.view.name, fontSize: 12, overflow: TextOverflow.clip)), ]; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart index 455602e3f9..da486e6934 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart @@ -106,7 +106,7 @@ class ViewSectionNotifier with ChangeNotifier { if (view != null) { WidgetsBinding.instance?.addPostFrameCallback((_) { - getIt().setStack(view.stackContext()); + getIt().setPlugin(view.stackContext()); }); } else { // do nothing diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart index 85178de0b6..a86bcef76d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart @@ -1,7 +1,8 @@ +import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/startup/tasks/load_plugin.dart'; import 'package:app_flowy/workspace/application/appearance.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; -import 'package:app_flowy/workspace/presentation/stack_page/trash/trash_page.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/menu.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; @@ -22,7 +23,7 @@ class MenuTrash extends StatelessWidget { child: InkWell( onTap: () { Provider.of(context, listen: false).selectedView.value = null; - getIt().setStack(TrashStackContext()); + getIt().setPlugin(makePlugin(pluginType: DefaultPluginEnum.trash.type())); }, child: _render(context), ), diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart index bbbf6ba927..aac78ead81 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart @@ -20,11 +20,13 @@ class View extends $pb.GeneratedMessage { ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'belongToId') ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc') - ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewType', $pb.PbFieldType.OE, defaultOrMaker: ViewType.RichText, valueOf: ViewType.valueOf, enumValues: ViewType.values) + ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dataType', $pb.PbFieldType.OE, defaultOrMaker: ViewDataType.RichText, valueOf: ViewDataType.valueOf, enumValues: ViewDataType.values) ..aInt64(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'version') ..aOM(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'belongings', subBuilder: RepeatedView.create) ..aInt64(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'modifiedTime') ..aInt64(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'createTime') + ..aOS(10, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extData') + ..aOS(11, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail') ..hasRequiredFields = false ; @@ -34,11 +36,13 @@ class View extends $pb.GeneratedMessage { $core.String? belongToId, $core.String? name, $core.String? desc, - ViewType? viewType, + ViewDataType? dataType, $fixnum.Int64? version, RepeatedView? belongings, $fixnum.Int64? modifiedTime, $fixnum.Int64? createTime, + $core.String? extData, + $core.String? thumbnail, }) { final _result = create(); if (id != null) { @@ -53,8 +57,8 @@ class View extends $pb.GeneratedMessage { if (desc != null) { _result.desc = desc; } - if (viewType != null) { - _result.viewType = viewType; + if (dataType != null) { + _result.dataType = dataType; } if (version != null) { _result.version = version; @@ -68,6 +72,12 @@ class View extends $pb.GeneratedMessage { if (createTime != null) { _result.createTime = createTime; } + if (extData != null) { + _result.extData = extData; + } + if (thumbnail != null) { + _result.thumbnail = thumbnail; + } return _result; } factory View.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -128,13 +138,13 @@ class View extends $pb.GeneratedMessage { void clearDesc() => clearField(4); @$pb.TagNumber(5) - ViewType get viewType => $_getN(4); + ViewDataType get dataType => $_getN(4); @$pb.TagNumber(5) - set viewType(ViewType v) { setField(5, v); } + set dataType(ViewDataType v) { setField(5, v); } @$pb.TagNumber(5) - $core.bool hasViewType() => $_has(4); + $core.bool hasDataType() => $_has(4); @$pb.TagNumber(5) - void clearViewType() => clearField(5); + void clearDataType() => clearField(5); @$pb.TagNumber(6) $fixnum.Int64 get version => $_getI64(5); @@ -173,6 +183,24 @@ class View extends $pb.GeneratedMessage { $core.bool hasCreateTime() => $_has(8); @$pb.TagNumber(9) void clearCreateTime() => clearField(9); + + @$pb.TagNumber(10) + $core.String get extData => $_getSZ(9); + @$pb.TagNumber(10) + set extData($core.String v) { $_setString(9, v); } + @$pb.TagNumber(10) + $core.bool hasExtData() => $_has(9); + @$pb.TagNumber(10) + void clearExtData() => clearField(10); + + @$pb.TagNumber(11) + $core.String get thumbnail => $_getSZ(10); + @$pb.TagNumber(11) + set thumbnail($core.String v) { $_setString(10, v); } + @$pb.TagNumber(11) + $core.bool hasThumbnail() => $_has(10); + @$pb.TagNumber(11) + void clearThumbnail() => clearField(11); } class RepeatedView extends $pb.GeneratedMessage { @@ -232,8 +260,8 @@ class CreateViewPayload extends $pb.GeneratedMessage { ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc') ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail') - ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewType', $pb.PbFieldType.OE, defaultOrMaker: ViewType.RichText, valueOf: ViewType.valueOf, enumValues: ViewType.values) - ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ext') + ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dataType', $pb.PbFieldType.OE, defaultOrMaker: ViewDataType.RichText, valueOf: ViewDataType.valueOf, enumValues: ViewDataType.values) + ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extData') ..hasRequiredFields = false ; @@ -243,8 +271,8 @@ class CreateViewPayload extends $pb.GeneratedMessage { $core.String? name, $core.String? desc, $core.String? thumbnail, - ViewType? viewType, - $core.String? ext, + ViewDataType? dataType, + $core.String? extData, }) { final _result = create(); if (belongToId != null) { @@ -259,11 +287,11 @@ class CreateViewPayload extends $pb.GeneratedMessage { if (thumbnail != null) { _result.thumbnail = thumbnail; } - if (viewType != null) { - _result.viewType = viewType; + if (dataType != null) { + _result.dataType = dataType; } - if (ext != null) { - _result.ext = ext; + if (extData != null) { + _result.extData = extData; } return _result; } @@ -328,22 +356,22 @@ class CreateViewPayload extends $pb.GeneratedMessage { void clearThumbnail() => clearField(4); @$pb.TagNumber(5) - ViewType get viewType => $_getN(4); + ViewDataType get dataType => $_getN(4); @$pb.TagNumber(5) - set viewType(ViewType v) { setField(5, v); } + set dataType(ViewDataType v) { setField(5, v); } @$pb.TagNumber(5) - $core.bool hasViewType() => $_has(4); + $core.bool hasDataType() => $_has(4); @$pb.TagNumber(5) - void clearViewType() => clearField(5); + void clearDataType() => clearField(5); @$pb.TagNumber(6) - $core.String get ext => $_getSZ(5); + $core.String get extData => $_getSZ(5); @$pb.TagNumber(6) - set ext($core.String v) { $_setString(5, v); } + set extData($core.String v) { $_setString(5, v); } @$pb.TagNumber(6) - $core.bool hasExt() => $_has(5); + $core.bool hasExtData() => $_has(5); @$pb.TagNumber(6) - void clearExt() => clearField(6); + void clearExtData() => clearField(6); } class CreateViewParams extends $pb.GeneratedMessage { @@ -352,9 +380,10 @@ class CreateViewParams extends $pb.GeneratedMessage { ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc') ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail') - ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewType', $pb.PbFieldType.OE, defaultOrMaker: ViewType.RichText, valueOf: ViewType.valueOf, enumValues: ViewType.values) - ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ext') + ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dataType', $pb.PbFieldType.OE, defaultOrMaker: ViewDataType.RichText, valueOf: ViewDataType.valueOf, enumValues: ViewDataType.values) + ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extData') ..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId') + ..aOS(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data') ..hasRequiredFields = false ; @@ -364,9 +393,10 @@ class CreateViewParams extends $pb.GeneratedMessage { $core.String? name, $core.String? desc, $core.String? thumbnail, - ViewType? viewType, - $core.String? ext, + ViewDataType? dataType, + $core.String? extData, $core.String? viewId, + $core.String? data, }) { final _result = create(); if (belongToId != null) { @@ -381,15 +411,18 @@ class CreateViewParams extends $pb.GeneratedMessage { if (thumbnail != null) { _result.thumbnail = thumbnail; } - if (viewType != null) { - _result.viewType = viewType; + if (dataType != null) { + _result.dataType = dataType; } - if (ext != null) { - _result.ext = ext; + if (extData != null) { + _result.extData = extData; } if (viewId != null) { _result.viewId = viewId; } + if (data != null) { + _result.data = data; + } return _result; } factory CreateViewParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -450,22 +483,22 @@ class CreateViewParams extends $pb.GeneratedMessage { void clearThumbnail() => clearField(4); @$pb.TagNumber(5) - ViewType get viewType => $_getN(4); + ViewDataType get dataType => $_getN(4); @$pb.TagNumber(5) - set viewType(ViewType v) { setField(5, v); } + set dataType(ViewDataType v) { setField(5, v); } @$pb.TagNumber(5) - $core.bool hasViewType() => $_has(4); + $core.bool hasDataType() => $_has(4); @$pb.TagNumber(5) - void clearViewType() => clearField(5); + void clearDataType() => clearField(5); @$pb.TagNumber(6) - $core.String get ext => $_getSZ(5); + $core.String get extData => $_getSZ(5); @$pb.TagNumber(6) - set ext($core.String v) { $_setString(5, v); } + set extData($core.String v) { $_setString(5, v); } @$pb.TagNumber(6) - $core.bool hasExt() => $_has(5); + $core.bool hasExtData() => $_has(5); @$pb.TagNumber(6) - void clearExt() => clearField(6); + void clearExtData() => clearField(6); @$pb.TagNumber(7) $core.String get viewId => $_getSZ(6); @@ -475,6 +508,15 @@ class CreateViewParams extends $pb.GeneratedMessage { $core.bool hasViewId() => $_has(6); @$pb.TagNumber(7) void clearViewId() => clearField(7); + + @$pb.TagNumber(8) + $core.String get data => $_getSZ(7); + @$pb.TagNumber(8) + set data($core.String v) { $_setString(7, v); } + @$pb.TagNumber(8) + $core.bool hasData() => $_has(7); + @$pb.TagNumber(8) + void clearData() => clearField(8); } class ViewId extends $pb.GeneratedMessage { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbenum.dart index 03fcc13afb..452830c084 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbenum.dart @@ -9,18 +9,18 @@ import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; -class ViewType extends $pb.ProtobufEnum { - static const ViewType RichText = ViewType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'RichText'); - static const ViewType PlainText = ViewType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PlainText'); +class ViewDataType extends $pb.ProtobufEnum { + static const ViewDataType RichText = ViewDataType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'RichText'); + static const ViewDataType PlainText = ViewDataType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PlainText'); - static const $core.List values = [ + static const $core.List values = [ RichText, PlainText, ]; - static final $core.Map<$core.int, ViewType> _byValue = $pb.ProtobufEnum.initByValue(values); - static ViewType? valueOf($core.int value) => _byValue[value]; + static final $core.Map<$core.int, ViewDataType> _byValue = $pb.ProtobufEnum.initByValue(values); + static ViewDataType? valueOf($core.int value) => _byValue[value]; - const ViewType._($core.int v, $core.String n) : super(v, n); + const ViewDataType._($core.int v, $core.String n) : super(v, n); } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart index a855f4f6d0..2221dec960 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart @@ -8,17 +8,17 @@ import 'dart:core' as $core; import 'dart:convert' as $convert; import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use viewTypeDescriptor instead') -const ViewType$json = const { - '1': 'ViewType', +@$core.Deprecated('Use viewDataTypeDescriptor instead') +const ViewDataType$json = const { + '1': 'ViewDataType', '2': const [ const {'1': 'RichText', '2': 0}, const {'1': 'PlainText', '2': 1}, ], }; -/// Descriptor for `ViewType`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List viewTypeDescriptor = $convert.base64Decode('CghWaWV3VHlwZRIMCghSaWNoVGV4dBAAEg0KCVBsYWluVGV4dBAB'); +/// Descriptor for `ViewDataType`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List viewDataTypeDescriptor = $convert.base64Decode('CgxWaWV3RGF0YVR5cGUSDAoIUmljaFRleHQQABINCglQbGFpblRleHQQAQ=='); @$core.Deprecated('Use viewDescriptor instead') const View$json = const { '1': 'View', @@ -27,16 +27,18 @@ const View$json = const { const {'1': 'belong_to_id', '3': 2, '4': 1, '5': 9, '10': 'belongToId'}, const {'1': 'name', '3': 3, '4': 1, '5': 9, '10': 'name'}, const {'1': 'desc', '3': 4, '4': 1, '5': 9, '10': 'desc'}, - const {'1': 'view_type', '3': 5, '4': 1, '5': 14, '6': '.ViewType', '10': 'viewType'}, + const {'1': 'data_type', '3': 5, '4': 1, '5': 14, '6': '.ViewDataType', '10': 'dataType'}, const {'1': 'version', '3': 6, '4': 1, '5': 3, '10': 'version'}, const {'1': 'belongings', '3': 7, '4': 1, '5': 11, '6': '.RepeatedView', '10': 'belongings'}, const {'1': 'modified_time', '3': 8, '4': 1, '5': 3, '10': 'modifiedTime'}, const {'1': 'create_time', '3': 9, '4': 1, '5': 3, '10': 'createTime'}, + const {'1': 'ext_data', '3': 10, '4': 1, '5': 9, '10': 'extData'}, + const {'1': 'thumbnail', '3': 11, '4': 1, '5': 9, '10': 'thumbnail'}, ], }; /// Descriptor for `View`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List viewDescriptor = $convert.base64Decode('CgRWaWV3Eg4KAmlkGAEgASgJUgJpZBIgCgxiZWxvbmdfdG9faWQYAiABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgDIAEoCVIEbmFtZRISCgRkZXNjGAQgASgJUgRkZXNjEiYKCXZpZXdfdHlwZRgFIAEoDjIJLlZpZXdUeXBlUgh2aWV3VHlwZRIYCgd2ZXJzaW9uGAYgASgDUgd2ZXJzaW9uEi0KCmJlbG9uZ2luZ3MYByABKAsyDS5SZXBlYXRlZFZpZXdSCmJlbG9uZ2luZ3MSIwoNbW9kaWZpZWRfdGltZRgIIAEoA1IMbW9kaWZpZWRUaW1lEh8KC2NyZWF0ZV90aW1lGAkgASgDUgpjcmVhdGVUaW1l'); +final $typed_data.Uint8List viewDescriptor = $convert.base64Decode('CgRWaWV3Eg4KAmlkGAEgASgJUgJpZBIgCgxiZWxvbmdfdG9faWQYAiABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgDIAEoCVIEbmFtZRISCgRkZXNjGAQgASgJUgRkZXNjEioKCWRhdGFfdHlwZRgFIAEoDjINLlZpZXdEYXRhVHlwZVIIZGF0YVR5cGUSGAoHdmVyc2lvbhgGIAEoA1IHdmVyc2lvbhItCgpiZWxvbmdpbmdzGAcgASgLMg0uUmVwZWF0ZWRWaWV3UgpiZWxvbmdpbmdzEiMKDW1vZGlmaWVkX3RpbWUYCCABKANSDG1vZGlmaWVkVGltZRIfCgtjcmVhdGVfdGltZRgJIAEoA1IKY3JlYXRlVGltZRIZCghleHRfZGF0YRgKIAEoCVIHZXh0RGF0YRIcCgl0aHVtYm5haWwYCyABKAlSCXRodW1ibmFpbA=='); @$core.Deprecated('Use repeatedViewDescriptor instead') const RepeatedView$json = const { '1': 'RepeatedView', @@ -55,8 +57,8 @@ const CreateViewPayload$json = const { const {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'}, const {'1': 'desc', '3': 3, '4': 1, '5': 9, '10': 'desc'}, const {'1': 'thumbnail', '3': 4, '4': 1, '5': 9, '9': 0, '10': 'thumbnail'}, - const {'1': 'view_type', '3': 5, '4': 1, '5': 14, '6': '.ViewType', '10': 'viewType'}, - const {'1': 'ext', '3': 6, '4': 1, '5': 9, '10': 'ext'}, + const {'1': 'data_type', '3': 5, '4': 1, '5': 14, '6': '.ViewDataType', '10': 'dataType'}, + const {'1': 'ext_data', '3': 6, '4': 1, '5': 9, '10': 'extData'}, ], '8': const [ const {'1': 'one_of_thumbnail'}, @@ -64,7 +66,7 @@ const CreateViewPayload$json = const { }; /// Descriptor for `CreateViewPayload`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List createViewPayloadDescriptor = $convert.base64Decode('ChFDcmVhdGVWaWV3UGF5bG9hZBIgCgxiZWxvbmdfdG9faWQYASABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEh4KCXRodW1ibmFpbBgEIAEoCUgAUgl0aHVtYm5haWwSJgoJdmlld190eXBlGAUgASgOMgkuVmlld1R5cGVSCHZpZXdUeXBlEhAKA2V4dBgGIAEoCVIDZXh0QhIKEG9uZV9vZl90aHVtYm5haWw='); +final $typed_data.Uint8List createViewPayloadDescriptor = $convert.base64Decode('ChFDcmVhdGVWaWV3UGF5bG9hZBIgCgxiZWxvbmdfdG9faWQYASABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEh4KCXRodW1ibmFpbBgEIAEoCUgAUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIZCghleHRfZGF0YRgGIAEoCVIHZXh0RGF0YUISChBvbmVfb2ZfdGh1bWJuYWls'); @$core.Deprecated('Use createViewParamsDescriptor instead') const CreateViewParams$json = const { '1': 'CreateViewParams', @@ -73,14 +75,15 @@ const CreateViewParams$json = const { const {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'}, const {'1': 'desc', '3': 3, '4': 1, '5': 9, '10': 'desc'}, const {'1': 'thumbnail', '3': 4, '4': 1, '5': 9, '10': 'thumbnail'}, - const {'1': 'view_type', '3': 5, '4': 1, '5': 14, '6': '.ViewType', '10': 'viewType'}, - const {'1': 'ext', '3': 6, '4': 1, '5': 9, '10': 'ext'}, + const {'1': 'data_type', '3': 5, '4': 1, '5': 14, '6': '.ViewDataType', '10': 'dataType'}, + const {'1': 'ext_data', '3': 6, '4': 1, '5': 9, '10': 'extData'}, const {'1': 'view_id', '3': 7, '4': 1, '5': 9, '10': 'viewId'}, + const {'1': 'data', '3': 8, '4': 1, '5': 9, '10': 'data'}, ], }; /// Descriptor for `CreateViewParams`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSJgoJdmlld190eXBlGAUgASgOMgkuVmlld1R5cGVSCHZpZXdUeXBlEhAKA2V4dBgGIAEoCVIDZXh0EhcKB3ZpZXdfaWQYByABKAlSBnZpZXdJZA=='); +final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIZCghleHRfZGF0YRgGIAEoCVIHZXh0RGF0YRIXCgd2aWV3X2lkGAcgASgJUgZ2aWV3SWQSEgoEZGF0YRgIIAEoCVIEZGF0YQ=='); @$core.Deprecated('Use viewIdDescriptor instead') const ViewId$json = const { '1': 'ViewId', diff --git a/frontend/rust-lib/flowy-document/src/queue.rs b/frontend/rust-lib/flowy-document/src/queue.rs index b23e486407..8ce74ce591 100644 --- a/frontend/rust-lib/flowy-document/src/queue.rs +++ b/frontend/rust-lib/flowy-document/src/queue.rs @@ -8,7 +8,7 @@ use flowy_collaboration::{ errors::CollaborateError, }; use flowy_error::{FlowyError, FlowyResult}; -use flowy_sync::{DeltaMD5, RevisionCompact, RevisionManager, TransformDeltas}; +use flowy_sync::{DeltaMD5, RevisionCompact, RevisionManager, RichTextTransformDeltas, TransformDeltas}; use futures::stream::StreamExt; use lib_ot::{ core::{Interval, OperationTransformable}, @@ -102,7 +102,7 @@ impl EditBlockQueue { server_prime = Some(s_prime); } drop(read_guard); - Ok::, CollaborateError>(TransformDeltas { + Ok::(TransformDeltas { client_prime, server_prime, }) @@ -232,7 +232,7 @@ pub(crate) enum EditorCommand { }, TransformDelta { delta: RichTextDelta, - ret: Ret>, + ret: Ret, }, Insert { index: usize, diff --git a/frontend/rust-lib/flowy-document/src/web_socket.rs b/frontend/rust-lib/flowy-document/src/web_socket.rs index a01e48789b..ee8db49cf4 100644 --- a/frontend/rust-lib/flowy-document/src/web_socket.rs +++ b/frontend/rust-lib/flowy-document/src/web_socket.rs @@ -10,7 +10,8 @@ use flowy_collaboration::{ use flowy_error::{internal_error, FlowyError}; use flowy_sync::*; use lib_infra::future::{BoxResultFuture, FutureResult}; -use lib_ot::{core::Delta, rich_text::RichTextAttributes}; +use lib_ot::rich_text::RichTextAttributes; +use lib_ot::rich_text::RichTextDelta; use lib_ws::WSConnectState; use std::{sync::Arc, time::Duration}; use tokio::sync::{ @@ -31,12 +32,8 @@ pub(crate) async fn make_block_ws_manager( ) -> Arc { let ws_data_provider = Arc::new(WSDataProvider::new(&doc_id, Arc::new(rev_manager.clone()))); let resolver = Arc::new(BlockConflictResolver { edit_cmd_tx }); - let conflict_controller = ConflictController::::new( - &user_id, - resolver, - Arc::new(ws_data_provider.clone()), - rev_manager, - ); + let conflict_controller = + RichTextConflictController::new(&user_id, resolver, Arc::new(ws_data_provider.clone()), rev_manager); let ws_data_stream = Arc::new(BlockRevisionWSDataStream::new(conflict_controller)); let ws_data_sink = Arc::new(BlockWSDataSink(ws_data_provider)); let ping_duration = Duration::from_millis(DOCUMENT_SYNC_INTERVAL_IN_MILLIS); @@ -66,11 +63,11 @@ fn listen_document_ws_state(_user_id: &str, _doc_id: &str, mut subscriber: broad } pub(crate) struct BlockRevisionWSDataStream { - conflict_controller: Arc>, + conflict_controller: Arc, } impl BlockRevisionWSDataStream { - pub fn new(conflict_controller: ConflictController) -> Self { + pub fn new(conflict_controller: RichTextConflictController) -> Self { Self { conflict_controller: Arc::new(conflict_controller), } @@ -112,7 +109,7 @@ struct BlockConflictResolver { } impl ConflictResolver for BlockConflictResolver { - fn compose_delta(&self, delta: Delta) -> BoxResultFuture { + fn compose_delta(&self, delta: RichTextDelta) -> BoxResultFuture { let tx = self.edit_cmd_tx.clone(); Box::pin(async move { let (ret, rx) = oneshot::channel(); @@ -131,11 +128,11 @@ impl ConflictResolver for BlockConflictResolver { fn transform_delta( &self, - delta: Delta, - ) -> BoxResultFuture, FlowyError> { + delta: RichTextDelta, + ) -> BoxResultFuture { let tx = self.edit_cmd_tx.clone(); Box::pin(async move { - let (ret, rx) = oneshot::channel::>>(); + let (ret, rx) = oneshot::channel::>(); tx.send(EditorCommand::TransformDelta { delta, ret }) .await .map_err(internal_error)?; @@ -146,7 +143,7 @@ impl ConflictResolver for BlockConflictResolver { }) } - fn reset_delta(&self, delta: Delta) -> BoxResultFuture { + fn reset_delta(&self, delta: RichTextDelta) -> BoxResultFuture { let tx = self.edit_cmd_tx.clone(); Box::pin(async move { let (ret, rx) = oneshot::channel(); diff --git a/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs b/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs index 985998498f..6f032964e8 100644 --- a/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs +++ b/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs @@ -12,7 +12,7 @@ use flowy_sync::{ RevisionWebSocket, RevisionWebSocketManager, }; use lib_infra::future::FutureResult; -use lib_ot::core::PlainAttributes; +use lib_ot::core::PlainTextAttributes; use lib_sqlite::ConnectionPool; use parking_lot::RwLock; use std::sync::Arc; @@ -144,7 +144,7 @@ impl RevisionCompact for FolderRevisionCompact { let (base_rev_id, rev_id) = first_revision.pair_rev_id(); let md5 = last_revision.md5.clone(); - let delta = make_delta_from_revisions::(revisions)?; + let delta = make_delta_from_revisions::(revisions)?; let delta_data = delta.to_bytes(); Ok(Revision::new(object_id, base_rev_id, rev_id, delta_data, user_id, md5)) } diff --git a/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs b/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs index a819629c95..50de4aa895 100644 --- a/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs +++ b/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs @@ -1,7 +1,7 @@ use crate::{ entities::{ trash::{Trash, TrashType}, - view::{RepeatedView, UpdateViewParams, View, ViewType}, + view::{RepeatedView, UpdateViewParams, View, ViewDataType}, }, errors::FlowyError, services::persistence::version_1::app_sql::AppTable, @@ -119,16 +119,16 @@ pub(crate) struct ViewTable { pub modified_time: i64, pub create_time: i64, pub thumbnail: String, - pub view_type: ViewTableType, + pub view_type: SqlViewDataType, pub version: i64, pub is_trash: bool, } impl ViewTable { pub fn new(view: View) -> Self { - let view_type = match view.view_type { - ViewType::RichText => ViewTableType::RichText, - ViewType::PlainText => ViewTableType::Text, + let data_type = match view.data_type { + ViewDataType::RichText => SqlViewDataType::RichText, + ViewDataType::PlainText => SqlViewDataType::PlainText, }; ViewTable { @@ -138,9 +138,8 @@ impl ViewTable { desc: view.desc, modified_time: view.modified_time, create_time: view.create_time, - // TODO: thumbnail - thumbnail: "".to_owned(), - view_type, + thumbnail: view.thumbnail, + view_type: data_type, version: 0, is_trash: false, } @@ -149,9 +148,9 @@ impl ViewTable { impl std::convert::From for View { fn from(table: ViewTable) -> Self { - let view_type = match table.view_type { - ViewTableType::RichText => ViewType::RichText, - ViewTableType::Text => ViewType::PlainText, + let data_type = match table.view_type { + SqlViewDataType::RichText => ViewDataType::RichText, + SqlViewDataType::PlainText => ViewDataType::PlainText, }; View { @@ -159,11 +158,13 @@ impl std::convert::From for View { belong_to_id: table.belong_to_id, name: table.name, desc: table.desc, - view_type, + data_type, belongings: RepeatedView::default(), modified_time: table.modified_time, version: table.version, create_time: table.create_time, + ext_data: "".to_string(), + thumbnail: table.thumbnail, } } } @@ -215,34 +216,34 @@ impl ViewChangeset { #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, FromSqlRow, AsExpression)] #[repr(i32)] #[sql_type = "Integer"] -pub enum ViewTableType { +pub enum SqlViewDataType { RichText = 0, - Text = 1, + PlainText = 1, } -impl std::default::Default for ViewTableType { +impl std::default::Default for SqlViewDataType { fn default() -> Self { - ViewTableType::RichText + SqlViewDataType::RichText } } -impl std::convert::From for ViewTableType { +impl std::convert::From for SqlViewDataType { fn from(value: i32) -> Self { match value { - 0 => ViewTableType::RichText, - 1 => ViewTableType::Text, + 0 => SqlViewDataType::RichText, + 1 => SqlViewDataType::PlainText, o => { log::error!("Unsupported view type {}, fallback to ViewType::Docs", o); - ViewTableType::Text + SqlViewDataType::PlainText } } } } -impl ViewTableType { +impl SqlViewDataType { pub fn value(&self) -> i32 { *self as i32 } } -impl_sql_integer_expression!(ViewTableType); +impl_sql_integer_expression!(SqlViewDataType); diff --git a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs index 748a27513b..80b2aa7094 100644 --- a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs +++ b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs @@ -24,7 +24,7 @@ use crate::{ use flowy_database::kv::KV; use flowy_document::BlockManager; use flowy_folder_data_model::entities::share::{ExportData, ExportParams}; -use flowy_folder_data_model::entities::view::ViewType; + use lib_infra::uuid_string; const LATEST_VIEW_ID: &str = "latest_view_id"; @@ -62,10 +62,10 @@ impl ViewController { #[tracing::instrument(level = "trace", skip(self, params), fields(name = %params.name), err)] pub(crate) async fn create_view_from_params(&self, params: CreateViewParams) -> Result { - let view_data = if params.ext.is_empty() { + let view_data = if params.data.is_empty() { initial_delta_string() } else { - params.ext.clone() + params.data.clone() }; let delta_data = Bytes::from(view_data); @@ -78,12 +78,11 @@ impl ViewController { Ok(view) } - #[tracing::instrument(level = "debug", skip(self, view_id, view_type, repeated_revision), err)] + #[tracing::instrument(level = "debug", skip(self, view_id, repeated_revision), err)] pub(crate) async fn create_view( &self, view_id: &str, repeated_revision: RepeatedRevision, - view_type: ViewType, ) -> Result<(), FlowyError> { if repeated_revision.is_empty() { return Err(FlowyError::internal().context("The content of the view should not be empty")); @@ -173,11 +172,12 @@ impl ViewController { let duplicate_params = CreateViewParams { belong_to_id: view.belong_to_id.clone(), name: format!("{} (copy)", &view.name), - desc: view.desc.clone(), - thumbnail: "".to_owned(), - view_type: view.view_type.clone(), - ext: document_json, + desc: view.desc, + thumbnail: view.thumbnail, + data_type: view.data_type, + data: document_json, view_id: uuid_string(), + ext_data: view.ext_data, }; let _ = self.create_view_from_params(duplicate_params).await?; diff --git a/frontend/rust-lib/flowy-folder/src/services/web_socket.rs b/frontend/rust-lib/flowy-folder/src/services/web_socket.rs index c3b20f9c87..438b3f52d3 100644 --- a/frontend/rust-lib/flowy-folder/src/services/web_socket.rs +++ b/frontend/rust-lib/flowy-folder/src/services/web_socket.rs @@ -10,7 +10,7 @@ use flowy_collaboration::{ use flowy_error::FlowyError; use flowy_sync::*; use lib_infra::future::{BoxResultFuture, FutureResult}; -use lib_ot::core::{Delta, OperationTransformable, PlainAttributes, PlainDelta}; +use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta}; use parking_lot::RwLock; use std::{sync::Arc, time::Duration}; @@ -23,8 +23,12 @@ pub(crate) async fn make_folder_ws_manager( ) -> Arc { let ws_data_provider = Arc::new(WSDataProvider::new(folder_id, Arc::new(rev_manager.clone()))); let resolver = Arc::new(FolderConflictResolver { folder_pad }); - let conflict_controller = - ConflictController::::new(user_id, resolver, Arc::new(ws_data_provider.clone()), rev_manager); + let conflict_controller = ConflictController::::new( + user_id, + resolver, + Arc::new(ws_data_provider.clone()), + rev_manager, + ); let ws_data_stream = Arc::new(FolderRevisionWSDataStream::new(conflict_controller)); let ws_data_sink = Arc::new(FolderWSDataSink(ws_data_provider)); let ping_duration = Duration::from_millis(FOLDER_SYNC_INTERVAL_IN_MILLIS); @@ -50,8 +54,8 @@ struct FolderConflictResolver { folder_pad: Arc>, } -impl ConflictResolver for FolderConflictResolver { - fn compose_delta(&self, delta: Delta) -> BoxResultFuture { +impl ConflictResolver for FolderConflictResolver { + fn compose_delta(&self, delta: PlainTextDelta) -> BoxResultFuture { let folder_pad = self.folder_pad.clone(); Box::pin(async move { let md5 = folder_pad.write().compose_remote_delta(delta)?; @@ -61,13 +65,13 @@ impl ConflictResolver for FolderConflictResolver { fn transform_delta( &self, - delta: Delta, - ) -> BoxResultFuture, FlowyError> { + delta: PlainTextDelta, + ) -> BoxResultFuture, FlowyError> { let folder_pad = self.folder_pad.clone(); Box::pin(async move { let read_guard = folder_pad.read(); - let mut server_prime: Option = None; - let client_prime: PlainDelta; + let mut server_prime: Option = None; + let client_prime: PlainTextDelta; if read_guard.is_empty() { // Do nothing client_prime = delta; @@ -84,7 +88,7 @@ impl ConflictResolver for FolderConflictResolver { }) } - fn reset_delta(&self, delta: Delta) -> BoxResultFuture { + fn reset_delta(&self, delta: PlainTextDelta) -> BoxResultFuture { let folder_pad = self.folder_pad.clone(); Box::pin(async move { let md5 = folder_pad.write().reset_folder(delta)?; @@ -94,11 +98,11 @@ impl ConflictResolver for FolderConflictResolver { } struct FolderRevisionWSDataStream { - conflict_controller: Arc>, + conflict_controller: Arc, } impl FolderRevisionWSDataStream { - pub fn new(conflict_controller: ConflictController) -> Self { + pub fn new(conflict_controller: PlainTextConflictController) -> Self { Self { conflict_controller: Arc::new(conflict_controller), } diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs b/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs index 09935c7248..241b359a9f 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs @@ -5,7 +5,7 @@ use flowy_folder_data_model::entities::workspace::WorkspaceId; use flowy_folder_data_model::entities::{ app::{App, AppId, CreateAppPayload, UpdateAppPayload}, trash::{RepeatedTrash, TrashId, TrashType}, - view::{CreateViewPayload, UpdateViewPayload, View, ViewType}, + view::{CreateViewPayload, UpdateViewPayload, View, ViewDataType}, workspace::{CreateWorkspacePayload, RepeatedWorkspace, Workspace}, }; use flowy_test::{event_builder::*, FlowySDKTest}; @@ -109,13 +109,14 @@ pub async fn delete_app(sdk: &FlowySDKTest, app_id: &str) { .await; } -pub async fn create_view(sdk: &FlowySDKTest, app_id: &str, name: &str, desc: &str, view_type: ViewType) -> View { +pub async fn create_view(sdk: &FlowySDKTest, app_id: &str, name: &str, desc: &str, view_type: ViewDataType) -> View { let request = CreateViewPayload { belong_to_id: app_id.to_string(), name: name.to_string(), desc: desc.to_string(), thumbnail: None, - view_type, + data_type: view_type, + ext_data: "".to_string(), }; let view = FolderEventBuilder::new(sdk.clone()) .event(CreateView) diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs index 70fa19eedd..d4f0fe0fd8 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs @@ -4,7 +4,7 @@ use flowy_folder::{errors::ErrorCode, services::folder_editor::ClientFolderEdito use flowy_folder_data_model::entities::{ app::{App, RepeatedApp}, trash::Trash, - view::{RepeatedView, View, ViewType}, + view::{RepeatedView, View, ViewDataType}, workspace::Workspace, }; use flowy_sync::REVISION_WRITE_INTERVAL_IN_MILLIS; @@ -68,7 +68,7 @@ impl FolderTest { let _ = sdk.init_user().await; let mut workspace = create_workspace(&sdk, "FolderWorkspace", "Folder test workspace").await; let mut app = create_app(&sdk, &workspace.id, "Folder App", "Folder test app").await; - let view = create_view(&sdk, &app.id, "Folder View", "Folder test view", ViewType::RichText).await; + let view = create_view(&sdk, &app.id, "Folder View", "Folder test view", ViewDataType::RichText).await; app.belongings = RepeatedView { items: vec![view.clone()], }; @@ -146,7 +146,7 @@ impl FolderTest { } FolderScript::CreateView { name, desc } => { - let view = create_view(sdk, &self.app.id, &name, &desc, ViewType::RichText).await; + let view = create_view(sdk, &self.app.id, &name, &desc, ViewDataType::RichText).await; self.view = view; } FolderScript::AssertView(view) => { diff --git a/frontend/rust-lib/flowy-net/src/local_server/server.rs b/frontend/rust-lib/flowy-net/src/local_server/server.rs index 363df41777..843c587a62 100644 --- a/frontend/rust-lib/flowy-net/src/local_server/server.rs +++ b/frontend/rust-lib/flowy-net/src/local_server/server.rs @@ -300,11 +300,13 @@ impl FolderCouldServiceV1 for LocalServer { belong_to_id: params.belong_to_id, name: params.name, desc: params.desc, - view_type: params.view_type, + data_type: params.data_type, version: 0, belongings: RepeatedView::default(), modified_time: time, create_time: time, + ext_data: params.ext_data, + thumbnail: params.thumbnail, }; FutureResult::new(async { Ok(view) }) } diff --git a/frontend/rust-lib/flowy-sync/src/conflict_resolve.rs b/frontend/rust-lib/flowy-sync/src/conflict_resolve.rs index ec3f897e54..817b77bd88 100644 --- a/frontend/rust-lib/flowy-sync/src/conflict_resolve.rs +++ b/frontend/rust-lib/flowy-sync/src/conflict_resolve.rs @@ -9,7 +9,8 @@ use flowy_collaboration::{ }; use flowy_error::{FlowyError, FlowyResult}; use lib_infra::future::BoxResultFuture; -use lib_ot::core::{Attributes, Delta}; +use lib_ot::core::{Attributes, Delta, PlainTextAttributes}; +use lib_ot::rich_text::RichTextAttributes; use serde::de::DeserializeOwned; use std::{convert::TryFrom, sync::Arc}; @@ -29,6 +30,9 @@ pub trait ConflictRevisionSink: Send + Sync + 'static { fn ack(&self, rev_id: String, ty: ServerRevisionWSDataType) -> BoxResultFuture<(), FlowyError>; } +pub type RichTextConflictController = ConflictController; +pub type PlainTextConflictController = ConflictController; + pub struct ConflictController where T: Attributes + Send + Sync, @@ -171,6 +175,8 @@ where } } +pub type RichTextTransformDeltas = TransformDeltas; + pub struct TransformDeltas where T: Attributes, diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index 6f87c226cd..4cb4a5e815 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -88,7 +88,8 @@ async fn create_view(sdk: &FlowySDKTest, app_id: &str) -> View { name: "View A".to_string(), desc: "".to_string(), thumbnail: Some("http://1.png".to_string()), - view_type: ViewType::RichText, + data_type: ViewDataType::RichText, + ext_data: "".to_string(), }; let view = FolderEventBuilder::new(sdk.clone()) diff --git a/shared-lib/flowy-collaboration/src/client_folder/builder.rs b/shared-lib/flowy-collaboration/src/client_folder/builder.rs index ef44e0adc6..437977789f 100644 --- a/shared-lib/flowy-collaboration/src/client_folder/builder.rs +++ b/shared-lib/flowy-collaboration/src/client_folder/builder.rs @@ -6,7 +6,7 @@ use crate::{ errors::{CollaborateError, CollaborateResult}, }; use flowy_folder_data_model::entities::{trash::Trash, workspace::Workspace}; -use lib_ot::core::{PlainAttributes, PlainDelta, PlainDeltaBuilder}; +use lib_ot::core::{PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder}; use serde::{Deserialize, Serialize}; use std::sync::Arc; @@ -34,7 +34,7 @@ impl FolderPadBuilder { self } - pub(crate) fn build_with_delta(self, mut delta: PlainDelta) -> CollaborateResult { + pub(crate) fn build_with_delta(self, mut delta: PlainTextDelta) -> CollaborateResult { if delta.is_empty() { delta = default_folder_delta(); } @@ -47,7 +47,7 @@ impl FolderPadBuilder { } pub(crate) fn build_with_revisions(self, revisions: Vec) -> CollaborateResult { - let folder_delta: FolderDelta = make_delta_from_revisions::(revisions)?; + let folder_delta: FolderDelta = make_delta_from_revisions::(revisions)?; self.build_with_delta(folder_delta) } @@ -57,7 +57,7 @@ impl FolderPadBuilder { Ok(FolderPad { workspaces: self.workspaces, trash: self.trash, - root: PlainDeltaBuilder::new().insert(&json).build(), + root: PlainTextDeltaBuilder::new().insert(&json).build(), }) } } diff --git a/shared-lib/flowy-collaboration/src/client_folder/folder_pad.rs b/shared-lib/flowy-collaboration/src/client_folder/folder_pad.rs index 4284a4875b..6e28ede769 100644 --- a/shared-lib/flowy-collaboration/src/client_folder/folder_pad.rs +++ b/shared-lib/flowy-collaboration/src/client_folder/folder_pad.rs @@ -8,7 +8,7 @@ use crate::{ }; use dissimilar::*; use flowy_folder_data_model::entities::{app::App, trash::Trash, view::View, workspace::Workspace}; -use lib_ot::core::{Delta, FlowyStr, OperationTransformable, PlainAttributes, PlainDeltaBuilder}; +use lib_ot::core::{FlowyStr, OperationTransformable, PlainTextDelta, PlainTextDeltaBuilder}; use serde::{Deserialize, Serialize}; use std::sync::Arc; @@ -21,7 +21,7 @@ pub struct FolderPad { } pub fn default_folder_delta() -> FolderDelta { - PlainDeltaBuilder::new() + PlainTextDeltaBuilder::new() .insert(r#"{"workspaces":[],"trash":[]}"#) .build() } @@ -385,9 +385,9 @@ impl FolderPad { } } -fn cal_diff(old: String, new: String) -> Delta { +fn cal_diff(old: String, new: String) -> PlainTextDelta { let chunks = dissimilar::diff(&old, &new); - let mut delta_builder = PlainDeltaBuilder::new(); + let mut delta_builder = PlainTextDeltaBuilder::new(); for chunk in &chunks { match chunk { Chunk::Equal(s) => { @@ -410,7 +410,7 @@ mod tests { use crate::{client_folder::folder_pad::FolderPad, entities::folder_info::FolderDelta}; use chrono::Utc; use flowy_folder_data_model::entities::{app::App, trash::Trash, view::View, workspace::Workspace}; - use lib_ot::core::{OperationTransformable, PlainDelta, PlainDeltaBuilder}; + use lib_ot::core::{OperationTransformable, PlainTextDelta, PlainTextDeltaBuilder}; #[test] fn folder_add_workspace() { @@ -725,7 +725,7 @@ mod tests { fn test_folder() -> (FolderPad, FolderDelta, Workspace) { let mut folder = FolderPad::default(); let folder_json = serde_json::to_string(&folder).unwrap(); - let mut delta = PlainDeltaBuilder::new().insert(&folder_json).build(); + let mut delta = PlainTextDeltaBuilder::new().insert(&folder_json).build(); let mut workspace = Workspace::default(); workspace.name = "😁 my first workspace".to_owned(); @@ -767,7 +767,7 @@ mod tests { fn test_trash() -> (FolderPad, FolderDelta, Trash) { let mut folder = FolderPad::default(); let folder_json = serde_json::to_string(&folder).unwrap(); - let mut delta = PlainDeltaBuilder::new().insert(&folder_json).build(); + let mut delta = PlainTextDeltaBuilder::new().insert(&folder_json).build(); let mut trash = Trash::default(); trash.name = "🚽 my first trash".to_owned(); @@ -780,7 +780,7 @@ mod tests { (folder, delta, trash) } - fn make_folder_from_delta(mut initial_delta: FolderDelta, deltas: Vec) -> FolderPad { + fn make_folder_from_delta(mut initial_delta: FolderDelta, deltas: Vec) -> FolderPad { for delta in deltas { initial_delta = initial_delta.compose(&delta).unwrap(); } diff --git a/shared-lib/flowy-collaboration/src/entities/folder_info.rs b/shared-lib/flowy-collaboration/src/entities/folder_info.rs index 7b3d330eb0..214190f517 100644 --- a/shared-lib/flowy-collaboration/src/entities/folder_info.rs +++ b/shared-lib/flowy-collaboration/src/entities/folder_info.rs @@ -1,7 +1,7 @@ use flowy_derive::ProtoBuf; -use lib_ot::core::PlainDelta; +use lib_ot::core::PlainTextDelta; -pub type FolderDelta = PlainDelta; +pub type FolderDelta = PlainTextDelta; #[derive(ProtoBuf, Default, Debug, Clone, Eq, PartialEq)] pub struct FolderInfo { diff --git a/shared-lib/flowy-collaboration/src/server_folder/folder_manager.rs b/shared-lib/flowy-collaboration/src/server_folder/folder_manager.rs index b81cb7fb91..96b7cb71cb 100644 --- a/shared-lib/flowy-collaboration/src/server_folder/folder_manager.rs +++ b/shared-lib/flowy-collaboration/src/server_folder/folder_manager.rs @@ -12,7 +12,7 @@ use crate::{ use async_stream::stream; use futures::stream::StreamExt; use lib_infra::future::BoxResultFuture; -use lib_ot::core::PlainAttributes; +use lib_ot::core::PlainTextAttributes; use std::{collections::HashMap, fmt::Debug, sync::Arc}; use tokio::{ sync::{mpsc, oneshot, RwLock}, @@ -187,7 +187,7 @@ impl ServerFolderManager { } } -type FolderRevisionSynchronizer = RevisionSynchronizer; +type FolderRevisionSynchronizer = RevisionSynchronizer; struct OpenFolderHandler { folder_id: String, diff --git a/shared-lib/flowy-collaboration/src/server_folder/folder_pad.rs b/shared-lib/flowy-collaboration/src/server_folder/folder_pad.rs index 811974ae44..a7c4746fea 100644 --- a/shared-lib/flowy-collaboration/src/server_folder/folder_pad.rs +++ b/shared-lib/flowy-collaboration/src/server_folder/folder_pad.rs @@ -1,5 +1,5 @@ use crate::{entities::folder_info::FolderDelta, errors::CollaborateError, synchronizer::RevisionSyncObject}; -use lib_ot::core::{Delta, OperationTransformable, PlainAttributes}; +use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta}; pub struct ServerFolder { folder_id: String, @@ -15,21 +15,18 @@ impl ServerFolder { } } -impl RevisionSyncObject for ServerFolder { +impl RevisionSyncObject for ServerFolder { fn id(&self) -> &str { &self.folder_id } - fn compose(&mut self, other: &Delta) -> Result<(), CollaborateError> { + fn compose(&mut self, other: &PlainTextDelta) -> Result<(), CollaborateError> { let new_delta = self.delta.compose(other)?; self.delta = new_delta; Ok(()) } - fn transform( - &self, - other: &Delta, - ) -> Result<(Delta, Delta), CollaborateError> { + fn transform(&self, other: &PlainTextDelta) -> Result<(PlainTextDelta, PlainTextDelta), CollaborateError> { let value = self.delta.transform(other)?; Ok(value) } @@ -38,7 +35,7 @@ impl RevisionSyncObject for ServerFolder { self.delta.to_json() } - fn set_delta(&mut self, new_delta: Delta) { + fn set_delta(&mut self, new_delta: PlainTextDelta) { self.delta = new_delta; } } diff --git a/shared-lib/flowy-folder-data-model/src/entities/view.rs b/shared-lib/flowy-folder-data-model/src/entities/view.rs index 0a6b03a41d..26a7d2938b 100644 --- a/shared-lib/flowy-folder-data-model/src/entities/view.rs +++ b/shared-lib/flowy-folder-data-model/src/entities/view.rs @@ -28,7 +28,8 @@ pub struct View { pub desc: String, #[pb(index = 5)] - pub view_type: ViewType, + #[serde(default)] + pub data_type: ViewDataType, #[pb(index = 6)] pub version: i64, @@ -41,6 +42,12 @@ pub struct View { #[pb(index = 9)] pub create_time: i64, + + #[pb(index = 10)] + pub ext_data: String, + + #[pb(index = 11)] + pub thumbnail: String, } #[derive(Eq, PartialEq, Debug, Default, ProtoBuf, Clone, Serialize, Deserialize)] @@ -65,25 +72,25 @@ impl std::convert::From for Trash { } #[derive(Eq, PartialEq, Debug, ProtoBuf_Enum, Clone, Serialize)] -pub enum ViewType { +pub enum ViewDataType { RichText = 0, PlainText = 1, } -impl std::default::Default for ViewType { +impl std::default::Default for ViewDataType { fn default() -> Self { - ViewType::PlainText + ViewDataType::PlainText } } -impl std::convert::From for ViewType { +impl std::convert::From for ViewDataType { fn from(val: i32) -> Self { match val { - 0 => ViewType::RichText, - 1 => ViewType::PlainText, + 0 => ViewDataType::RichText, + 1 => ViewDataType::PlainText, _ => { log::error!("Invalid view type: {}", val); - ViewType::PlainText + ViewDataType::PlainText } } } @@ -104,10 +111,10 @@ pub struct CreateViewPayload { pub thumbnail: Option, #[pb(index = 5)] - pub view_type: ViewType, + pub data_type: ViewDataType, #[pb(index = 6)] - pub ext: String, + pub ext_data: String, } #[derive(Default, ProtoBuf, Debug, Clone)] @@ -125,35 +132,16 @@ pub struct CreateViewParams { pub thumbnail: String, #[pb(index = 5)] - pub view_type: ViewType, + pub data_type: ViewDataType, #[pb(index = 6)] - pub ext: String, + pub ext_data: String, #[pb(index = 7)] pub view_id: String, -} -impl CreateViewParams { - pub fn new( - belong_to_id: String, - name: String, - desc: String, - view_type: ViewType, - thumbnail: String, - ext: String, - view_id: String, - ) -> Self { - Self { - belong_to_id, - name, - desc, - thumbnail, - view_type, - ext, - view_id, - } - } + #[pb(index = 8)] + pub data: String, } impl TryInto for CreateViewPayload { @@ -163,21 +151,22 @@ impl TryInto for CreateViewPayload { let name = ViewName::parse(self.name)?.0; let belong_to_id = AppIdentify::parse(self.belong_to_id)?.0; let view_id = uuid::Uuid::new_v4().to_string(); - let ext = ViewExtensionData::parse(self.ext)?.0; + let ext_data = ViewExtensionData::parse(self.ext_data)?.0; let thumbnail = match self.thumbnail { None => "".to_string(), Some(thumbnail) => ViewThumbnail::parse(thumbnail)?.0, }; - Ok(CreateViewParams::new( + Ok(CreateViewParams { belong_to_id, name, - self.desc, - self.view_type, + desc: self.desc, + data_type: self.data_type, thumbnail, - ext, + ext_data, view_id, - )) + data: "".to_string(), + }) } } @@ -280,7 +269,7 @@ impl TryInto for UpdateViewPayload { } } -impl<'de> Deserialize<'de> for ViewType { +impl<'de> Deserialize<'de> for ViewDataType { fn deserialize(deserializer: D) -> Result>::Error> where D: Deserializer<'de>, @@ -288,7 +277,7 @@ impl<'de> Deserialize<'de> for ViewType { struct ViewTypeVisitor(); impl<'de> Visitor<'de> for ViewTypeVisitor { - type Value = ViewType; + type Value = ViewDataType; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { formatter.write_str("Plugin, RichText") } @@ -301,10 +290,10 @@ impl<'de> Deserialize<'de> for ViewType { match s { "Doc" | "RichText" => { // Rename ViewType::Doc to ViewType::RichText, So we need to migrate the ViewType manually. - view_type = ViewType::RichText; + view_type = ViewDataType::RichText; } "Plugin" => { - view_type = ViewType::PlainText; + view_type = ViewDataType::PlainText; } unknown => { return Err(de::Error::invalid_value(Unexpected::Str(unknown), &self)); diff --git a/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs b/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs index 9fefa85482..b1900de3dd 100644 --- a/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs +++ b/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs @@ -30,11 +30,13 @@ pub struct View { pub belong_to_id: ::std::string::String, pub name: ::std::string::String, pub desc: ::std::string::String, - pub view_type: ViewType, + pub data_type: ViewDataType, pub version: i64, pub belongings: ::protobuf::SingularPtrField, pub modified_time: i64, pub create_time: i64, + pub ext_data: ::std::string::String, + pub thumbnail: ::std::string::String, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -155,19 +157,19 @@ impl View { ::std::mem::replace(&mut self.desc, ::std::string::String::new()) } - // .ViewType view_type = 5; + // .ViewDataType data_type = 5; - pub fn get_view_type(&self) -> ViewType { - self.view_type + pub fn get_data_type(&self) -> ViewDataType { + self.data_type } - pub fn clear_view_type(&mut self) { - self.view_type = ViewType::RichText; + pub fn clear_data_type(&mut self) { + self.data_type = ViewDataType::RichText; } // Param is passed by value, moved - pub fn set_view_type(&mut self, v: ViewType) { - self.view_type = v; + pub fn set_data_type(&mut self, v: ViewDataType) { + self.data_type = v; } // int64 version = 6; @@ -247,6 +249,58 @@ impl View { pub fn set_create_time(&mut self, v: i64) { self.create_time = v; } + + // string ext_data = 10; + + + pub fn get_ext_data(&self) -> &str { + &self.ext_data + } + pub fn clear_ext_data(&mut self) { + self.ext_data.clear(); + } + + // Param is passed by value, moved + pub fn set_ext_data(&mut self, v: ::std::string::String) { + self.ext_data = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_ext_data(&mut self) -> &mut ::std::string::String { + &mut self.ext_data + } + + // Take field + pub fn take_ext_data(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.ext_data, ::std::string::String::new()) + } + + // string thumbnail = 11; + + + pub fn get_thumbnail(&self) -> &str { + &self.thumbnail + } + pub fn clear_thumbnail(&mut self) { + self.thumbnail.clear(); + } + + // Param is passed by value, moved + pub fn set_thumbnail(&mut self, v: ::std::string::String) { + self.thumbnail = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_thumbnail(&mut self) -> &mut ::std::string::String { + &mut self.thumbnail + } + + // Take field + pub fn take_thumbnail(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.thumbnail, ::std::string::String::new()) + } } impl ::protobuf::Message for View { @@ -276,7 +330,7 @@ impl ::protobuf::Message for View { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.desc)?; }, 5 => { - ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.view_type, 5, &mut self.unknown_fields)? + ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.data_type, 5, &mut self.unknown_fields)? }, 6 => { if wire_type != ::protobuf::wire_format::WireTypeVarint { @@ -302,6 +356,12 @@ impl ::protobuf::Message for View { let tmp = is.read_int64()?; self.create_time = tmp; }, + 10 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.ext_data)?; + }, + 11 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.thumbnail)?; + }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; }, @@ -326,8 +386,8 @@ impl ::protobuf::Message for View { if !self.desc.is_empty() { my_size += ::protobuf::rt::string_size(4, &self.desc); } - if self.view_type != ViewType::RichText { - my_size += ::protobuf::rt::enum_size(5, self.view_type); + if self.data_type != ViewDataType::RichText { + my_size += ::protobuf::rt::enum_size(5, self.data_type); } if self.version != 0 { my_size += ::protobuf::rt::value_size(6, self.version, ::protobuf::wire_format::WireTypeVarint); @@ -342,6 +402,12 @@ impl ::protobuf::Message for View { if self.create_time != 0 { my_size += ::protobuf::rt::value_size(9, self.create_time, ::protobuf::wire_format::WireTypeVarint); } + if !self.ext_data.is_empty() { + my_size += ::protobuf::rt::string_size(10, &self.ext_data); + } + if !self.thumbnail.is_empty() { + my_size += ::protobuf::rt::string_size(11, &self.thumbnail); + } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); my_size @@ -360,8 +426,8 @@ impl ::protobuf::Message for View { if !self.desc.is_empty() { os.write_string(4, &self.desc)?; } - if self.view_type != ViewType::RichText { - os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.view_type))?; + if self.data_type != ViewDataType::RichText { + os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.data_type))?; } if self.version != 0 { os.write_int64(6, self.version)?; @@ -377,6 +443,12 @@ impl ::protobuf::Message for View { if self.create_time != 0 { os.write_int64(9, self.create_time)?; } + if !self.ext_data.is_empty() { + os.write_string(10, &self.ext_data)?; + } + if !self.thumbnail.is_empty() { + os.write_string(11, &self.thumbnail)?; + } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) } @@ -435,10 +507,10 @@ impl ::protobuf::Message for View { |m: &View| { &m.desc }, |m: &mut View| { &mut m.desc }, )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( - "view_type", - |m: &View| { &m.view_type }, - |m: &mut View| { &mut m.view_type }, + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( + "data_type", + |m: &View| { &m.data_type }, + |m: &mut View| { &mut m.data_type }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt64>( "version", @@ -460,6 +532,16 @@ impl ::protobuf::Message for View { |m: &View| { &m.create_time }, |m: &mut View| { &mut m.create_time }, )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "ext_data", + |m: &View| { &m.ext_data }, + |m: &mut View| { &mut m.ext_data }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "thumbnail", + |m: &View| { &m.thumbnail }, + |m: &mut View| { &mut m.thumbnail }, + )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "View", fields, @@ -480,11 +562,13 @@ impl ::protobuf::Clear for View { self.belong_to_id.clear(); self.name.clear(); self.desc.clear(); - self.view_type = ViewType::RichText; + self.data_type = ViewDataType::RichText; self.version = 0; self.belongings.clear(); self.modified_time = 0; self.create_time = 0; + self.ext_data.clear(); + self.thumbnail.clear(); self.unknown_fields.clear(); } } @@ -673,8 +757,8 @@ pub struct CreateViewPayload { pub belong_to_id: ::std::string::String, pub name: ::std::string::String, pub desc: ::std::string::String, - pub view_type: ViewType, - pub ext: ::std::string::String, + pub data_type: ViewDataType, + pub ext_data: ::std::string::String, // message oneof groups pub one_of_thumbnail: ::std::option::Option, // special fields @@ -825,45 +909,45 @@ impl CreateViewPayload { } } - // .ViewType view_type = 5; + // .ViewDataType data_type = 5; - pub fn get_view_type(&self) -> ViewType { - self.view_type + pub fn get_data_type(&self) -> ViewDataType { + self.data_type } - pub fn clear_view_type(&mut self) { - self.view_type = ViewType::RichText; + pub fn clear_data_type(&mut self) { + self.data_type = ViewDataType::RichText; } // Param is passed by value, moved - pub fn set_view_type(&mut self, v: ViewType) { - self.view_type = v; + pub fn set_data_type(&mut self, v: ViewDataType) { + self.data_type = v; } - // string ext = 6; + // string ext_data = 6; - pub fn get_ext(&self) -> &str { - &self.ext + pub fn get_ext_data(&self) -> &str { + &self.ext_data } - pub fn clear_ext(&mut self) { - self.ext.clear(); + pub fn clear_ext_data(&mut self) { + self.ext_data.clear(); } // Param is passed by value, moved - pub fn set_ext(&mut self, v: ::std::string::String) { - self.ext = v; + pub fn set_ext_data(&mut self, v: ::std::string::String) { + self.ext_data = v; } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_ext(&mut self) -> &mut ::std::string::String { - &mut self.ext + pub fn mut_ext_data(&mut self) -> &mut ::std::string::String { + &mut self.ext_data } // Take field - pub fn take_ext(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.ext, ::std::string::String::new()) + pub fn take_ext_data(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.ext_data, ::std::string::String::new()) } } @@ -892,10 +976,10 @@ impl ::protobuf::Message for CreateViewPayload { self.one_of_thumbnail = ::std::option::Option::Some(CreateViewPayload_oneof_one_of_thumbnail::thumbnail(is.read_string()?)); }, 5 => { - ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.view_type, 5, &mut self.unknown_fields)? + ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.data_type, 5, &mut self.unknown_fields)? }, 6 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.ext)?; + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.ext_data)?; }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -918,11 +1002,11 @@ impl ::protobuf::Message for CreateViewPayload { if !self.desc.is_empty() { my_size += ::protobuf::rt::string_size(3, &self.desc); } - if self.view_type != ViewType::RichText { - my_size += ::protobuf::rt::enum_size(5, self.view_type); + if self.data_type != ViewDataType::RichText { + my_size += ::protobuf::rt::enum_size(5, self.data_type); } - if !self.ext.is_empty() { - my_size += ::protobuf::rt::string_size(6, &self.ext); + if !self.ext_data.is_empty() { + my_size += ::protobuf::rt::string_size(6, &self.ext_data); } if let ::std::option::Option::Some(ref v) = self.one_of_thumbnail { match v { @@ -946,11 +1030,11 @@ impl ::protobuf::Message for CreateViewPayload { if !self.desc.is_empty() { os.write_string(3, &self.desc)?; } - if self.view_type != ViewType::RichText { - os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.view_type))?; + if self.data_type != ViewDataType::RichText { + os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.data_type))?; } - if !self.ext.is_empty() { - os.write_string(6, &self.ext)?; + if !self.ext_data.is_empty() { + os.write_string(6, &self.ext_data)?; } if let ::std::option::Option::Some(ref v) = self.one_of_thumbnail { match v { @@ -1017,15 +1101,15 @@ impl ::protobuf::Message for CreateViewPayload { CreateViewPayload::has_thumbnail, CreateViewPayload::get_thumbnail, )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( - "view_type", - |m: &CreateViewPayload| { &m.view_type }, - |m: &mut CreateViewPayload| { &mut m.view_type }, + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( + "data_type", + |m: &CreateViewPayload| { &m.data_type }, + |m: &mut CreateViewPayload| { &mut m.data_type }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "ext", - |m: &CreateViewPayload| { &m.ext }, - |m: &mut CreateViewPayload| { &mut m.ext }, + "ext_data", + |m: &CreateViewPayload| { &m.ext_data }, + |m: &mut CreateViewPayload| { &mut m.ext_data }, )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "CreateViewPayload", @@ -1047,8 +1131,8 @@ impl ::protobuf::Clear for CreateViewPayload { self.name.clear(); self.desc.clear(); self.one_of_thumbnail = ::std::option::Option::None; - self.view_type = ViewType::RichText; - self.ext.clear(); + self.data_type = ViewDataType::RichText; + self.ext_data.clear(); self.unknown_fields.clear(); } } @@ -1072,9 +1156,10 @@ pub struct CreateViewParams { pub name: ::std::string::String, pub desc: ::std::string::String, pub thumbnail: ::std::string::String, - pub view_type: ViewType, - pub ext: ::std::string::String, + pub data_type: ViewDataType, + pub ext_data: ::std::string::String, pub view_id: ::std::string::String, + pub data: ::std::string::String, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -1195,45 +1280,45 @@ impl CreateViewParams { ::std::mem::replace(&mut self.thumbnail, ::std::string::String::new()) } - // .ViewType view_type = 5; + // .ViewDataType data_type = 5; - pub fn get_view_type(&self) -> ViewType { - self.view_type + pub fn get_data_type(&self) -> ViewDataType { + self.data_type } - pub fn clear_view_type(&mut self) { - self.view_type = ViewType::RichText; + pub fn clear_data_type(&mut self) { + self.data_type = ViewDataType::RichText; } // Param is passed by value, moved - pub fn set_view_type(&mut self, v: ViewType) { - self.view_type = v; + pub fn set_data_type(&mut self, v: ViewDataType) { + self.data_type = v; } - // string ext = 6; + // string ext_data = 6; - pub fn get_ext(&self) -> &str { - &self.ext + pub fn get_ext_data(&self) -> &str { + &self.ext_data } - pub fn clear_ext(&mut self) { - self.ext.clear(); + pub fn clear_ext_data(&mut self) { + self.ext_data.clear(); } // Param is passed by value, moved - pub fn set_ext(&mut self, v: ::std::string::String) { - self.ext = v; + pub fn set_ext_data(&mut self, v: ::std::string::String) { + self.ext_data = v; } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_ext(&mut self) -> &mut ::std::string::String { - &mut self.ext + pub fn mut_ext_data(&mut self) -> &mut ::std::string::String { + &mut self.ext_data } // Take field - pub fn take_ext(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.ext, ::std::string::String::new()) + pub fn take_ext_data(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.ext_data, ::std::string::String::new()) } // string view_id = 7; @@ -1261,6 +1346,32 @@ impl CreateViewParams { pub fn take_view_id(&mut self) -> ::std::string::String { ::std::mem::replace(&mut self.view_id, ::std::string::String::new()) } + + // string data = 8; + + + pub fn get_data(&self) -> &str { + &self.data + } + pub fn clear_data(&mut self) { + self.data.clear(); + } + + // Param is passed by value, moved + pub fn set_data(&mut self, v: ::std::string::String) { + self.data = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_data(&mut self) -> &mut ::std::string::String { + &mut self.data + } + + // Take field + pub fn take_data(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.data, ::std::string::String::new()) + } } impl ::protobuf::Message for CreateViewParams { @@ -1285,14 +1396,17 @@ impl ::protobuf::Message for CreateViewParams { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.thumbnail)?; }, 5 => { - ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.view_type, 5, &mut self.unknown_fields)? + ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.data_type, 5, &mut self.unknown_fields)? }, 6 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.ext)?; + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.ext_data)?; }, 7 => { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.view_id)?; }, + 8 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?; + }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; }, @@ -1317,15 +1431,18 @@ impl ::protobuf::Message for CreateViewParams { if !self.thumbnail.is_empty() { my_size += ::protobuf::rt::string_size(4, &self.thumbnail); } - if self.view_type != ViewType::RichText { - my_size += ::protobuf::rt::enum_size(5, self.view_type); + if self.data_type != ViewDataType::RichText { + my_size += ::protobuf::rt::enum_size(5, self.data_type); } - if !self.ext.is_empty() { - my_size += ::protobuf::rt::string_size(6, &self.ext); + if !self.ext_data.is_empty() { + my_size += ::protobuf::rt::string_size(6, &self.ext_data); } if !self.view_id.is_empty() { my_size += ::protobuf::rt::string_size(7, &self.view_id); } + if !self.data.is_empty() { + my_size += ::protobuf::rt::string_size(8, &self.data); + } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); my_size @@ -1344,15 +1461,18 @@ impl ::protobuf::Message for CreateViewParams { if !self.thumbnail.is_empty() { os.write_string(4, &self.thumbnail)?; } - if self.view_type != ViewType::RichText { - os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.view_type))?; + if self.data_type != ViewDataType::RichText { + os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.data_type))?; } - if !self.ext.is_empty() { - os.write_string(6, &self.ext)?; + if !self.ext_data.is_empty() { + os.write_string(6, &self.ext_data)?; } if !self.view_id.is_empty() { os.write_string(7, &self.view_id)?; } + if !self.data.is_empty() { + os.write_string(8, &self.data)?; + } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) } @@ -1411,21 +1531,26 @@ impl ::protobuf::Message for CreateViewParams { |m: &CreateViewParams| { &m.thumbnail }, |m: &mut CreateViewParams| { &mut m.thumbnail }, )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( - "view_type", - |m: &CreateViewParams| { &m.view_type }, - |m: &mut CreateViewParams| { &mut m.view_type }, + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( + "data_type", + |m: &CreateViewParams| { &m.data_type }, + |m: &mut CreateViewParams| { &mut m.data_type }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "ext", - |m: &CreateViewParams| { &m.ext }, - |m: &mut CreateViewParams| { &mut m.ext }, + "ext_data", + |m: &CreateViewParams| { &m.ext_data }, + |m: &mut CreateViewParams| { &mut m.ext_data }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "view_id", |m: &CreateViewParams| { &m.view_id }, |m: &mut CreateViewParams| { &mut m.view_id }, )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "data", + |m: &CreateViewParams| { &m.data }, + |m: &mut CreateViewParams| { &mut m.data }, + )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "CreateViewParams", fields, @@ -1446,9 +1571,10 @@ impl ::protobuf::Clear for CreateViewParams { self.name.clear(); self.desc.clear(); self.thumbnail.clear(); - self.view_type = ViewType::RichText; - self.ext.clear(); + self.data_type = ViewDataType::RichText; + self.ext_data.clear(); self.view_id.clear(); + self.data.clear(); self.unknown_fields.clear(); } } @@ -2589,28 +2715,28 @@ impl ::protobuf::reflect::ProtobufValue for UpdateViewParams { } #[derive(Clone,PartialEq,Eq,Debug,Hash)] -pub enum ViewType { +pub enum ViewDataType { RichText = 0, PlainText = 1, } -impl ::protobuf::ProtobufEnum for ViewType { +impl ::protobuf::ProtobufEnum for ViewDataType { fn value(&self) -> i32 { *self as i32 } - fn from_i32(value: i32) -> ::std::option::Option { + fn from_i32(value: i32) -> ::std::option::Option { match value { - 0 => ::std::option::Option::Some(ViewType::RichText), - 1 => ::std::option::Option::Some(ViewType::PlainText), + 0 => ::std::option::Option::Some(ViewDataType::RichText), + 1 => ::std::option::Option::Some(ViewDataType::PlainText), _ => ::std::option::Option::None } } fn values() -> &'static [Self] { - static values: &'static [ViewType] = &[ - ViewType::RichText, - ViewType::PlainText, + static values: &'static [ViewDataType] = &[ + ViewDataType::RichText, + ViewDataType::PlainText, ]; values } @@ -2618,58 +2744,61 @@ impl ::protobuf::ProtobufEnum for ViewType { fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor { static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT; descriptor.get(|| { - ::protobuf::reflect::EnumDescriptor::new_pb_name::("ViewType", file_descriptor_proto()) + ::protobuf::reflect::EnumDescriptor::new_pb_name::("ViewDataType", file_descriptor_proto()) }) } } -impl ::std::marker::Copy for ViewType { +impl ::std::marker::Copy for ViewDataType { } -impl ::std::default::Default for ViewType { +impl ::std::default::Default for ViewDataType { fn default() -> Self { - ViewType::RichText + ViewDataType::RichText } } -impl ::protobuf::reflect::ProtobufValue for ViewType { +impl ::protobuf::reflect::ProtobufValue for ViewDataType { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self)) } } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\nview.proto\"\x97\x02\n\x04View\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\ + \n\nview.proto\"\xd4\x02\n\x04View\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\ \x02id\x12\x20\n\x0cbelong_to_id\x18\x02\x20\x01(\tR\nbelongToId\x12\x12\ \n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x04\x20\x01\ - (\tR\x04desc\x12&\n\tview_type\x18\x05\x20\x01(\x0e2\t.ViewTypeR\x08view\ - Type\x12\x18\n\x07version\x18\x06\x20\x01(\x03R\x07version\x12-\n\nbelon\ - gings\x18\x07\x20\x01(\x0b2\r.RepeatedViewR\nbelongings\x12#\n\rmodified\ - _time\x18\x08\x20\x01(\x03R\x0cmodifiedTime\x12\x1f\n\x0bcreate_time\x18\ - \t\x20\x01(\x03R\ncreateTime\"+\n\x0cRepeatedView\x12\x1b\n\x05items\x18\ - \x01\x20\x03(\x0b2\x05.ViewR\x05items\"\xcb\x01\n\x11CreateViewPayload\ - \x12\x20\n\x0cbelong_to_id\x18\x01\x20\x01(\tR\nbelongToId\x12\x12\n\x04\ - name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\ - \x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\0R\tthumbnail\x12&\n\t\ - view_type\x18\x05\x20\x01(\x0e2\t.ViewTypeR\x08viewType\x12\x10\n\x03ext\ - \x18\x06\x20\x01(\tR\x03extB\x12\n\x10one_of_thumbnail\"\xcd\x01\n\x10Cr\ - eateViewParams\x12\x20\n\x0cbelong_to_id\x18\x01\x20\x01(\tR\nbelongToId\ - \x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\ - \x20\x01(\tR\x04desc\x12\x1c\n\tthumbnail\x18\x04\x20\x01(\tR\tthumbnail\ - \x12&\n\tview_type\x18\x05\x20\x01(\x0e2\t.ViewTypeR\x08viewType\x12\x10\ - \n\x03ext\x18\x06\x20\x01(\tR\x03ext\x12\x17\n\x07view_id\x18\x07\x20\ - \x01(\tR\x06viewId\"\x1e\n\x06ViewId\x12\x14\n\x05value\x18\x01\x20\x01(\ - \tR\x05value\"&\n\x0eRepeatedViewId\x12\x14\n\x05items\x18\x01\x20\x03(\ - \tR\x05items\"\xaa\x01\n\x11UpdateViewPayload\x12\x17\n\x07view_id\x18\ - \x01\x20\x01(\tR\x06viewId\x12\x14\n\x04name\x18\x02\x20\x01(\tH\0R\x04n\ - ame\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\x12\x1e\n\tthumbn\ - ail\x18\x04\x20\x01(\tH\x02R\tthumbnailB\r\n\x0bone_of_nameB\r\n\x0bone_\ - of_descB\x12\n\x10one_of_thumbnail\"\xa9\x01\n\x10UpdateViewParams\x12\ - \x17\n\x07view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\x04name\x18\ - \x02\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\ - \x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthumbnailB\r\n\ - \x0bone_of_nameB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnail*'\n\x08Vi\ - ewType\x12\x0c\n\x08RichText\x10\0\x12\r\n\tPlainText\x10\x01b\x06proto3\ + (\tR\x04desc\x12*\n\tdata_type\x18\x05\x20\x01(\x0e2\r.ViewDataTypeR\x08\ + dataType\x12\x18\n\x07version\x18\x06\x20\x01(\x03R\x07version\x12-\n\nb\ + elongings\x18\x07\x20\x01(\x0b2\r.RepeatedViewR\nbelongings\x12#\n\rmodi\ + fied_time\x18\x08\x20\x01(\x03R\x0cmodifiedTime\x12\x1f\n\x0bcreate_time\ + \x18\t\x20\x01(\x03R\ncreateTime\x12\x19\n\x08ext_data\x18\n\x20\x01(\tR\ + \x07extData\x12\x1c\n\tthumbnail\x18\x0b\x20\x01(\tR\tthumbnail\"+\n\x0c\ + RepeatedView\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.ViewR\x05items\ + \"\xd8\x01\n\x11CreateViewPayload\x12\x20\n\x0cbelong_to_id\x18\x01\x20\ + \x01(\tR\nbelongToId\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\ + \x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12\x1e\n\tthumbnail\x18\x04\ + \x20\x01(\tH\0R\tthumbnail\x12*\n\tdata_type\x18\x05\x20\x01(\x0e2\r.Vie\ + wDataTypeR\x08dataType\x12\x19\n\x08ext_data\x18\x06\x20\x01(\tR\x07extD\ + ataB\x12\n\x10one_of_thumbnail\"\xee\x01\n\x10CreateViewParams\x12\x20\n\ + \x0cbelong_to_id\x18\x01\x20\x01(\tR\nbelongToId\x12\x12\n\x04name\x18\ + \x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\ + \x12\x1c\n\tthumbnail\x18\x04\x20\x01(\tR\tthumbnail\x12*\n\tdata_type\ + \x18\x05\x20\x01(\x0e2\r.ViewDataTypeR\x08dataType\x12\x19\n\x08ext_data\ + \x18\x06\x20\x01(\tR\x07extData\x12\x17\n\x07view_id\x18\x07\x20\x01(\tR\ + \x06viewId\x12\x12\n\x04data\x18\x08\x20\x01(\tR\x04data\"\x1e\n\x06View\ + Id\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"&\n\x0eRepeatedViewI\ + d\x12\x14\n\x05items\x18\x01\x20\x03(\tR\x05items\"\xaa\x01\n\x11UpdateV\ + iewPayload\x12\x17\n\x07view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\ + \x04name\x18\x02\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\ + \x01(\tH\x01R\x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthu\ + mbnailB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnai\ + l\"\xa9\x01\n\x10UpdateViewParams\x12\x17\n\x07view_id\x18\x01\x20\x01(\ + \tR\x06viewId\x12\x14\n\x04name\x18\x02\x20\x01(\tH\0R\x04name\x12\x14\n\ + \x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\x12\x1e\n\tthumbnail\x18\x04\ + \x20\x01(\tH\x02R\tthumbnailB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\ + \x12\n\x10one_of_thumbnail*+\n\x0cViewDataType\x12\x0c\n\x08RichText\x10\ + \0\x12\r\n\tPlainText\x10\x01b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto b/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto index 503c027128..824d4a8c2e 100644 --- a/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto +++ b/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto @@ -5,11 +5,13 @@ message View { string belong_to_id = 2; string name = 3; string desc = 4; - ViewType view_type = 5; + ViewDataType data_type = 5; int64 version = 6; RepeatedView belongings = 7; int64 modified_time = 8; int64 create_time = 9; + string ext_data = 10; + string thumbnail = 11; } message RepeatedView { repeated View items = 1; @@ -19,17 +21,18 @@ message CreateViewPayload { string name = 2; string desc = 3; oneof one_of_thumbnail { string thumbnail = 4; }; - ViewType view_type = 5; - string ext = 6; + ViewDataType data_type = 5; + string ext_data = 6; } message CreateViewParams { string belong_to_id = 1; string name = 2; string desc = 3; string thumbnail = 4; - ViewType view_type = 5; - string ext = 6; + ViewDataType data_type = 5; + string ext_data = 6; string view_id = 7; + string data = 8; } message ViewId { string value = 1; @@ -49,7 +52,7 @@ message UpdateViewParams { oneof one_of_desc { string desc = 3; }; oneof one_of_thumbnail { string thumbnail = 4; }; } -enum ViewType { +enum ViewDataType { RichText = 0; PlainText = 1; } diff --git a/shared-lib/flowy-folder-data-model/src/user_default.rs b/shared-lib/flowy-folder-data-model/src/user_default.rs index 3ea164e0cd..6a3b1b92dc 100644 --- a/shared-lib/flowy-folder-data-model/src/user_default.rs +++ b/shared-lib/flowy-folder-data-model/src/user_default.rs @@ -1,6 +1,6 @@ use crate::entities::{ app::{App, RepeatedApp}, - view::{RepeatedView, View, ViewType}, + view::{RepeatedView, View, ViewDataType}, workspace::Workspace, }; use chrono::Utc; @@ -49,17 +49,19 @@ fn create_default_view(app_id: String, time: chrono::DateTime) -> View { let view_id = uuid::Uuid::new_v4(); let name = "Read me".to_string(); let desc = "".to_string(); - let view_type = ViewType::RichText; + let data_type = ViewDataType::RichText; View { id: view_id.to_string(), belong_to_id: app_id, name, desc, - view_type, + data_type, version: 0, belongings: Default::default(), modified_time: time.timestamp(), create_time: time.timestamp(), + ext_data: "".to_string(), + thumbnail: "".to_string(), } } diff --git a/shared-lib/lib-ot/src/core/delta/builder.rs b/shared-lib/lib-ot/src/core/delta/builder.rs index 2289e3d02a..b065b645af 100644 --- a/shared-lib/lib-ot/src/core/delta/builder.rs +++ b/shared-lib/lib-ot/src/core/delta/builder.rs @@ -1,6 +1,6 @@ -use crate::core::{trim, Attributes, Delta, PlainAttributes}; +use crate::core::{trim, Attributes, Delta, PlainTextAttributes}; -pub type PlainDeltaBuilder = DeltaBuilder; +pub type PlainTextDeltaBuilder = DeltaBuilder; pub struct DeltaBuilder { delta: Delta, diff --git a/shared-lib/lib-ot/src/core/delta/delta.rs b/shared-lib/lib-ot/src/core/delta/delta.rs index 78f067b800..0fc748a0e5 100644 --- a/shared-lib/lib-ot/src/core/delta/delta.rs +++ b/shared-lib/lib-ot/src/core/delta/delta.rs @@ -13,7 +13,7 @@ use std::{ str::FromStr, }; -pub type PlainDelta = Delta; +pub type PlainTextDelta = Delta; // TODO: optimize the memory usage with Arc::make_mut or Cow #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/shared-lib/lib-ot/src/core/operation/builder.rs b/shared-lib/lib-ot/src/core/operation/builder.rs index bcada8ad4e..dc7b6dd7d9 100644 --- a/shared-lib/lib-ot/src/core/operation/builder.rs +++ b/shared-lib/lib-ot/src/core/operation/builder.rs @@ -1,10 +1,10 @@ use crate::{ - core::{Attributes, Operation, PlainAttributes}, + core::{Attributes, Operation, PlainTextAttributes}, rich_text::RichTextAttributes, }; pub type RichTextOpBuilder = OpBuilder; -pub type PlainTextOpBuilder = OpBuilder; +pub type PlainTextOpBuilder = OpBuilder; pub struct OpBuilder { ty: Operation, diff --git a/shared-lib/lib-ot/src/core/operation/operation.rs b/shared-lib/lib-ot/src/core/operation/operation.rs index 9dfdea395e..82228c19fc 100644 --- a/shared-lib/lib-ot/src/core/operation/operation.rs +++ b/shared-lib/lib-ot/src/core/operation/operation.rs @@ -339,14 +339,14 @@ where } #[derive(Debug, Clone, Eq, PartialEq, Default, Serialize, Deserialize)] -pub struct PlainAttributes(); -impl fmt::Display for PlainAttributes { +pub struct PlainTextAttributes(); +impl fmt::Display for PlainTextAttributes { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("PlainAttributes") } } -impl Attributes for PlainAttributes { +impl Attributes for PlainTextAttributes { fn is_empty(&self) -> bool { true } @@ -356,7 +356,7 @@ impl Attributes for PlainAttributes { fn extend_other(&mut self, _other: Self) {} } -impl OperationTransformable for PlainAttributes { +impl OperationTransformable for PlainTextAttributes { fn compose(&self, _other: &Self) -> Result { Ok(self.clone()) } diff --git a/shared-lib/lib-ot/src/rich_text/attributes.rs b/shared-lib/lib-ot/src/rich_text/attributes.rs index 7aa9cfeb34..d70e23228b 100644 --- a/shared-lib/lib-ot/src/rich_text/attributes.rs +++ b/shared-lib/lib-ot/src/rich_text/attributes.rs @@ -40,6 +40,7 @@ impl fmt::Display for RichTextAttributes { } } +#[inline(always)] pub fn plain_attributes() -> RichTextAttributes { RichTextAttributes::default() } @@ -58,7 +59,7 @@ impl RichTextAttributes { self.inner.insert(key, value); } - pub fn add_kv(&mut self, key: RichTextAttributeKey, value: RichTextAttributeValue) { + pub fn insert(&mut self, key: RichTextAttributeKey, value: RichTextAttributeValue) { self.inner.insert(key, value); } diff --git a/shared-lib/lib-ot/src/rich_text/attributes_serde.rs b/shared-lib/lib-ot/src/rich_text/attributes_serde.rs index 5126f722e1..19ffb5a416 100644 --- a/shared-lib/lib-ot/src/rich_text/attributes_serde.rs +++ b/shared-lib/lib-ot/src/rich_text/attributes_serde.rs @@ -101,7 +101,7 @@ impl<'de> Deserialize<'de> for RichTextAttributes { let mut attributes = RichTextAttributes::new(); while let Some(key) = map.next_key::()? { let value = map.next_value::()?; - attributes.add_kv(key, value); + attributes.insert(key, value); } Ok(attributes) From b6de0caad6f2922c571e0e9b03bb3970b3621f93 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 1 Mar 2022 10:25:21 +0800 Subject: [PATCH 08/12] refactor: show plugin --- frontend/app_flowy/lib/plugin/plugin.dart | 6 +- .../app_flowy/lib/plugin/src/sandbox.dart | 13 +- .../lib/startup/tasks/load_plugin.dart | 27 +-- .../lib/workspace/application/appearance.dart | 2 +- .../workspace/application/menu/menu_bloc.dart | 2 +- .../domain/page_stack/page_stack.dart | 2 +- .../lib/workspace/domain/view_ext.dart | 6 + .../presentation/home/home_screen.dart | 3 +- .../stack_page/blank/blank_page.dart | 16 +- .../stack_page/doc/doc_stack_page.dart | 3 +- .../stack_page/trash/trash_page.dart | 14 +- .../menu/widget/app/section/section.dart | 2 +- .../widgets/menu/widget/menu_trash.dart | 2 +- .../flowy-folder-data-model/view.pb.dart | 42 +++++ .../flowy-folder-data-model/view.pbjson.dart | 9 +- .../persistence/version_1/view_sql.rs | 46 +---- .../src/services/view/controller.rs | 1 + .../flowy-net/src/local_server/server.rs | 1 + .../src/entities/view.rs | 18 +- .../src/protobuf/model/view.rs | 162 +++++++++++++++--- .../src/protobuf/proto/view.proto | 3 + .../src/user_default.rs | 1 + 22 files changed, 255 insertions(+), 126 deletions(-) diff --git a/frontend/app_flowy/lib/plugin/plugin.dart b/frontend/app_flowy/lib/plugin/plugin.dart index cc7894aab1..a949d76985 100644 --- a/frontend/app_flowy/lib/plugin/plugin.dart +++ b/frontend/app_flowy/lib/plugin/plugin.dart @@ -8,7 +8,7 @@ import 'package:flutter/widgets.dart'; export "./src/sandbox.dart"; -typedef PluginType = String; +typedef PluginType = int; typedef PluginDataType = ViewDataType; @@ -31,7 +31,7 @@ abstract class PluginBuilder { PluginType get pluginType; - ViewDataType get dataType; + ViewDataType get dataType => ViewDataType.PlainText; } abstract class PluginDisplay with NavigationItem { @@ -50,7 +50,7 @@ void registerPlugin({required PluginBuilder builder}) { getIt().registerPlugin(builder.pluginType, builder); } -Plugin makePlugin({required String pluginType, dynamic data}) { +Plugin makePlugin({required PluginType pluginType, dynamic data}) { final plugin = getIt().buildPlugin(pluginType, data); return plugin; } diff --git a/frontend/app_flowy/lib/plugin/src/sandbox.dart b/frontend/app_flowy/lib/plugin/src/sandbox.dart index 02dd64d062..cfaecb605e 100644 --- a/frontend/app_flowy/lib/plugin/src/sandbox.dart +++ b/frontend/app_flowy/lib/plugin/src/sandbox.dart @@ -6,14 +6,14 @@ import '../plugin.dart'; import 'runner.dart'; class PluginSandbox { - final LinkedHashMap _pluginMap = LinkedHashMap(); + final LinkedHashMap _pluginMap = LinkedHashMap(); late PluginRunner pluginRunner; PluginSandbox() { pluginRunner = PluginRunner(); } - int indexOf(String pluginType) { + int indexOf(PluginType pluginType) { final index = _pluginMap.keys.toList().indexWhere((ty) => ty == pluginType); if (index == -1) { throw PlatformException(code: '-1', message: "Can't find the flowy plugin type: $pluginType"); @@ -21,20 +21,19 @@ class PluginSandbox { return index; } - Plugin buildPlugin(String pluginType, dynamic data) { - final index = indexOf(pluginType); - final plugin = _pluginMap[index]!.build(data); + Plugin buildPlugin(PluginType pluginType, dynamic data) { + final plugin = _pluginMap[pluginType]!.build(data); return plugin; } - void registerPlugin(String pluginType, PluginBuilder builder) { + void registerPlugin(PluginType pluginType, PluginBuilder builder) { if (_pluginMap.containsKey(pluginType)) { throw PlatformException(code: '-1', message: "$pluginType was registered before"); } _pluginMap[pluginType] = builder; } - List get supportPluginTypes => _pluginMap.keys.toList(); + List get supportPluginTypes => _pluginMap.keys.toList(); List get builders => _pluginMap.values.toList(); } diff --git a/frontend/app_flowy/lib/startup/tasks/load_plugin.dart b/frontend/app_flowy/lib/startup/tasks/load_plugin.dart index c2d9b0cb8e..0542cbda29 100644 --- a/frontend/app_flowy/lib/startup/tasks/load_plugin.dart +++ b/frontend/app_flowy/lib/startup/tasks/load_plugin.dart @@ -4,24 +4,27 @@ import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dar import 'package:app_flowy/workspace/presentation/stack_page/doc/doc_stack_page.dart'; import 'package:app_flowy/workspace/presentation/stack_page/trash/trash_page.dart'; -enum DefaultPluginEnum { +enum DefaultPlugin { + quillEditor, blank, trash, } -extension FlowyDefaultPluginExt on DefaultPluginEnum { - String type() { +extension FlowyDefaultPluginExt on DefaultPlugin { + int type() { switch (this) { - case DefaultPluginEnum.blank: - return "Blank"; - case DefaultPluginEnum.trash: - return "Trash"; + case DefaultPlugin.quillEditor: + return 0; + case DefaultPlugin.blank: + return 1; + case DefaultPlugin.trash: + return 2; } } } -bool isDefaultPlugin(String pluginType) { - return DefaultPluginEnum.values.map((e) => e.type()).contains(pluginType); +bool isDefaultPlugin(PluginType pluginType) { + return DefaultPlugin.values.map((e) => e.type()).contains(pluginType); } class PluginLoadTask extends LaunchTask { @@ -30,10 +33,8 @@ class PluginLoadTask extends LaunchTask { @override Future initialize(LaunchContext context) async { - registerPlugin(builder: DocumentPluginBuilder()); - - registerPlugin(builder: TrashPluginBuilder()); - registerPlugin(builder: BlankPluginBuilder()); + registerPlugin(builder: TrashPluginBuilder()); + registerPlugin(builder: DocumentPluginBuilder()); } } diff --git a/frontend/app_flowy/lib/workspace/application/appearance.dart b/frontend/app_flowy/lib/workspace/application/appearance.dart index 80a6cab581..8c590c5f53 100644 --- a/frontend/app_flowy/lib/workspace/application/appearance.dart +++ b/frontend/app_flowy/lib/workspace/application/appearance.dart @@ -48,7 +48,7 @@ class AppearanceSettingModel extends ChangeNotifier with EquatableMixin { void setLocale(BuildContext context, Locale newLocale) { if (_locale != newLocale) { if (!context.supportedLocales.contains(newLocale)) { - Log.error("Unsupported locale: $newLocale"); + Log.warn("Unsupported locale: $newLocale"); newLocale = const Locale('en'); Log.debug("Fallback to locale: $newLocale"); } diff --git a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart index 23224af55b..9675870b8d 100644 --- a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart @@ -100,6 +100,6 @@ class MenuState with _$MenuState { isCollapse: false, apps: none(), successOrFailure: left(unit), - plugin: makePlugin(pluginType: DefaultPluginEnum.blank.type()), + plugin: makePlugin(pluginType: DefaultPlugin.blank.type()), ); } diff --git a/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart b/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart index 594711220e..9023bd4cc3 100644 --- a/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart +++ b/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart @@ -40,7 +40,7 @@ class HomeStackNotifier extends ChangeNotifier { Widget get titleWidget => _plugin.display.leftBarItem; - HomeStackNotifier({Plugin? plugin}) : _plugin = plugin ?? makePlugin(pluginType: DefaultPluginEnum.blank.type()); + HomeStackNotifier({Plugin? plugin}) : _plugin = plugin ?? makePlugin(pluginType: DefaultPlugin.blank.type()); set plugin(Plugin newPlugin) { if (newPlugin.pluginId == _plugin.pluginId) { diff --git a/frontend/app_flowy/lib/workspace/domain/view_ext.dart b/frontend/app_flowy/lib/workspace/domain/view_ext.dart index bb94947128..cf80a820a0 100644 --- a/frontend/app_flowy/lib/workspace/domain/view_ext.dart +++ b/frontend/app_flowy/lib/workspace/domain/view_ext.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/plugin/plugin.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flutter/material.dart'; @@ -41,4 +42,9 @@ extension ViewExtension on View { final Widget widget = svg(thumbnail, color: iconColor); return widget; } + + Plugin plugin() { + final plugin = makePlugin(pluginType: pluginType, data: this); + return plugin; + } } diff --git a/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart b/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart index 5f1ff4d89b..174727c2df 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart @@ -13,7 +13,6 @@ import 'package:flowy_sdk/protobuf/flowy-folder-data-model/protobuf.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; -import 'package:app_flowy/workspace/domain/view_ext.dart'; import 'home_layout.dart'; @@ -110,7 +109,7 @@ class _HomeScreenState extends State { Widget _buildHomeMenu({required HomeLayout layout, required BuildContext context}) { if (initialView == null && widget.workspaceSetting.hasLatestView()) { initialView = widget.workspaceSetting.latestView; - final plugin = makePlugin(pluginType: "RichText", data: initialView); + final plugin = makePlugin(pluginType: initialView!.pluginType, data: initialView); getIt().setPlugin(plugin); } diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart index 08db10bfa1..69b8e0b9fd 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart @@ -1,14 +1,13 @@ import 'package:app_flowy/startup/tasks/load_plugin.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pbenum.dart'; import 'package:flutter/material.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; -class BlankPluginBuilder implements PluginBuilder { +class BlankPluginBuilder extends PluginBuilder { @override Plugin build(dynamic data) { return BlankPagePlugin(pluginType: pluginType); @@ -18,19 +17,14 @@ class BlankPluginBuilder implements PluginBuilder { String get pluginName => "Blank"; @override - PluginType get pluginType => DefaultPluginEnum.blank.type(); - - @override - ViewDataType get dataType => ViewDataType.PlainText; + PluginType get pluginType => DefaultPlugin.blank.type(); } class BlankPagePlugin implements Plugin { - late PluginType _pluginType; + final PluginType _pluginType; BlankPagePlugin({ - required String pluginType, - }) { - _pluginType = pluginType; - } + required PluginType pluginType, + }) : _pluginType = pluginType; @override void dispose() {} diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart index 9f2c9bd1bc..1c4f9711e3 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/startup/tasks/load_plugin.dart'; import 'package:app_flowy/workspace/application/appearance.dart'; import 'package:app_flowy/workspace/application/doc/share_bloc.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; @@ -38,7 +39,7 @@ class DocumentPluginBuilder implements PluginBuilder { String get pluginName => "Doc"; @override - PluginType get pluginType => "RichText"; + PluginType get pluginType => DefaultPlugin.quillEditor.type(); @override ViewDataType get dataType => ViewDataType.RichText; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart index 436aea4ac0..e2c71f1cda 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart @@ -14,7 +14,6 @@ import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pbenum.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; @@ -22,7 +21,7 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'widget/trash_header.dart'; -class TrashPluginBuilder implements PluginBuilder { +class TrashPluginBuilder extends PluginBuilder { @override Plugin build(dynamic data) { return TrashPlugin(pluginType: pluginType); @@ -32,18 +31,13 @@ class TrashPluginBuilder implements PluginBuilder { String get pluginName => "Trash"; @override - PluginType get pluginType => DefaultPluginEnum.trash.type(); - - @override - ViewDataType get dataType => ViewDataType.PlainText; + PluginType get pluginType => DefaultPlugin.trash.type(); } class TrashPlugin implements Plugin { - late PluginType _pluginType; + final PluginType _pluginType; - TrashPlugin({required PluginType pluginType}) { - _pluginType = pluginType; - } + TrashPlugin({required PluginType pluginType}) : _pluginType = pluginType; @override void dispose() {} diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart index da486e6934..be3ed9ab33 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart @@ -106,7 +106,7 @@ class ViewSectionNotifier with ChangeNotifier { if (view != null) { WidgetsBinding.instance?.addPostFrameCallback((_) { - getIt().setPlugin(view.stackContext()); + getIt().setPlugin(view.plugin()); }); } else { // do nothing diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart index a86bcef76d..96170f350e 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart @@ -23,7 +23,7 @@ class MenuTrash extends StatelessWidget { child: InkWell( onTap: () { Provider.of(context, listen: false).selectedView.value = null; - getIt().setPlugin(makePlugin(pluginType: DefaultPluginEnum.trash.type())); + getIt().setPlugin(makePlugin(pluginType: DefaultPlugin.trash.type())); }, child: _render(context), ), diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart index aac78ead81..6bf9801803 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart @@ -27,6 +27,7 @@ class View extends $pb.GeneratedMessage { ..aInt64(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'createTime') ..aOS(10, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extData') ..aOS(11, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail') + ..a<$core.int>(12, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'pluginType', $pb.PbFieldType.O3) ..hasRequiredFields = false ; @@ -43,6 +44,7 @@ class View extends $pb.GeneratedMessage { $fixnum.Int64? createTime, $core.String? extData, $core.String? thumbnail, + $core.int? pluginType, }) { final _result = create(); if (id != null) { @@ -78,6 +80,9 @@ class View extends $pb.GeneratedMessage { if (thumbnail != null) { _result.thumbnail = thumbnail; } + if (pluginType != null) { + _result.pluginType = pluginType; + } return _result; } factory View.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -201,6 +206,15 @@ class View extends $pb.GeneratedMessage { $core.bool hasThumbnail() => $_has(10); @$pb.TagNumber(11) void clearThumbnail() => clearField(11); + + @$pb.TagNumber(12) + $core.int get pluginType => $_getIZ(11); + @$pb.TagNumber(12) + set pluginType($core.int v) { $_setSignedInt32(11, v); } + @$pb.TagNumber(12) + $core.bool hasPluginType() => $_has(11); + @$pb.TagNumber(12) + void clearPluginType() => clearField(12); } class RepeatedView extends $pb.GeneratedMessage { @@ -262,6 +276,7 @@ class CreateViewPayload extends $pb.GeneratedMessage { ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail') ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dataType', $pb.PbFieldType.OE, defaultOrMaker: ViewDataType.RichText, valueOf: ViewDataType.valueOf, enumValues: ViewDataType.values) ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extData') + ..a<$core.int>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'pluginType', $pb.PbFieldType.O3) ..hasRequiredFields = false ; @@ -273,6 +288,7 @@ class CreateViewPayload extends $pb.GeneratedMessage { $core.String? thumbnail, ViewDataType? dataType, $core.String? extData, + $core.int? pluginType, }) { final _result = create(); if (belongToId != null) { @@ -293,6 +309,9 @@ class CreateViewPayload extends $pb.GeneratedMessage { if (extData != null) { _result.extData = extData; } + if (pluginType != null) { + _result.pluginType = pluginType; + } return _result; } factory CreateViewPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -372,6 +391,15 @@ class CreateViewPayload extends $pb.GeneratedMessage { $core.bool hasExtData() => $_has(5); @$pb.TagNumber(6) void clearExtData() => clearField(6); + + @$pb.TagNumber(7) + $core.int get pluginType => $_getIZ(6); + @$pb.TagNumber(7) + set pluginType($core.int v) { $_setSignedInt32(6, v); } + @$pb.TagNumber(7) + $core.bool hasPluginType() => $_has(6); + @$pb.TagNumber(7) + void clearPluginType() => clearField(7); } class CreateViewParams extends $pb.GeneratedMessage { @@ -384,6 +412,7 @@ class CreateViewParams extends $pb.GeneratedMessage { ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extData') ..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId') ..aOS(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data') + ..a<$core.int>(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'pluginType', $pb.PbFieldType.O3) ..hasRequiredFields = false ; @@ -397,6 +426,7 @@ class CreateViewParams extends $pb.GeneratedMessage { $core.String? extData, $core.String? viewId, $core.String? data, + $core.int? pluginType, }) { final _result = create(); if (belongToId != null) { @@ -423,6 +453,9 @@ class CreateViewParams extends $pb.GeneratedMessage { if (data != null) { _result.data = data; } + if (pluginType != null) { + _result.pluginType = pluginType; + } return _result; } factory CreateViewParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -517,6 +550,15 @@ class CreateViewParams extends $pb.GeneratedMessage { $core.bool hasData() => $_has(7); @$pb.TagNumber(8) void clearData() => clearField(8); + + @$pb.TagNumber(9) + $core.int get pluginType => $_getIZ(8); + @$pb.TagNumber(9) + set pluginType($core.int v) { $_setSignedInt32(8, v); } + @$pb.TagNumber(9) + $core.bool hasPluginType() => $_has(8); + @$pb.TagNumber(9) + void clearPluginType() => clearField(9); } class ViewId extends $pb.GeneratedMessage { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart index 2221dec960..8c50bd08fc 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart @@ -34,11 +34,12 @@ const View$json = const { const {'1': 'create_time', '3': 9, '4': 1, '5': 3, '10': 'createTime'}, const {'1': 'ext_data', '3': 10, '4': 1, '5': 9, '10': 'extData'}, const {'1': 'thumbnail', '3': 11, '4': 1, '5': 9, '10': 'thumbnail'}, + const {'1': 'plugin_type', '3': 12, '4': 1, '5': 5, '10': 'pluginType'}, ], }; /// Descriptor for `View`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List viewDescriptor = $convert.base64Decode('CgRWaWV3Eg4KAmlkGAEgASgJUgJpZBIgCgxiZWxvbmdfdG9faWQYAiABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgDIAEoCVIEbmFtZRISCgRkZXNjGAQgASgJUgRkZXNjEioKCWRhdGFfdHlwZRgFIAEoDjINLlZpZXdEYXRhVHlwZVIIZGF0YVR5cGUSGAoHdmVyc2lvbhgGIAEoA1IHdmVyc2lvbhItCgpiZWxvbmdpbmdzGAcgASgLMg0uUmVwZWF0ZWRWaWV3UgpiZWxvbmdpbmdzEiMKDW1vZGlmaWVkX3RpbWUYCCABKANSDG1vZGlmaWVkVGltZRIfCgtjcmVhdGVfdGltZRgJIAEoA1IKY3JlYXRlVGltZRIZCghleHRfZGF0YRgKIAEoCVIHZXh0RGF0YRIcCgl0aHVtYm5haWwYCyABKAlSCXRodW1ibmFpbA=='); +final $typed_data.Uint8List viewDescriptor = $convert.base64Decode('CgRWaWV3Eg4KAmlkGAEgASgJUgJpZBIgCgxiZWxvbmdfdG9faWQYAiABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgDIAEoCVIEbmFtZRISCgRkZXNjGAQgASgJUgRkZXNjEioKCWRhdGFfdHlwZRgFIAEoDjINLlZpZXdEYXRhVHlwZVIIZGF0YVR5cGUSGAoHdmVyc2lvbhgGIAEoA1IHdmVyc2lvbhItCgpiZWxvbmdpbmdzGAcgASgLMg0uUmVwZWF0ZWRWaWV3UgpiZWxvbmdpbmdzEiMKDW1vZGlmaWVkX3RpbWUYCCABKANSDG1vZGlmaWVkVGltZRIfCgtjcmVhdGVfdGltZRgJIAEoA1IKY3JlYXRlVGltZRIZCghleHRfZGF0YRgKIAEoCVIHZXh0RGF0YRIcCgl0aHVtYm5haWwYCyABKAlSCXRodW1ibmFpbBIfCgtwbHVnaW5fdHlwZRgMIAEoBVIKcGx1Z2luVHlwZQ=='); @$core.Deprecated('Use repeatedViewDescriptor instead') const RepeatedView$json = const { '1': 'RepeatedView', @@ -59,6 +60,7 @@ const CreateViewPayload$json = const { const {'1': 'thumbnail', '3': 4, '4': 1, '5': 9, '9': 0, '10': 'thumbnail'}, const {'1': 'data_type', '3': 5, '4': 1, '5': 14, '6': '.ViewDataType', '10': 'dataType'}, const {'1': 'ext_data', '3': 6, '4': 1, '5': 9, '10': 'extData'}, + const {'1': 'plugin_type', '3': 7, '4': 1, '5': 5, '10': 'pluginType'}, ], '8': const [ const {'1': 'one_of_thumbnail'}, @@ -66,7 +68,7 @@ const CreateViewPayload$json = const { }; /// Descriptor for `CreateViewPayload`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List createViewPayloadDescriptor = $convert.base64Decode('ChFDcmVhdGVWaWV3UGF5bG9hZBIgCgxiZWxvbmdfdG9faWQYASABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEh4KCXRodW1ibmFpbBgEIAEoCUgAUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIZCghleHRfZGF0YRgGIAEoCVIHZXh0RGF0YUISChBvbmVfb2ZfdGh1bWJuYWls'); +final $typed_data.Uint8List createViewPayloadDescriptor = $convert.base64Decode('ChFDcmVhdGVWaWV3UGF5bG9hZBIgCgxiZWxvbmdfdG9faWQYASABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEh4KCXRodW1ibmFpbBgEIAEoCUgAUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIZCghleHRfZGF0YRgGIAEoCVIHZXh0RGF0YRIfCgtwbHVnaW5fdHlwZRgHIAEoBVIKcGx1Z2luVHlwZUISChBvbmVfb2ZfdGh1bWJuYWls'); @$core.Deprecated('Use createViewParamsDescriptor instead') const CreateViewParams$json = const { '1': 'CreateViewParams', @@ -79,11 +81,12 @@ const CreateViewParams$json = const { const {'1': 'ext_data', '3': 6, '4': 1, '5': 9, '10': 'extData'}, const {'1': 'view_id', '3': 7, '4': 1, '5': 9, '10': 'viewId'}, const {'1': 'data', '3': 8, '4': 1, '5': 9, '10': 'data'}, + const {'1': 'plugin_type', '3': 9, '4': 1, '5': 5, '10': 'pluginType'}, ], }; /// Descriptor for `CreateViewParams`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIZCghleHRfZGF0YRgGIAEoCVIHZXh0RGF0YRIXCgd2aWV3X2lkGAcgASgJUgZ2aWV3SWQSEgoEZGF0YRgIIAEoCVIEZGF0YQ=='); +final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIZCghleHRfZGF0YRgGIAEoCVIHZXh0RGF0YRIXCgd2aWV3X2lkGAcgASgJUgZ2aWV3SWQSEgoEZGF0YRgIIAEoCVIEZGF0YRIfCgtwbHVnaW5fdHlwZRgJIAEoBVIKcGx1Z2luVHlwZQ=='); @$core.Deprecated('Use viewIdDescriptor instead') const ViewId$json = const { '1': 'ViewId', diff --git a/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs b/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs index 50de4aa895..955bf44818 100644 --- a/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs +++ b/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs @@ -65,49 +65,6 @@ impl ViewTableSql { } } -// pub(crate) fn read_views( -// belong_to_id: &str, -// is_trash: Option, -// conn: &SqliteConnection, -// ) -> Result { -// let views = dsl::view_table -// .inner_join(trash_table::dsl::trash_table.on(trash_id.ne(view_table:: -// id))) .filter(view_table::belong_to_id.eq(belong_to_id)) -// .select(( -// view_table::id, -// view_table::belong_to_id, -// view_table::name, -// view_table::desc, -// view_table::modified_time, -// view_table::create_time, -// view_table::thumbnail, -// view_table::view_type, -// view_table::version, -// )) -// .load(conn)? -// .into_iter() -// .map( -// |(id, belong_to_id, name, desc, create_time, modified_time, -// thumbnail, view_type, version)| { ViewTable { -// id, -// belong_to_id, -// name, -// desc, -// modified_time, -// create_time, -// thumbnail, -// view_type, -// version, -// is_trash: false, -// } -// .into() -// }, -// ) -// .collect::>(); -// -// Ok(RepeatedView { items: views }) -// } - #[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)] #[belongs_to(AppTable, foreign_key = "belong_to_id")] #[table_name = "view_table"] @@ -165,6 +122,9 @@ impl std::convert::From for View { create_time: table.create_time, ext_data: "".to_string(), thumbnail: table.thumbnail, + // Store the view in ViewTable was deprecated since v0.0.2. + // No need worry about plugin_type. + plugin_type: 0, } } } diff --git a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs index 80b2aa7094..2e23f544f7 100644 --- a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs +++ b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs @@ -178,6 +178,7 @@ impl ViewController { data: document_json, view_id: uuid_string(), ext_data: view.ext_data, + plugin_type: view.plugin_type, }; let _ = self.create_view_from_params(duplicate_params).await?; diff --git a/frontend/rust-lib/flowy-net/src/local_server/server.rs b/frontend/rust-lib/flowy-net/src/local_server/server.rs index 843c587a62..e8dcd1ed93 100644 --- a/frontend/rust-lib/flowy-net/src/local_server/server.rs +++ b/frontend/rust-lib/flowy-net/src/local_server/server.rs @@ -307,6 +307,7 @@ impl FolderCouldServiceV1 for LocalServer { create_time: time, ext_data: params.ext_data, thumbnail: params.thumbnail, + plugin_type: params.plugin_type, }; FutureResult::new(async { Ok(view) }) } diff --git a/shared-lib/flowy-folder-data-model/src/entities/view.rs b/shared-lib/flowy-folder-data-model/src/entities/view.rs index 26a7d2938b..8a90f0fb9f 100644 --- a/shared-lib/flowy-folder-data-model/src/entities/view.rs +++ b/shared-lib/flowy-folder-data-model/src/entities/view.rs @@ -48,6 +48,14 @@ pub struct View { #[pb(index = 11)] pub thumbnail: String, + + #[pb(index = 12)] + #[serde(default = "default_plugin_type")] + pub plugin_type: i32, +} + +fn default_plugin_type() -> i32 { + 0 } #[derive(Eq, PartialEq, Debug, Default, ProtoBuf, Clone, Serialize, Deserialize)] @@ -115,6 +123,9 @@ pub struct CreateViewPayload { #[pb(index = 6)] pub ext_data: String, + + #[pb(index = 7)] + pub plugin_type: i32, } #[derive(Default, ProtoBuf, Debug, Clone)] @@ -142,6 +153,9 @@ pub struct CreateViewParams { #[pb(index = 8)] pub data: String, + + #[pb(index = 9)] + pub plugin_type: i32, } impl TryInto for CreateViewPayload { @@ -156,6 +170,7 @@ impl TryInto for CreateViewPayload { None => "".to_string(), Some(thumbnail) => ViewThumbnail::parse(thumbnail)?.0, }; + let data = "".to_string(); Ok(CreateViewParams { belong_to_id, @@ -165,7 +180,8 @@ impl TryInto for CreateViewPayload { thumbnail, ext_data, view_id, - data: "".to_string(), + data, + plugin_type: self.plugin_type, }) } } diff --git a/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs b/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs index b1900de3dd..0e1e3a7279 100644 --- a/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs +++ b/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs @@ -37,6 +37,7 @@ pub struct View { pub create_time: i64, pub ext_data: ::std::string::String, pub thumbnail: ::std::string::String, + pub plugin_type: i32, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -301,6 +302,21 @@ impl View { pub fn take_thumbnail(&mut self) -> ::std::string::String { ::std::mem::replace(&mut self.thumbnail, ::std::string::String::new()) } + + // int32 plugin_type = 12; + + + pub fn get_plugin_type(&self) -> i32 { + self.plugin_type + } + pub fn clear_plugin_type(&mut self) { + self.plugin_type = 0; + } + + // Param is passed by value, moved + pub fn set_plugin_type(&mut self, v: i32) { + self.plugin_type = v; + } } impl ::protobuf::Message for View { @@ -362,6 +378,13 @@ impl ::protobuf::Message for View { 11 => { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.thumbnail)?; }, + 12 => { + if wire_type != ::protobuf::wire_format::WireTypeVarint { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + let tmp = is.read_int32()?; + self.plugin_type = tmp; + }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; }, @@ -408,6 +431,9 @@ impl ::protobuf::Message for View { if !self.thumbnail.is_empty() { my_size += ::protobuf::rt::string_size(11, &self.thumbnail); } + if self.plugin_type != 0 { + my_size += ::protobuf::rt::value_size(12, self.plugin_type, ::protobuf::wire_format::WireTypeVarint); + } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); my_size @@ -449,6 +475,9 @@ impl ::protobuf::Message for View { if !self.thumbnail.is_empty() { os.write_string(11, &self.thumbnail)?; } + if self.plugin_type != 0 { + os.write_int32(12, self.plugin_type)?; + } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) } @@ -542,6 +571,11 @@ impl ::protobuf::Message for View { |m: &View| { &m.thumbnail }, |m: &mut View| { &mut m.thumbnail }, )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>( + "plugin_type", + |m: &View| { &m.plugin_type }, + |m: &mut View| { &mut m.plugin_type }, + )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "View", fields, @@ -569,6 +603,7 @@ impl ::protobuf::Clear for View { self.create_time = 0; self.ext_data.clear(); self.thumbnail.clear(); + self.plugin_type = 0; self.unknown_fields.clear(); } } @@ -759,6 +794,7 @@ pub struct CreateViewPayload { pub desc: ::std::string::String, pub data_type: ViewDataType, pub ext_data: ::std::string::String, + pub plugin_type: i32, // message oneof groups pub one_of_thumbnail: ::std::option::Option, // special fields @@ -949,6 +985,21 @@ impl CreateViewPayload { pub fn take_ext_data(&mut self) -> ::std::string::String { ::std::mem::replace(&mut self.ext_data, ::std::string::String::new()) } + + // int32 plugin_type = 7; + + + pub fn get_plugin_type(&self) -> i32 { + self.plugin_type + } + pub fn clear_plugin_type(&mut self) { + self.plugin_type = 0; + } + + // Param is passed by value, moved + pub fn set_plugin_type(&mut self, v: i32) { + self.plugin_type = v; + } } impl ::protobuf::Message for CreateViewPayload { @@ -981,6 +1032,13 @@ impl ::protobuf::Message for CreateViewPayload { 6 => { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.ext_data)?; }, + 7 => { + if wire_type != ::protobuf::wire_format::WireTypeVarint { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + let tmp = is.read_int32()?; + self.plugin_type = tmp; + }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; }, @@ -1008,6 +1066,9 @@ impl ::protobuf::Message for CreateViewPayload { if !self.ext_data.is_empty() { my_size += ::protobuf::rt::string_size(6, &self.ext_data); } + if self.plugin_type != 0 { + my_size += ::protobuf::rt::value_size(7, self.plugin_type, ::protobuf::wire_format::WireTypeVarint); + } if let ::std::option::Option::Some(ref v) = self.one_of_thumbnail { match v { &CreateViewPayload_oneof_one_of_thumbnail::thumbnail(ref v) => { @@ -1036,6 +1097,9 @@ impl ::protobuf::Message for CreateViewPayload { if !self.ext_data.is_empty() { os.write_string(6, &self.ext_data)?; } + if self.plugin_type != 0 { + os.write_int32(7, self.plugin_type)?; + } if let ::std::option::Option::Some(ref v) = self.one_of_thumbnail { match v { &CreateViewPayload_oneof_one_of_thumbnail::thumbnail(ref v) => { @@ -1111,6 +1175,11 @@ impl ::protobuf::Message for CreateViewPayload { |m: &CreateViewPayload| { &m.ext_data }, |m: &mut CreateViewPayload| { &mut m.ext_data }, )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>( + "plugin_type", + |m: &CreateViewPayload| { &m.plugin_type }, + |m: &mut CreateViewPayload| { &mut m.plugin_type }, + )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "CreateViewPayload", fields, @@ -1133,6 +1202,7 @@ impl ::protobuf::Clear for CreateViewPayload { self.one_of_thumbnail = ::std::option::Option::None; self.data_type = ViewDataType::RichText; self.ext_data.clear(); + self.plugin_type = 0; self.unknown_fields.clear(); } } @@ -1160,6 +1230,7 @@ pub struct CreateViewParams { pub ext_data: ::std::string::String, pub view_id: ::std::string::String, pub data: ::std::string::String, + pub plugin_type: i32, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -1372,6 +1443,21 @@ impl CreateViewParams { pub fn take_data(&mut self) -> ::std::string::String { ::std::mem::replace(&mut self.data, ::std::string::String::new()) } + + // int32 plugin_type = 9; + + + pub fn get_plugin_type(&self) -> i32 { + self.plugin_type + } + pub fn clear_plugin_type(&mut self) { + self.plugin_type = 0; + } + + // Param is passed by value, moved + pub fn set_plugin_type(&mut self, v: i32) { + self.plugin_type = v; + } } impl ::protobuf::Message for CreateViewParams { @@ -1407,6 +1493,13 @@ impl ::protobuf::Message for CreateViewParams { 8 => { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?; }, + 9 => { + if wire_type != ::protobuf::wire_format::WireTypeVarint { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + let tmp = is.read_int32()?; + self.plugin_type = tmp; + }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; }, @@ -1443,6 +1536,9 @@ impl ::protobuf::Message for CreateViewParams { if !self.data.is_empty() { my_size += ::protobuf::rt::string_size(8, &self.data); } + if self.plugin_type != 0 { + my_size += ::protobuf::rt::value_size(9, self.plugin_type, ::protobuf::wire_format::WireTypeVarint); + } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); my_size @@ -1473,6 +1569,9 @@ impl ::protobuf::Message for CreateViewParams { if !self.data.is_empty() { os.write_string(8, &self.data)?; } + if self.plugin_type != 0 { + os.write_int32(9, self.plugin_type)?; + } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) } @@ -1551,6 +1650,11 @@ impl ::protobuf::Message for CreateViewParams { |m: &CreateViewParams| { &m.data }, |m: &mut CreateViewParams| { &mut m.data }, )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>( + "plugin_type", + |m: &CreateViewParams| { &m.plugin_type }, + |m: &mut CreateViewParams| { &mut m.plugin_type }, + )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "CreateViewParams", fields, @@ -1575,6 +1679,7 @@ impl ::protobuf::Clear for CreateViewParams { self.ext_data.clear(); self.view_id.clear(); self.data.clear(); + self.plugin_type = 0; self.unknown_fields.clear(); } } @@ -2765,7 +2870,7 @@ impl ::protobuf::reflect::ProtobufValue for ViewDataType { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\nview.proto\"\xd4\x02\n\x04View\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\ + \n\nview.proto\"\xf5\x02\n\x04View\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\ \x02id\x12\x20\n\x0cbelong_to_id\x18\x02\x20\x01(\tR\nbelongToId\x12\x12\ \n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x04\x20\x01\ (\tR\x04desc\x12*\n\tdata_type\x18\x05\x20\x01(\x0e2\r.ViewDataTypeR\x08\ @@ -2773,32 +2878,35 @@ static file_descriptor_proto_data: &'static [u8] = b"\ elongings\x18\x07\x20\x01(\x0b2\r.RepeatedViewR\nbelongings\x12#\n\rmodi\ fied_time\x18\x08\x20\x01(\x03R\x0cmodifiedTime\x12\x1f\n\x0bcreate_time\ \x18\t\x20\x01(\x03R\ncreateTime\x12\x19\n\x08ext_data\x18\n\x20\x01(\tR\ - \x07extData\x12\x1c\n\tthumbnail\x18\x0b\x20\x01(\tR\tthumbnail\"+\n\x0c\ - RepeatedView\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.ViewR\x05items\ - \"\xd8\x01\n\x11CreateViewPayload\x12\x20\n\x0cbelong_to_id\x18\x01\x20\ - \x01(\tR\nbelongToId\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\ - \x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12\x1e\n\tthumbnail\x18\x04\ - \x20\x01(\tH\0R\tthumbnail\x12*\n\tdata_type\x18\x05\x20\x01(\x0e2\r.Vie\ - wDataTypeR\x08dataType\x12\x19\n\x08ext_data\x18\x06\x20\x01(\tR\x07extD\ - ataB\x12\n\x10one_of_thumbnail\"\xee\x01\n\x10CreateViewParams\x12\x20\n\ - \x0cbelong_to_id\x18\x01\x20\x01(\tR\nbelongToId\x12\x12\n\x04name\x18\ - \x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\ - \x12\x1c\n\tthumbnail\x18\x04\x20\x01(\tR\tthumbnail\x12*\n\tdata_type\ - \x18\x05\x20\x01(\x0e2\r.ViewDataTypeR\x08dataType\x12\x19\n\x08ext_data\ - \x18\x06\x20\x01(\tR\x07extData\x12\x17\n\x07view_id\x18\x07\x20\x01(\tR\ - \x06viewId\x12\x12\n\x04data\x18\x08\x20\x01(\tR\x04data\"\x1e\n\x06View\ - Id\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"&\n\x0eRepeatedViewI\ - d\x12\x14\n\x05items\x18\x01\x20\x03(\tR\x05items\"\xaa\x01\n\x11UpdateV\ - iewPayload\x12\x17\n\x07view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\ - \x04name\x18\x02\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\ - \x01(\tH\x01R\x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthu\ - mbnailB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnai\ - l\"\xa9\x01\n\x10UpdateViewParams\x12\x17\n\x07view_id\x18\x01\x20\x01(\ - \tR\x06viewId\x12\x14\n\x04name\x18\x02\x20\x01(\tH\0R\x04name\x12\x14\n\ - \x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\x12\x1e\n\tthumbnail\x18\x04\ - \x20\x01(\tH\x02R\tthumbnailB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\ - \x12\n\x10one_of_thumbnail*+\n\x0cViewDataType\x12\x0c\n\x08RichText\x10\ - \0\x12\r\n\tPlainText\x10\x01b\x06proto3\ + \x07extData\x12\x1c\n\tthumbnail\x18\x0b\x20\x01(\tR\tthumbnail\x12\x1f\ + \n\x0bplugin_type\x18\x0c\x20\x01(\x05R\npluginType\"+\n\x0cRepeatedView\ + \x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.ViewR\x05items\"\xf9\x01\n\ + \x11CreateViewPayload\x12\x20\n\x0cbelong_to_id\x18\x01\x20\x01(\tR\nbel\ + ongToId\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\ + \x18\x03\x20\x01(\tR\x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\0R\ + \tthumbnail\x12*\n\tdata_type\x18\x05\x20\x01(\x0e2\r.ViewDataTypeR\x08d\ + ataType\x12\x19\n\x08ext_data\x18\x06\x20\x01(\tR\x07extData\x12\x1f\n\ + \x0bplugin_type\x18\x07\x20\x01(\x05R\npluginTypeB\x12\n\x10one_of_thumb\ + nail\"\x8f\x02\n\x10CreateViewParams\x12\x20\n\x0cbelong_to_id\x18\x01\ + \x20\x01(\tR\nbelongToId\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\ + \x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12\x1c\n\tthumbnail\x18\ + \x04\x20\x01(\tR\tthumbnail\x12*\n\tdata_type\x18\x05\x20\x01(\x0e2\r.Vi\ + ewDataTypeR\x08dataType\x12\x19\n\x08ext_data\x18\x06\x20\x01(\tR\x07ext\ + Data\x12\x17\n\x07view_id\x18\x07\x20\x01(\tR\x06viewId\x12\x12\n\x04dat\ + a\x18\x08\x20\x01(\tR\x04data\x12\x1f\n\x0bplugin_type\x18\t\x20\x01(\ + \x05R\npluginType\"\x1e\n\x06ViewId\x12\x14\n\x05value\x18\x01\x20\x01(\ + \tR\x05value\"&\n\x0eRepeatedViewId\x12\x14\n\x05items\x18\x01\x20\x03(\ + \tR\x05items\"\xaa\x01\n\x11UpdateViewPayload\x12\x17\n\x07view_id\x18\ + \x01\x20\x01(\tR\x06viewId\x12\x14\n\x04name\x18\x02\x20\x01(\tH\0R\x04n\ + ame\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\x12\x1e\n\tthumbn\ + ail\x18\x04\x20\x01(\tH\x02R\tthumbnailB\r\n\x0bone_of_nameB\r\n\x0bone_\ + of_descB\x12\n\x10one_of_thumbnail\"\xa9\x01\n\x10UpdateViewParams\x12\ + \x17\n\x07view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\x04name\x18\ + \x02\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\ + \x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthumbnailB\r\n\ + \x0bone_of_nameB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnail*+\n\x0cVi\ + ewDataType\x12\x0c\n\x08RichText\x10\0\x12\r\n\tPlainText\x10\x01b\x06pr\ + oto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto b/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto index 824d4a8c2e..b938e004f4 100644 --- a/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto +++ b/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto @@ -12,6 +12,7 @@ message View { int64 create_time = 9; string ext_data = 10; string thumbnail = 11; + int32 plugin_type = 12; } message RepeatedView { repeated View items = 1; @@ -23,6 +24,7 @@ message CreateViewPayload { oneof one_of_thumbnail { string thumbnail = 4; }; ViewDataType data_type = 5; string ext_data = 6; + int32 plugin_type = 7; } message CreateViewParams { string belong_to_id = 1; @@ -33,6 +35,7 @@ message CreateViewParams { string ext_data = 6; string view_id = 7; string data = 8; + int32 plugin_type = 9; } message ViewId { string value = 1; diff --git a/shared-lib/flowy-folder-data-model/src/user_default.rs b/shared-lib/flowy-folder-data-model/src/user_default.rs index 6a3b1b92dc..b664557f2b 100644 --- a/shared-lib/flowy-folder-data-model/src/user_default.rs +++ b/shared-lib/flowy-folder-data-model/src/user_default.rs @@ -63,5 +63,6 @@ fn create_default_view(app_id: String, time: chrono::DateTime) -> View { create_time: time.timestamp(), ext_data: "".to_string(), thumbnail: "".to_string(), + plugin_type: 0, } } From 156d38179a3e45cd02f79ca8e31f8fe5a4d85a9d Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 1 Mar 2022 11:22:39 +0800 Subject: [PATCH 09/12] fix: add default value of serde --- frontend/app_flowy/lib/plugin/plugin.dart | 24 +++++++++++++++---- .../app_flowy/lib/plugin/src/sandbox.dart | 23 +++++++++++------- .../lib/startup/tasks/load_plugin.dart | 8 ++----- .../workspace/application/app/app_bloc.dart | 14 +++++++++-- .../infrastructure/repos/app_repo.dart | 4 +++- .../stack_page/blank/blank_page.dart | 10 ++++---- .../stack_page/doc/doc_stack_page.dart | 7 ++---- .../stack_page/trash/trash_page.dart | 10 ++++---- .../menu/widget/app/header/add_button.dart | 9 ++----- .../menu/widget/app/header/header.dart | 1 + .../src/entities/view.rs | 2 ++ 11 files changed, 70 insertions(+), 42 deletions(-) diff --git a/frontend/app_flowy/lib/plugin/plugin.dart b/frontend/app_flowy/lib/plugin/plugin.dart index a949d76985..b4b8ad9fd1 100644 --- a/frontend/app_flowy/lib/plugin/plugin.dart +++ b/frontend/app_flowy/lib/plugin/plugin.dart @@ -17,8 +17,6 @@ abstract class Plugin { String get pluginId; - bool get enable; - void dispose(); PluginDisplay get display; @@ -27,13 +25,17 @@ abstract class Plugin { abstract class PluginBuilder { Plugin build(dynamic data); - String get pluginName; + String get name; PluginType get pluginType; ViewDataType get dataType => ViewDataType.PlainText; } +abstract class PluginConfig { + bool get creatable => true; +} + abstract class PluginDisplay with NavigationItem { @override Widget get leftBarItem; @@ -46,8 +48,8 @@ abstract class PluginDisplay with NavigationItem { Widget buildWidget(); } -void registerPlugin({required PluginBuilder builder}) { - getIt().registerPlugin(builder.pluginType, builder); +void registerPlugin({required PluginBuilder builder, PluginConfig? config}) { + getIt().registerPlugin(builder.pluginType, builder, config: config); } Plugin makePlugin({required PluginType pluginType, dynamic data}) { @@ -55,6 +57,18 @@ Plugin makePlugin({required PluginType pluginType, dynamic data}) { return plugin; } +List pluginBuilders() { + final pluginBuilders = getIt().builders; + final pluginConfigs = getIt().pluginConfigs; + + return pluginBuilders.where( + (builder) { + final config = pluginConfigs[builder.pluginType]?.creatable; + return config ?? true; + }, + ).toList(); +} + enum FlowyPluginException { invalidData, } diff --git a/frontend/app_flowy/lib/plugin/src/sandbox.dart b/frontend/app_flowy/lib/plugin/src/sandbox.dart index cfaecb605e..5f1d63c287 100644 --- a/frontend/app_flowy/lib/plugin/src/sandbox.dart +++ b/frontend/app_flowy/lib/plugin/src/sandbox.dart @@ -6,7 +6,8 @@ import '../plugin.dart'; import 'runner.dart'; class PluginSandbox { - final LinkedHashMap _pluginMap = LinkedHashMap(); + final LinkedHashMap _pluginBuilders = LinkedHashMap(); + final Map _pluginConfigs = {}; late PluginRunner pluginRunner; PluginSandbox() { @@ -14,7 +15,7 @@ class PluginSandbox { } int indexOf(PluginType pluginType) { - final index = _pluginMap.keys.toList().indexWhere((ty) => ty == pluginType); + final index = _pluginBuilders.keys.toList().indexWhere((ty) => ty == pluginType); if (index == -1) { throw PlatformException(code: '-1', message: "Can't find the flowy plugin type: $pluginType"); } @@ -22,18 +23,24 @@ class PluginSandbox { } Plugin buildPlugin(PluginType pluginType, dynamic data) { - final plugin = _pluginMap[pluginType]!.build(data); + final plugin = _pluginBuilders[pluginType]!.build(data); return plugin; } - void registerPlugin(PluginType pluginType, PluginBuilder builder) { - if (_pluginMap.containsKey(pluginType)) { + void registerPlugin(PluginType pluginType, PluginBuilder builder, {PluginConfig? config}) { + if (_pluginBuilders.containsKey(pluginType)) { throw PlatformException(code: '-1', message: "$pluginType was registered before"); } - _pluginMap[pluginType] = builder; + _pluginBuilders[pluginType] = builder; + + if (config != null) { + _pluginConfigs[pluginType] = config; + } } - List get supportPluginTypes => _pluginMap.keys.toList(); + List get supportPluginTypes => _pluginBuilders.keys.toList(); - List get builders => _pluginMap.values.toList(); + List get builders => _pluginBuilders.values.toList(); + + Map get pluginConfigs => _pluginConfigs; } diff --git a/frontend/app_flowy/lib/startup/tasks/load_plugin.dart b/frontend/app_flowy/lib/startup/tasks/load_plugin.dart index 0542cbda29..5899a109b5 100644 --- a/frontend/app_flowy/lib/startup/tasks/load_plugin.dart +++ b/frontend/app_flowy/lib/startup/tasks/load_plugin.dart @@ -23,18 +23,14 @@ extension FlowyDefaultPluginExt on DefaultPlugin { } } -bool isDefaultPlugin(PluginType pluginType) { - return DefaultPlugin.values.map((e) => e.type()).contains(pluginType); -} - class PluginLoadTask extends LaunchTask { @override LaunchTaskType get type => LaunchTaskType.dataProcessing; @override Future initialize(LaunchContext context) async { - registerPlugin(builder: BlankPluginBuilder()); - registerPlugin(builder: TrashPluginBuilder()); + registerPlugin(builder: BlankPluginBuilder(), config: BlankPluginConfig()); + registerPlugin(builder: TrashPluginBuilder(), config: TrashPluginConfig()); registerPlugin(builder: DocumentPluginBuilder()); } } diff --git a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart index 49539cb2d0..2f9cfa355c 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart @@ -22,7 +22,12 @@ class AppBloc extends Bloc { ); await _fetchViews(emit); }, createView: (CreateView value) async { - final viewOrFailed = await repo.createView(name: value.name, desc: value.desc, dataType: value.dataType); + final viewOrFailed = await repo.createView( + name: value.name, + desc: value.desc, + dataType: value.dataType, + pluginType: value.pluginType, + ); viewOrFailed.fold( (view) => emit(state.copyWith( latestCreatedView: view, @@ -96,7 +101,12 @@ class AppBloc extends Bloc { @freezed class AppEvent with _$AppEvent { const factory AppEvent.initial() = Initial; - const factory AppEvent.createView(String name, String desc, PluginDataType dataType) = CreateView; + const factory AppEvent.createView( + String name, + String desc, + PluginDataType dataType, + PluginType pluginType, + ) = CreateView; const factory AppEvent.delete() = Delete; const factory AppEvent.rename(String newName) = Rename; const factory AppEvent.didReceiveViews(List views) = ReceiveViews; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart index f443605365..d060a32b05 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart @@ -28,12 +28,14 @@ class AppRepository { required String name, required String desc, required PluginDataType dataType, + required PluginType pluginType, }) { final request = CreateViewPayload.create() ..belongToId = appId ..name = name ..desc = desc - ..dataType = dataType; + ..dataType = dataType + ..pluginType = pluginType; return FolderEventCreateView(request).send(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart index 69b8e0b9fd..05148c34cf 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart @@ -14,12 +14,17 @@ class BlankPluginBuilder extends PluginBuilder { } @override - String get pluginName => "Blank"; + String get name => "Blank"; @override PluginType get pluginType => DefaultPlugin.blank.type(); } +class BlankPluginConfig implements PluginConfig { + @override + bool get creatable => false; +} + class BlankPagePlugin implements Plugin { final PluginType _pluginType; BlankPagePlugin({ @@ -32,9 +37,6 @@ class BlankPagePlugin implements Plugin { @override PluginDisplay get display => BlankPagePluginDisplay(); - @override - bool get enable => true; - @override String get pluginId => "BlankStack"; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart index 1c4f9711e3..74280fa67f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart @@ -25,7 +25,7 @@ import 'package:provider/provider.dart'; import 'document_page.dart'; -class DocumentPluginBuilder implements PluginBuilder { +class DocumentPluginBuilder extends PluginBuilder { @override Plugin build(dynamic data) { if (data is View) { @@ -36,7 +36,7 @@ class DocumentPluginBuilder implements PluginBuilder { } @override - String get pluginName => "Doc"; + String get name => "Doc"; @override PluginType get pluginType => DefaultPlugin.quillEditor.type(); @@ -74,9 +74,6 @@ class DocumentPlugin implements Plugin { @override PluginDisplay get display => DocumentPluginDisplay(view: _view); - @override - bool get enable => true; - @override PluginType get pluginType => _pluginType; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart index e2c71f1cda..7fcf90da5f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart @@ -28,12 +28,17 @@ class TrashPluginBuilder extends PluginBuilder { } @override - String get pluginName => "Trash"; + String get name => "Trash"; @override PluginType get pluginType => DefaultPlugin.trash.type(); } +class TrashPluginConfig implements PluginConfig { + @override + bool get creatable => false; +} + class TrashPlugin implements Plugin { final PluginType _pluginType; @@ -45,9 +50,6 @@ class TrashPlugin implements Plugin { @override PluginDisplay get display => TrashPluginDisplay(); - @override - bool get enable => true; - @override String get pluginId => "TrashStack"; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart index 90dc29d6c7..4b7a00c21f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart @@ -44,12 +44,7 @@ class ActionList { const ActionList({required this.anchorContext, required this.onSelected}); void show(BuildContext buildContext) { - final items = getIt() - .builders - .where( - (builder) => !isDefaultPlugin(builder.pluginType), - ) - .map( + final items = pluginBuilders().map( (pluginBuilder) { return CreateItem( pluginBuilder: pluginBuilder, @@ -94,7 +89,7 @@ class CreateItem extends StatelessWidget { return GestureDetector( onTap: () => onSelected(pluginBuilder), child: FlowyText.medium( - pluginBuilder.pluginName, + pluginBuilder.name, color: theme.textColor, fontSize: 12, ).padding(horizontal: 10, vertical: 6), diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart index 565b6af717..53e9720f18 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart @@ -107,6 +107,7 @@ class MenuAppHeader extends StatelessWidget { LocaleKeys.menuAppHeader_defaultNewPageName.tr(), "", pluginBuilder.dataType, + pluginBuilder.pluginType, )); }, ).padding(right: MenuAppSizes.headerPadding), diff --git a/shared-lib/flowy-folder-data-model/src/entities/view.rs b/shared-lib/flowy-folder-data-model/src/entities/view.rs index 8a90f0fb9f..3af0943dc0 100644 --- a/shared-lib/flowy-folder-data-model/src/entities/view.rs +++ b/shared-lib/flowy-folder-data-model/src/entities/view.rs @@ -44,9 +44,11 @@ pub struct View { pub create_time: i64, #[pb(index = 10)] + #[serde(default)] pub ext_data: String, #[pb(index = 11)] + #[serde(default)] pub thumbnail: String, #[pb(index = 12)] From 7a36fed778acfd272a812f8cf1dcce69b9924915 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 1 Mar 2022 16:05:45 +0800 Subject: [PATCH 10/12] refactor: remove domain folder --- frontend/app_flowy/lib/plugin/plugin.dart | 15 +- .../lib/startup/tasks/load_plugin.dart | 6 +- .../edit_pannel}/edit_context.dart | 0 .../edit_pannel/edit_pannel_bloc.dart | 2 +- .../workspace/application/home/home_bloc.dart | 2 +- .../view}/view_ext.dart | 0 .../domain/edit_action/app_edit.dart | 29 --- .../domain/edit_action/view_edit.dart | 34 --- .../domain/page_stack/page_stack.dart | 111 --------- .../infrastructure/deps_resolver.dart | 2 +- .../presentation/home/home_screen.dart | 8 +- .../presentation/home/home_stack.dart | 213 ++++++++++++++++++ .../menu}/app/create_button.dart | 0 .../menu}/app/header/add_button.dart | 5 +- .../menu}/app/header/header.dart | 28 ++- .../menu}/app/header/right_click_action.dart | 3 +- .../widget => home/menu}/app/menu_app.dart | 3 +- .../menu}/app/section/disclosure_action.dart | 3 +- .../menu}/app/section/item.dart | 36 ++- .../menu}/app/section/section.dart | 7 +- .../menu}/favorite/favorite.dart | 0 .../widget => home/menu}/favorite/header.dart | 0 .../menu}/favorite/section.dart | 0 .../{widgets => home}/menu/menu.dart | 66 +++--- .../menu/widget => home/menu}/menu_user.dart | 0 .../presentation/home/navigation.dart | 11 +- .../blank/blank.dart} | 17 +- .../doc/document.dart} | 33 ++- .../doc/src}/document_page.dart | 2 +- .../doc => plugins/doc/src}/styles.dart | 2 +- .../doc/src}/widget/banner.dart | 0 .../doc/src/widget}/style_widgets.dart | 0 .../doc/src}/widget/toolbar/check_button.dart | 0 .../doc/src}/widget/toolbar/color_picker.dart | 0 .../src}/widget/toolbar/header_button.dart | 0 .../src}/widget/toolbar/history_button.dart | 0 .../doc/src}/widget/toolbar/image_button.dart | 0 .../doc/src}/widget/toolbar/link_button.dart | 0 .../src}/widget/toolbar/toggle_button.dart | 0 .../doc/src}/widget/toolbar/tool_bar.dart | 2 +- .../widget/toolbar/toolbar_icon_button.dart | 0 .../trash/menu.dart} | 4 +- .../widget => plugins/trash/src}/sizes.dart | 0 .../trash/src}/trash_cell.dart | 0 .../trash/src}/trash_header.dart | 0 .../trash/trash.dart} | 20 +- .../presentation/stack_page/home_stack.dart | 86 ------- .../widgets/edit_pannel/edit_pannel.dart | 2 +- .../emoji_picker/src/emoji_button.dart | 3 +- .../widgets/float_bubble/question_bubble.dart | 2 +- .../presentation/widgets/home_top_bar.dart | 40 ---- .../presentation/widgets/menu/prelude.dart | 1 - .../widgets/menu/widget/top_bar.dart | 36 --- .../presentation/widgets/prelude.dart | 5 - .../flowy-folder/tests/workspace/helper.rs | 1 + frontend/rust-lib/flowy-test/src/helper.rs | 1 + 56 files changed, 396 insertions(+), 445 deletions(-) rename frontend/app_flowy/lib/workspace/{domain => application/edit_pannel}/edit_context.dart (100%) rename frontend/app_flowy/lib/workspace/{domain => application/view}/view_ext.dart (100%) delete mode 100644 frontend/app_flowy/lib/workspace/domain/edit_action/app_edit.dart delete mode 100644 frontend/app_flowy/lib/workspace/domain/edit_action/view_edit.dart delete mode 100644 frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/home/home_stack.dart rename frontend/app_flowy/lib/workspace/presentation/{widgets/menu/widget => home/menu}/app/create_button.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{widgets/menu/widget => home/menu}/app/header/add_button.dart (93%) rename frontend/app_flowy/lib/workspace/presentation/{widgets/menu/widget => home/menu}/app/header/header.dart (87%) rename frontend/app_flowy/lib/workspace/presentation/{widgets/menu/widget => home/menu}/app/header/right_click_action.dart (94%) rename frontend/app_flowy/lib/workspace/presentation/{widgets/menu/widget => home/menu}/app/menu_app.dart (96%) rename frontend/app_flowy/lib/workspace/presentation/{widgets/menu/widget => home/menu}/app/section/disclosure_action.dart (96%) rename frontend/app_flowy/lib/workspace/presentation/{widgets/menu/widget => home/menu}/app/section/item.dart (77%) rename frontend/app_flowy/lib/workspace/presentation/{widgets/menu/widget => home/menu}/app/section/section.dart (93%) rename frontend/app_flowy/lib/workspace/presentation/{widgets/menu/widget => home/menu}/favorite/favorite.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{widgets/menu/widget => home/menu}/favorite/header.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{widgets/menu/widget => home/menu}/favorite/section.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{widgets => home}/menu/menu.dart (67%) rename frontend/app_flowy/lib/workspace/presentation/{widgets/menu/widget => home/menu}/menu_user.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/blank/blank_page.dart => plugins/blank/blank.dart} (82%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/doc/doc_stack_page.dart => plugins/doc/document.dart} (91%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/doc => plugins/doc/src}/document_page.dart (98%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/doc => plugins/doc/src}/styles.dart (98%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/doc => plugins/doc/src}/widget/banner.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/doc/widget/style_widgets => plugins/doc/src/widget}/style_widgets.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/doc => plugins/doc/src}/widget/toolbar/check_button.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/doc => plugins/doc/src}/widget/toolbar/color_picker.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/doc => plugins/doc/src}/widget/toolbar/header_button.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/doc => plugins/doc/src}/widget/toolbar/history_button.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/doc => plugins/doc/src}/widget/toolbar/image_button.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/doc => plugins/doc/src}/widget/toolbar/link_button.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/doc => plugins/doc/src}/widget/toolbar/toggle_button.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/doc => plugins/doc/src}/widget/toolbar/tool_bar.dart (98%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/doc => plugins/doc/src}/widget/toolbar/toolbar_icon_button.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{widgets/menu/widget/menu_trash.dart => plugins/trash/menu.dart} (93%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/trash/widget => plugins/trash/src}/sizes.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/trash/widget => plugins/trash/src}/trash_cell.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/trash/widget => plugins/trash/src}/trash_header.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/{stack_page/trash/trash_page.dart => plugins/trash/trash.dart} (93%) delete mode 100644 frontend/app_flowy/lib/workspace/presentation/stack_page/home_stack.dart delete mode 100644 frontend/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart delete mode 100644 frontend/app_flowy/lib/workspace/presentation/widgets/menu/prelude.dart delete mode 100644 frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/top_bar.dart delete mode 100644 frontend/app_flowy/lib/workspace/presentation/widgets/prelude.dart diff --git a/frontend/app_flowy/lib/plugin/plugin.dart b/frontend/app_flowy/lib/plugin/plugin.dart index b4b8ad9fd1..d46e14746f 100644 --- a/frontend/app_flowy/lib/plugin/plugin.dart +++ b/frontend/app_flowy/lib/plugin/plugin.dart @@ -2,7 +2,7 @@ library flowy_plugin; import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; +import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flutter/widgets.dart'; @@ -12,20 +12,24 @@ typedef PluginType = int; typedef PluginDataType = ViewDataType; +typedef PluginId = String; + abstract class Plugin { + PluginId get pluginId; + + PluginDisplay get pluginDisplay; + PluginType get pluginType; - String get pluginId; + ChangeNotifier? get displayNotifier => null; void dispose(); - - PluginDisplay get display; } abstract class PluginBuilder { Plugin build(dynamic data); - String get name; + String get menuName; PluginType get pluginType; @@ -60,7 +64,6 @@ Plugin makePlugin({required PluginType pluginType, dynamic data}) { List pluginBuilders() { final pluginBuilders = getIt().builders; final pluginConfigs = getIt().pluginConfigs; - return pluginBuilders.where( (builder) { final config = pluginConfigs[builder.pluginType]?.creatable; diff --git a/frontend/app_flowy/lib/startup/tasks/load_plugin.dart b/frontend/app_flowy/lib/startup/tasks/load_plugin.dart index 5899a109b5..650dd49d22 100644 --- a/frontend/app_flowy/lib/startup/tasks/load_plugin.dart +++ b/frontend/app_flowy/lib/startup/tasks/load_plugin.dart @@ -1,8 +1,8 @@ import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dart'; -import 'package:app_flowy/workspace/presentation/stack_page/doc/doc_stack_page.dart'; -import 'package:app_flowy/workspace/presentation/stack_page/trash/trash_page.dart'; +import 'package:app_flowy/workspace/presentation/plugins/blank/blank.dart'; +import 'package:app_flowy/workspace/presentation/plugins/doc/document.dart'; +import 'package:app_flowy/workspace/presentation/plugins/trash/trash.dart'; enum DefaultPlugin { quillEditor, diff --git a/frontend/app_flowy/lib/workspace/domain/edit_context.dart b/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_context.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/domain/edit_context.dart rename to frontend/app_flowy/lib/workspace/application/edit_pannel/edit_context.dart diff --git a/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_pannel_bloc.dart b/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_pannel_bloc.dart index e8bc319e3b..0ae2e8326a 100644 --- a/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_pannel_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_pannel_bloc.dart @@ -1,4 +1,4 @@ -import 'package:app_flowy/workspace/domain/edit_context.dart'; +import 'package:app_flowy/workspace/application/edit_pannel/edit_context.dart'; import 'package:dartz/dartz.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; // ignore: import_of_legacy_library_into_null_safe diff --git a/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart b/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart index 385735ed44..e4b0482989 100644 --- a/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart @@ -1,4 +1,4 @@ -import 'package:app_flowy/workspace/domain/edit_context.dart'; +import 'package:app_flowy/workspace/application/edit_pannel/edit_context.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:dartz/dartz.dart'; diff --git a/frontend/app_flowy/lib/workspace/domain/view_ext.dart b/frontend/app_flowy/lib/workspace/application/view/view_ext.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/domain/view_ext.dart rename to frontend/app_flowy/lib/workspace/application/view/view_ext.dart diff --git a/frontend/app_flowy/lib/workspace/domain/edit_action/app_edit.dart b/frontend/app_flowy/lib/workspace/domain/edit_action/app_edit.dart deleted file mode 100644 index 7ce5d3682c..0000000000 --- a/frontend/app_flowy/lib/workspace/domain/edit_action/app_edit.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:easy_localization/easy_localization.dart'; -import 'package:flowy_infra/image.dart'; -import 'package:flutter/material.dart'; -import 'package:app_flowy/generated/locale_keys.g.dart'; - -enum AppDisclosureAction { - rename, - delete, -} - -extension AppDisclosureExtension on AppDisclosureAction { - String get name { - switch (this) { - case AppDisclosureAction.rename: - return LocaleKeys.disclosureAction_rename.tr(); - case AppDisclosureAction.delete: - return LocaleKeys.disclosureAction_delete.tr(); - } - } - - Widget get icon { - switch (this) { - case AppDisclosureAction.rename: - return svg('editor/edit', color: const Color(0xffe5e5e5)); - case AppDisclosureAction.delete: - return svg('editor/delete', color: const Color(0xffe5e5e5)); - } - } -} diff --git a/frontend/app_flowy/lib/workspace/domain/edit_action/view_edit.dart b/frontend/app_flowy/lib/workspace/domain/edit_action/view_edit.dart deleted file mode 100644 index 31a3c14307..0000000000 --- a/frontend/app_flowy/lib/workspace/domain/edit_action/view_edit.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:easy_localization/easy_localization.dart'; -import 'package:flowy_infra/image.dart'; -import 'package:flutter/material.dart'; -import 'package:app_flowy/generated/locale_keys.g.dart'; - -enum ViewDisclosureAction { - rename, - delete, - duplicate, -} - -extension ViewDisclosureExtension on ViewDisclosureAction { - String get name { - switch (this) { - case ViewDisclosureAction.rename: - return LocaleKeys.disclosureAction_rename.tr(); - case ViewDisclosureAction.delete: - return LocaleKeys.disclosureAction_delete.tr(); - case ViewDisclosureAction.duplicate: - return LocaleKeys.disclosureAction_duplicate.tr(); - } - } - - Widget get icon { - switch (this) { - case ViewDisclosureAction.rename: - return svg('editor/edit', color: const Color(0xff999999)); - case ViewDisclosureAction.delete: - return svg('editor/delete', color: const Color(0xff999999)); - case ViewDisclosureAction.duplicate: - return svg('editor/copy', color: const Color(0xff999999)); - } - } -} diff --git a/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart b/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart deleted file mode 100644 index 9023bd4cc3..0000000000 --- a/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart +++ /dev/null @@ -1,111 +0,0 @@ -import 'package:app_flowy/plugin/plugin.dart'; -import 'package:app_flowy/startup/tasks/load_plugin.dart'; -import 'package:flowy_infra/notifier.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/presentation/stack_page/home_stack.dart'; -import 'package:app_flowy/workspace/presentation/widgets/prelude.dart'; - -typedef NavigationCallback = void Function(String id); - -abstract class NavigationItem { - Widget get leftBarItem; - Widget? get rightBarItem => null; - - NavigationCallback get action => (id) { - getIt().setStackWithId(id); - }; -} - -abstract class HomeStackContext with NavigationItem { - List get navigationItems; - - @override - Widget get leftBarItem; - - @override - Widget? get rightBarItem; - - ValueNotifier get isUpdated; - - Widget buildWidget(); - - void dispose(); -} - -class HomeStackNotifier extends ChangeNotifier { - Plugin _plugin; - PublishNotifier collapsedNotifier = PublishNotifier(); - - Widget get titleWidget => _plugin.display.leftBarItem; - - HomeStackNotifier({Plugin? plugin}) : _plugin = plugin ?? makePlugin(pluginType: DefaultPlugin.blank.type()); - - set plugin(Plugin newPlugin) { - if (newPlugin.pluginId == _plugin.pluginId) { - return; - } - - // stackContext.isUpdated.removeListener(notifyListeners); - _plugin.dispose(); - - _plugin = newPlugin; - // stackContext.isUpdated.addListener(notifyListeners); - notifyListeners(); - } - - Plugin get plugin => _plugin; -} - -// HomeStack is initialized as singleton to controll the page stack. -class HomeStackManager { - final HomeStackNotifier _notifier = HomeStackNotifier(); - HomeStackManager(); - - Widget title() { - return _notifier.plugin.display.leftBarItem; - } - - PublishNotifier get collapsedNotifier => _notifier.collapsedNotifier; - - void setPlugin(Plugin newPlugin) { - _notifier.plugin = newPlugin; - } - - void setStackWithId(String id) {} - - Widget stackTopBar() { - return MultiProvider( - providers: [ - ChangeNotifierProvider.value(value: _notifier), - ], - child: Selector( - selector: (context, notifier) => notifier.titleWidget, - builder: (context, widget, child) { - return const HomeTopBar(); - }, - ), - ); - } - - Widget stackWidget() { - return MultiProvider( - providers: [ - ChangeNotifierProvider.value(value: _notifier), - ], - child: Consumer(builder: (ctx, HomeStackNotifier notifier, child) { - return FadingIndexedStack( - index: getIt().indexOf(notifier.plugin.pluginType), - children: getIt().supportPluginTypes.map((pluginType) { - if (pluginType == notifier.plugin.pluginType) { - return notifier.plugin.display.buildWidget(); - } else { - return const BlankStackPage(); - } - }).toList(), - ); - }), - ); - } -} diff --git a/frontend/app_flowy/lib/workspace/infrastructure/deps_resolver.dart b/frontend/app_flowy/lib/workspace/infrastructure/deps_resolver.dart index 8983c4e41e..55b9e27f80 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/deps_resolver.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/deps_resolver.dart @@ -7,12 +7,12 @@ import 'package:app_flowy/workspace/application/menu/menu_user_bloc.dart'; import 'package:app_flowy/workspace/application/trash/trash_bloc.dart'; import 'package:app_flowy/workspace/application/view/view_bloc.dart'; import 'package:app_flowy/workspace/application/workspace/welcome_bloc.dart'; -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/infrastructure/repos/app_repo.dart'; import 'package:app_flowy/workspace/infrastructure/repos/trash_repo.dart'; import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart'; import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart'; import 'package:app_flowy/workspace/infrastructure/repos/workspace_repo.dart'; +import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart b/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart index 174727c2df..88ec0f5ad6 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart @@ -1,10 +1,8 @@ import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/workspace/application/home/home_bloc.dart'; import 'package:app_flowy/workspace/application/home/home_listen_bloc.dart'; -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; -import 'package:app_flowy/workspace/presentation/stack_page/home_stack.dart'; +import 'package:app_flowy/workspace/presentation/widgets/edit_pannel/pannel_animation.dart'; import 'package:app_flowy/workspace/presentation/widgets/float_bubble/question_bubble.dart'; -import 'package:app_flowy/workspace/presentation/widgets/prelude.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_infra_ui/style_widget/container.dart'; @@ -14,7 +12,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; +import '../widgets/edit_pannel/edit_pannel.dart'; + import 'home_layout.dart'; +import 'home_stack.dart'; +import 'menu/menu.dart'; class HomeScreen extends StatefulWidget { static GlobalKey scaffoldKey = GlobalKey(); diff --git a/frontend/app_flowy/lib/workspace/presentation/home/home_stack.dart b/frontend/app_flowy/lib/workspace/presentation/home/home_stack.dart new file mode 100644 index 0000000000..6127440a89 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/home/home_stack.dart @@ -0,0 +1,213 @@ +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/presentation/home/home_screen.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:time/time.dart'; +import 'package:fluttertoast/fluttertoast.dart'; + +import 'package:app_flowy/plugin/plugin.dart'; +import 'package:app_flowy/startup/tasks/load_plugin.dart'; +import 'package:app_flowy/workspace/presentation/plugins/blank/blank.dart'; +import 'package:app_flowy/workspace/presentation/home/home_sizes.dart'; +import 'package:app_flowy/workspace/presentation/home/navigation.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flowy_infra_ui/style_widget/extension.dart'; +import 'package:flowy_infra/notifier.dart'; + +typedef NavigationCallback = void Function(String id); + +late FToast fToast; + +class HomeStack extends StatelessWidget { + static GlobalKey scaffoldKey = GlobalKey(); + // final Size size; + const HomeStack({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + Log.info('HomePage build'); + final theme = context.watch(); + return Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + getIt().stackTopBar(), + Expanded( + child: Container( + color: theme.surface, + child: FocusTraversalGroup( + child: getIt().stackWidget(), + ), + ), + ), + ], + ); + } +} + +class FadingIndexedStack extends StatefulWidget { + final int index; + final List children; + final Duration duration; + + const FadingIndexedStack({ + Key? key, + required this.index, + required this.children, + this.duration = const Duration( + milliseconds: 250, + ), + }) : super(key: key); + + @override + _FadingIndexedStackState createState() => _FadingIndexedStackState(); +} + +class _FadingIndexedStackState extends State { + double _targetOpacity = 1; + + @override + void initState() { + super.initState(); + fToast = FToast(); + fToast.init(HomeScreen.scaffoldKey.currentState!.context); + } + + @override + void didUpdateWidget(FadingIndexedStack oldWidget) { + if (oldWidget.index == widget.index) return; + setState(() => _targetOpacity = 0); + Future.delayed(1.milliseconds, () => setState(() => _targetOpacity = 1)); + super.didUpdateWidget(oldWidget); + } + + @override + Widget build(BuildContext context) { + return TweenAnimationBuilder( + duration: _targetOpacity > 0 ? widget.duration : 0.milliseconds, + tween: Tween(begin: 0, end: _targetOpacity), + builder: (_, value, child) { + return Opacity(opacity: value, child: child); + }, + child: IndexedStack(index: widget.index, children: widget.children), + ); + } +} + +abstract class NavigationItem { + Widget get leftBarItem; + Widget? get rightBarItem => null; + + NavigationCallback get action => (id) { + getIt().setStackWithId(id); + }; +} + +class HomeStackNotifier extends ChangeNotifier { + Plugin _plugin; + PublishNotifier collapsedNotifier = PublishNotifier(); + + Widget get titleWidget => _plugin.pluginDisplay.leftBarItem; + + HomeStackNotifier({Plugin? plugin}) : _plugin = plugin ?? makePlugin(pluginType: DefaultPlugin.blank.type()); + + set plugin(Plugin newPlugin) { + if (newPlugin.pluginId == _plugin.pluginId) { + return; + } + + _plugin.displayNotifier?.removeListener(notifyListeners); + _plugin.dispose(); + + _plugin = newPlugin; + _plugin.displayNotifier?.addListener(notifyListeners); + notifyListeners(); + } + + Plugin get plugin => _plugin; +} + +// HomeStack is initialized as singleton to controll the page stack. +class HomeStackManager { + final HomeStackNotifier _notifier = HomeStackNotifier(); + HomeStackManager(); + + Widget title() { + return _notifier.plugin.pluginDisplay.leftBarItem; + } + + PublishNotifier get collapsedNotifier => _notifier.collapsedNotifier; + + void setPlugin(Plugin newPlugin) { + _notifier.plugin = newPlugin; + } + + void setStackWithId(String id) {} + + Widget stackTopBar() { + return MultiProvider( + providers: [ + ChangeNotifierProvider.value(value: _notifier), + ], + child: Selector( + selector: (context, notifier) => notifier.titleWidget, + builder: (context, widget, child) { + return const HomeTopBar(); + }, + ), + ); + } + + Widget stackWidget() { + return MultiProvider( + providers: [ + ChangeNotifierProvider.value(value: _notifier), + ], + child: Consumer(builder: (ctx, HomeStackNotifier notifier, child) { + return FadingIndexedStack( + index: getIt().indexOf(notifier.plugin.pluginType), + children: getIt().supportPluginTypes.map((pluginType) { + if (pluginType == notifier.plugin.pluginType) { + return notifier.plugin.pluginDisplay.buildWidget(); + } else { + return const BlankStackPage(); + } + }).toList(), + ); + }), + ); + } +} + +class HomeTopBar extends StatelessWidget { + const HomeTopBar({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return Container( + color: theme.surface, + height: HomeSizes.topBarHeight, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const FlowyNavigation(), + const HSpace(16), + ChangeNotifierProvider.value( + value: Provider.of(context, listen: false), + child: Consumer( + builder: (BuildContext context, HomeStackNotifier notifier, Widget? child) { + return notifier.plugin.pluginDisplay.rightBarItem ?? const SizedBox(); + }, + ), + ) // _renderMoreButton(), + ], + ) + .padding( + horizontal: HomeInsets.topBarTitlePadding, + ) + .bottomBorder(color: Colors.grey.shade300), + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/create_button.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/create_button.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/create_button.dart rename to frontend/app_flowy/lib/workspace/presentation/home/menu/app/create_button.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/add_button.dart similarity index 93% rename from frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart rename to frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/add_button.dart index 4b7a00c21f..9e696e8a73 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/add_button.dart @@ -1,7 +1,4 @@ import 'package:app_flowy/plugin/plugin.dart'; -import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/startup/tasks/load_plugin.dart'; -import 'package:app_flowy/workspace/domain/view_ext.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -89,7 +86,7 @@ class CreateItem extends StatelessWidget { return GestureDetector( onTap: () => onSelected(pluginBuilder), child: FlowyText.medium( - pluginBuilder.name, + pluginBuilder.menuName, color: theme.textColor, fontSize: 12, ).padding(horizontal: 10, vertical: 6), diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart similarity index 87% rename from frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart rename to frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart index 53e9720f18..58ebabc0c2 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart @@ -1,4 +1,3 @@ -import 'package:app_flowy/workspace/domain/edit_action/app_edit.dart'; import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:expandable/expandable.dart'; @@ -13,6 +12,8 @@ import 'package:app_flowy/workspace/application/app/app_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:dartz/dartz.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:flowy_infra/image.dart'; + import '../menu_app.dart'; import 'add_button.dart'; import 'right_click_action.dart'; @@ -134,3 +135,28 @@ class MenuAppHeader extends StatelessWidget { }); } } + +enum AppDisclosureAction { + rename, + delete, +} + +extension AppDisclosureExtension on AppDisclosureAction { + String get name { + switch (this) { + case AppDisclosureAction.rename: + return LocaleKeys.disclosureAction_rename.tr(); + case AppDisclosureAction.delete: + return LocaleKeys.disclosureAction_delete.tr(); + } + } + + Widget get icon { + switch (this) { + case AppDisclosureAction.rename: + return svg('editor/edit', color: const Color(0xffe5e5e5)); + case AppDisclosureAction.delete: + return svg('editor/delete', color: const Color(0xffe5e5e5)); + } + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/right_click_action.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/right_click_action.dart similarity index 94% rename from frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/right_click_action.dart rename to frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/right_click_action.dart index 9ff429706c..8938443236 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/right_click_action.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/right_click_action.dart @@ -1,9 +1,10 @@ -import 'package:app_flowy/workspace/domain/edit_action/app_edit.dart'; import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart'; import 'package:dartz/dartz.dart' as dartz; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; +import 'header.dart'; + class AppDisclosureActionSheet with ActionList implements FlowyOverlayDelegate { final Function(dartz.Option) onSelected; final _items = AppDisclosureAction.values.map((action) => DisclosureActionWrapper(action)).toList(); diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/menu_app.dart similarity index 96% rename from frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart rename to frontend/app_flowy/lib/workspace/presentation/home/menu/app/menu_app.dart index f5de26dc13..41ba6ab4d1 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/menu_app.dart @@ -1,6 +1,5 @@ import 'package:app_flowy/workspace/application/appearance.dart'; -import 'package:app_flowy/workspace/presentation/widgets/menu/menu.dart'; -import 'package:app_flowy/workspace/presentation/widgets/menu/widget/app/header/header.dart'; +import 'package:app_flowy/workspace/presentation/home/menu/menu.dart'; import 'package:expandable/expandable.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/disclosure_action.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart similarity index 96% rename from frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/disclosure_action.dart rename to frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart index 63b79dabe7..a2cd2edcac 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/disclosure_action.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart @@ -1,4 +1,3 @@ -import 'package:app_flowy/workspace/domain/edit_action/view_edit.dart'; import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart'; import 'package:dartz/dartz.dart' as dartz; import 'package:flowy_infra/image.dart'; @@ -8,6 +7,8 @@ import 'package:flutter/material.dart'; import 'package:flowy_infra/theme.dart'; import 'package:provider/provider.dart'; +import 'item.dart'; + // [[Widget: LifeCycle]] // https://flutterbyexample.com/lesson/stateful-widget-lifecycle class ViewDisclosureButton extends StatelessWidget diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart similarity index 77% rename from frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart rename to frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart index ad604a295a..f818b5839f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/view/view_bloc.dart'; -import 'package:app_flowy/workspace/domain/edit_action/view_edit.dart'; -import 'package:app_flowy/workspace/domain/view_ext.dart'; +import 'package:app_flowy/workspace/application/view/view_ext.dart'; +import 'package:app_flowy/workspace/presentation/home/menu/menu.dart'; import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart'; import 'package:dartz/dartz.dart' as dartz; import 'package:easy_localization/easy_localization.dart'; @@ -13,8 +13,8 @@ import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; -import 'package:app_flowy/workspace/presentation/widgets/menu/widget/app/menu_app.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:flowy_infra/image.dart'; import 'disclosure_action.dart'; @@ -104,3 +104,33 @@ class ViewSectionItem extends StatelessWidget { }); } } + +enum ViewDisclosureAction { + rename, + delete, + duplicate, +} + +extension ViewDisclosureExtension on ViewDisclosureAction { + String get name { + switch (this) { + case ViewDisclosureAction.rename: + return LocaleKeys.disclosureAction_rename.tr(); + case ViewDisclosureAction.delete: + return LocaleKeys.disclosureAction_delete.tr(); + case ViewDisclosureAction.duplicate: + return LocaleKeys.disclosureAction_duplicate.tr(); + } + } + + Widget get icon { + switch (this) { + case ViewDisclosureAction.rename: + return svg('editor/edit', color: const Color(0xff999999)); + case ViewDisclosureAction.delete: + return svg('editor/delete', color: const Color(0xff999999)); + case ViewDisclosureAction.duplicate: + return svg('editor/copy', color: const Color(0xff999999)); + } + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/section.dart similarity index 93% rename from frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart rename to frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/section.dart index be3ed9ab33..dcb2d454b9 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/section.dart @@ -1,8 +1,7 @@ import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; -import 'package:app_flowy/workspace/domain/view_ext.dart'; -import 'package:app_flowy/workspace/presentation/widgets/menu/menu.dart'; -import 'package:app_flowy/workspace/presentation/widgets/menu/widget/app/menu_app.dart'; +import 'package:app_flowy/workspace/application/view/view_ext.dart'; +import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; +import 'package:app_flowy/workspace/presentation/home/menu/menu.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/favorite/favorite.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/favorite/favorite.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/favorite/favorite.dart rename to frontend/app_flowy/lib/workspace/presentation/home/menu/favorite/favorite.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/favorite/header.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/favorite/header.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/favorite/header.dart rename to frontend/app_flowy/lib/workspace/presentation/home/menu/favorite/header.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/favorite/section.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/favorite/section.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/favorite/section.dart rename to frontend/app_flowy/lib/workspace/presentation/home/menu/favorite/section.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/menu.dart similarity index 67% rename from frontend/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart rename to frontend/app_flowy/lib/workspace/presentation/home/menu/menu.dart index f76f226795..bf3e66168b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/menu.dart @@ -1,4 +1,8 @@ -import 'package:app_flowy/workspace/presentation/widgets/menu/widget/top_bar.dart'; +export './app/header/header.dart'; +export './app/menu_app.dart'; + +import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; +import 'package:app_flowy/workspace/presentation/plugins/trash/menu.dart'; import 'package:flowy_infra/notifier.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme.dart'; @@ -15,32 +19,13 @@ import 'package:expandable/expandable.dart'; import 'package:flowy_infra/time/duration.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/menu/menu_bloc.dart'; -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; -import 'package:app_flowy/workspace/presentation/widgets/menu/widget/menu_user.dart'; +import 'package:app_flowy/workspace/presentation/home/home_sizes.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra_ui/style_widget/icon_button.dart'; -import 'widget/app/menu_app.dart'; -import 'widget/app/create_button.dart'; -import 'widget/menu_trash.dart'; - -// [[diagram: HomeMenu's widget structure]] -// get user profile or modify user -// ┌──────┐ -// ┌──────────┐ ┌──▶│IUser │ -// ┌─▶│MenuTopBar│ ┌────────┐ ┌─────────────┐ │ └──────┘ -// │ └──────────┘ ┌───│MenuUser│─▶│MenuUserBloc │──┤ -// ┌──────────┐ │ │ └────────┘ └─────────────┘ │ ┌─────────────┐ -// │ HomeMenu │─┤ │ └──▶│IUserListener│ -// └──────────┘ │ │ └─────────────┘ -// │ │ listen workspace changes or user -// │ impl │ profile changes -// │ ┌──────────┐ ┌─────────┐ │ -// └─▶│ MenuList │───▶│MenuItem │◀─┤ -// └──────────┘ └─────────┘ │ ┌────────┐ -// │ ┌─▶│AppBloc │ fetch app's views or modify view -// │ │ └────────┘ -// │ ┌────────┐ │ -// └───│MenuApp │──┤ -// └────────┘ +import 'app/menu_app.dart'; +import 'app/create_button.dart'; +import 'menu_user.dart'; class HomeMenu extends StatelessWidget { final PublishNotifier _collapsedNotifier; @@ -181,3 +166,32 @@ class MenuSharedState extends ChangeNotifier { }); } } + +class MenuTopBar extends StatelessWidget { + const MenuTopBar({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return BlocBuilder( + builder: (context, state) { + return SizedBox( + height: HomeSizes.topBarHeight, + child: Row( + children: [ + (theme.isDark + ? svgWithSize("flowy_logo_dark_mode", const Size(92, 17)) + : svgWithSize("flowy_logo_with_text", const Size(92, 17))), + const Spacer(), + FlowyIconButton( + width: 28, + onPressed: () => context.read().add(const MenuEvent.collapse()), + iconPadding: const EdgeInsets.fromLTRB(4, 4, 4, 4), + icon: svg("home/hide_menu", color: theme.iconColor), + ) + ], + ), + ); + }, + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_user.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/menu_user.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_user.dart rename to frontend/app_flowy/lib/workspace/presentation/home/menu/menu_user.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart b/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart index a739976c1d..e8a9c3d457 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart @@ -1,4 +1,4 @@ -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; +import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/notifier.dart'; import 'package:flowy_infra/theme.dart'; @@ -17,8 +17,8 @@ class NavigationNotifier with ChangeNotifier { void update(HomeStackNotifier notifier) { bool shouldNotify = false; - if (navigationItems != notifier.plugin.display.navigationItems) { - navigationItems = notifier.plugin.display.navigationItems; + if (navigationItems != notifier.plugin.pluginDisplay.navigationItems) { + navigationItems = notifier.plugin.pluginDisplay.navigationItems; shouldNotify = true; } @@ -59,7 +59,7 @@ class FlowyNavigation extends StatelessWidget { create: (_) { final notifier = Provider.of(context, listen: false); return NavigationNotifier( - navigationItems: notifier.plugin.display.navigationItems, + navigationItems: notifier.plugin.pluginDisplay.navigationItems, collapasedNotifier: notifier.collapsedNotifier, ); }, @@ -179,7 +179,4 @@ class EllipsisNaviItem extends NavigationItem { @override NavigationCallback get action => (id) {}; - - @override - String get identifier => "Ellipsis"; } diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/blank/blank.dart similarity index 82% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/blank/blank.dart index 05148c34cf..4534053ad8 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/blank/blank.dart @@ -1,11 +1,11 @@ import 'package:app_flowy/startup/tasks/load_plugin.dart'; +import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/plugin/plugin.dart'; -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; class BlankPluginBuilder extends PluginBuilder { @override @@ -14,7 +14,7 @@ class BlankPluginBuilder extends PluginBuilder { } @override - String get name => "Blank"; + String get menuName => "Blank"; @override PluginType get pluginType => DefaultPlugin.blank.type(); @@ -25,7 +25,7 @@ class BlankPluginConfig implements PluginConfig { bool get creatable => false; } -class BlankPagePlugin implements Plugin { +class BlankPagePlugin extends Plugin { final PluginType _pluginType; BlankPagePlugin({ required PluginType pluginType, @@ -35,10 +35,10 @@ class BlankPagePlugin implements Plugin { void dispose() {} @override - PluginDisplay get display => BlankPagePluginDisplay(); + PluginDisplay get pluginDisplay => BlankPagePluginDisplay(); @override - String get pluginId => "BlankStack"; + PluginId get pluginId => "BlankStack"; @override PluginType get pluginType => _pluginType; @@ -49,12 +49,7 @@ class BlankPagePluginDisplay extends PluginDisplay { Widget get leftBarItem => FlowyText.medium(LocaleKeys.blankPageTitle.tr(), fontSize: 12); @override - Widget? get rightBarItem => null; - - @override - Widget buildWidget() { - return const BlankStackPage(); - } + Widget buildWidget() => const BlankStackPage(); @override List get navigationItems => [this]; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart similarity index 91% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart index 74280fa67f..2dc44421ee 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart @@ -1,10 +1,17 @@ +library docuemnt_plugin; + +export './src/document_page.dart'; +export './src/widget/toolbar/history_button.dart'; +export './src/widget/toolbar/toolbar_icon_button.dart'; +export './src/widget/toolbar/tool_bar.dart'; + import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/startup/tasks/load_plugin.dart'; import 'package:app_flowy/workspace/application/appearance.dart'; import 'package:app_flowy/workspace/application/doc/share_bloc.dart'; -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart'; +import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart'; import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -23,7 +30,7 @@ import 'package:clipboard/clipboard.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:provider/provider.dart'; -import 'document_page.dart'; +import 'src/document_page.dart'; class DocumentPluginBuilder extends PluginBuilder { @override @@ -36,7 +43,7 @@ class DocumentPluginBuilder extends PluginBuilder { } @override - String get name => "Doc"; + String get menuName => "Doc"; @override PluginType get pluginType => DefaultPlugin.quillEditor.type(); @@ -47,38 +54,42 @@ class DocumentPluginBuilder extends PluginBuilder { class DocumentPlugin implements Plugin { late View _view; - late ViewListener _listener; - final ValueNotifier _isUpdated = ValueNotifier(0); + ViewListener? _listener; + final ValueNotifier _displayNotifier = ValueNotifier(0); late PluginType _pluginType; DocumentPlugin({required PluginType pluginType, required View view, Key? key}) : _view = view { _pluginType = pluginType; _listener = getIt(param1: view); - _listener.updatedNotifier.addPublishListener((result) { + _listener?.updatedNotifier.addPublishListener((result) { result.fold( (newView) { _view = newView; - _isUpdated.value = _view.hashCode; + _displayNotifier.value = _view.hashCode; }, (error) {}, ); }); - _listener.start(); + _listener?.start(); } @override void dispose() { - _listener.close(); + _listener?.close(); + _listener = null; } @override - PluginDisplay get display => DocumentPluginDisplay(view: _view); + PluginDisplay get pluginDisplay => DocumentPluginDisplay(view: _view); @override PluginType get pluginType => _pluginType; @override - String get pluginId => _view.id; + PluginId get pluginId => _view.id; + + @override + ChangeNotifier? get displayNotifier => _displayNotifier; } class DocumentPluginDisplay extends PluginDisplay { diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/document_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/document_page.dart similarity index 98% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/doc/document_page.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/document_page.dart index d611da0c9c..30b88e652f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/document_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/document_page.dart @@ -1,6 +1,7 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/appearance.dart'; import 'package:app_flowy/workspace/application/doc/doc_bloc.dart'; +import 'package:app_flowy/workspace/presentation/plugins/doc/document.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter_quill/flutter_quill.dart' as quill; @@ -12,7 +13,6 @@ import 'package:provider/provider.dart'; import 'package:styled_widget/styled_widget.dart'; import 'styles.dart'; import 'widget/banner.dart'; -import 'widget/toolbar/tool_bar.dart'; class DocumentPage extends StatefulWidget { final View view; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/styles.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/styles.dart similarity index 98% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/doc/styles.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/styles.dart index fdf3183354..c6eb292c49 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/styles.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/styles.dart @@ -4,7 +4,7 @@ import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; import 'package:flowy_infra/theme.dart'; -import 'widget/style_widgets/style_widgets.dart'; +import 'widget/style_widgets.dart'; DefaultStyles customStyles(BuildContext context) { const baseSpacing = Tuple2(6, 0); diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/banner.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/banner.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/banner.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/banner.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/style_widgets/style_widgets.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/style_widgets.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/style_widgets/style_widgets.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/style_widgets.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/check_button.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/check_button.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/check_button.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/check_button.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/color_picker.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/color_picker.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/color_picker.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/color_picker.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/header_button.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/header_button.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/header_button.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/header_button.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/history_button.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/history_button.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/history_button.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/history_button.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/image_button.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/image_button.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/image_button.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/image_button.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/link_button.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/link_button.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/link_button.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/link_button.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/toggle_button.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/toggle_button.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/toggle_button.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/toggle_button.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/tool_bar.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/tool_bar.dart similarity index 98% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/tool_bar.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/tool_bar.dart index faf49e8027..2ab0b78cc9 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/tool_bar.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/tool_bar.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:math'; -import 'package:app_flowy/workspace/presentation/stack_page/doc/widget/toolbar/history_button.dart'; import 'package:app_flowy/workspace/presentation/widgets/emoji_picker/emoji_picker.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter_quill/flutter_quill.dart'; @@ -10,6 +9,7 @@ import 'package:styled_widget/styled_widget.dart'; import 'check_button.dart'; import 'color_picker.dart'; import 'header_button.dart'; +import 'history_button.dart'; import 'link_button.dart'; import 'toggle_button.dart'; import 'toolbar_icon_button.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/toolbar_icon_button.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/toolbar_icon_button.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/toolbar_icon_button.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/toolbar_icon_button.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/trash/menu.dart similarity index 93% rename from frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/trash/menu.dart index 96170f350e..2053432264 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/trash/menu.dart @@ -2,8 +2,8 @@ import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/startup/tasks/load_plugin.dart'; import 'package:app_flowy/workspace/application/appearance.dart'; -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; -import 'package:app_flowy/workspace/presentation/widgets/menu/menu.dart'; +import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; +import 'package:app_flowy/workspace/presentation/home/menu/menu.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/widget/sizes.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/trash/src/sizes.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/trash/widget/sizes.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/trash/src/sizes.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/trash/src/trash_cell.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_cell.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/trash/src/trash_cell.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/trash/src/trash_header.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_header.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/trash/src/trash_header.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/trash/trash.dart similarity index 93% rename from frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/trash/trash.dart index 7fcf90da5f..b0324a1138 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/trash/trash.dart @@ -1,10 +1,12 @@ +export "./src/sizes.dart"; +export "./src/trash_cell.dart"; +export "./src/trash_header.dart"; + import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/startup/tasks/load_plugin.dart'; import 'package:app_flowy/workspace/application/trash/trash_bloc.dart'; -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; -import 'package:app_flowy/workspace/presentation/stack_page/trash/widget/sizes.dart'; -import 'package:app_flowy/workspace/presentation/stack_page/trash/widget/trash_cell.dart'; +import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -19,7 +21,9 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; -import 'widget/trash_header.dart'; +import 'src/sizes.dart'; +import 'src/trash_cell.dart'; +import 'src/trash_header.dart'; class TrashPluginBuilder extends PluginBuilder { @override @@ -28,7 +32,7 @@ class TrashPluginBuilder extends PluginBuilder { } @override - String get name => "Trash"; + String get menuName => "Trash"; @override PluginType get pluginType => DefaultPlugin.trash.type(); @@ -39,7 +43,7 @@ class TrashPluginConfig implements PluginConfig { bool get creatable => false; } -class TrashPlugin implements Plugin { +class TrashPlugin extends Plugin { final PluginType _pluginType; TrashPlugin({required PluginType pluginType}) : _pluginType = pluginType; @@ -48,10 +52,10 @@ class TrashPlugin implements Plugin { void dispose() {} @override - PluginDisplay get display => TrashPluginDisplay(); + PluginDisplay get pluginDisplay => TrashPluginDisplay(); @override - String get pluginId => "TrashStack"; + PluginId get pluginId => "TrashStack"; @override PluginType get pluginType => _pluginType; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/home_stack.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/home_stack.dart deleted file mode 100644 index 486967f215..0000000000 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/home_stack.dart +++ /dev/null @@ -1,86 +0,0 @@ -import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; -import 'package:app_flowy/workspace/presentation/home/home_screen.dart'; -import 'package:flowy_infra/theme.dart'; -import 'package:flowy_sdk/log.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:time/time.dart'; -import 'package:fluttertoast/fluttertoast.dart'; - -late FToast fToast; - -class HomeStack extends StatelessWidget { - static GlobalKey scaffoldKey = GlobalKey(); - // final Size size; - const HomeStack({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - Log.info('HomePage build'); - final theme = context.watch(); - return Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - getIt().stackTopBar(), - Expanded( - child: Container( - color: theme.surface, - child: FocusTraversalGroup( - child: getIt().stackWidget(), - ), - ), - ), - ], - ); - } -} - -class FadingIndexedStack extends StatefulWidget { - final int index; - final List children; - final Duration duration; - - const FadingIndexedStack({ - Key? key, - required this.index, - required this.children, - this.duration = const Duration( - milliseconds: 250, - ), - }) : super(key: key); - - @override - _FadingIndexedStackState createState() => _FadingIndexedStackState(); -} - -class _FadingIndexedStackState extends State { - double _targetOpacity = 1; - - @override - void initState() { - super.initState(); - fToast = FToast(); - fToast.init(HomeScreen.scaffoldKey.currentState!.context); - } - - @override - void didUpdateWidget(FadingIndexedStack oldWidget) { - if (oldWidget.index == widget.index) return; - setState(() => _targetOpacity = 0); - Future.delayed(1.milliseconds, () => setState(() => _targetOpacity = 1)); - super.didUpdateWidget(oldWidget); - } - - @override - Widget build(BuildContext context) { - return TweenAnimationBuilder( - duration: _targetOpacity > 0 ? widget.duration : 0.milliseconds, - tween: Tween(begin: 0, end: _targetOpacity), - builder: (_, value, child) { - return Opacity(opacity: value, child: child); - }, - child: IndexedStack(index: widget.index, children: widget.children), - ); - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart index c55d405b76..b892a8e49d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart @@ -1,5 +1,5 @@ import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dart'; -import 'package:app_flowy/workspace/domain/edit_context.dart'; +import 'package:app_flowy/workspace/application/edit_pannel/edit_context.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/presentation/home/home_sizes.dart'; import 'package:dartz/dartz.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/emoji_picker/src/emoji_button.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/emoji_picker/src/emoji_button.dart index 4fdc3bd14f..eeafd4ae98 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/emoji_picker/src/emoji_button.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/emoji_picker/src/emoji_button.dart @@ -1,7 +1,6 @@ +import 'package:app_flowy/workspace/presentation/plugins/doc/document.dart'; import 'package:flutter/material.dart'; import 'package:flutter_quill/flutter_quill.dart'; - -import 'package:app_flowy/workspace/presentation/stack_page/doc/widget/toolbar/toolbar_icon_button.dart'; import 'package:app_flowy/workspace/presentation/widgets/emoji_picker/emoji_picker.dart'; class FlowyEmojiStyleButton extends StatefulWidget { diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart index acedb7c1d6..2c28b88660 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme.dart'; @@ -16,7 +17,6 @@ import 'package:url_launcher/url_launcher.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:fluttertoast/fluttertoast.dart'; -import 'package:app_flowy/workspace/presentation/stack_page/home_stack.dart'; class QuestionBubble extends StatelessWidget { const QuestionBubble({Key? key}) : super(key: key); diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart deleted file mode 100644 index 0ac344cf69..0000000000 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; -import 'package:app_flowy/workspace/presentation/home/home_sizes.dart'; -import 'package:app_flowy/workspace/presentation/home/navigation.dart'; -import 'package:flowy_infra/theme.dart'; -import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flutter/material.dart'; -import 'package:flowy_infra_ui/style_widget/extension.dart'; -import 'package:provider/provider.dart'; - -class HomeTopBar extends StatelessWidget { - const HomeTopBar({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final theme = context.watch(); - return Container( - color: theme.surface, - height: HomeSizes.topBarHeight, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const FlowyNavigation(), - const HSpace(16), - ChangeNotifierProvider.value( - value: Provider.of(context, listen: false), - child: Consumer( - builder: (BuildContext context, HomeStackNotifier notifier, Widget? child) { - return notifier.plugin.display.rightBarItem ?? const SizedBox(); - }, - ), - ) // _renderMoreButton(), - ], - ) - .padding( - horizontal: HomeInsets.topBarTitlePadding, - ) - .bottomBorder(color: Colors.grey.shade300), - ); - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/prelude.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/prelude.dart deleted file mode 100644 index c08dc66133..0000000000 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/prelude.dart +++ /dev/null @@ -1 +0,0 @@ -export 'menu.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/top_bar.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/top_bar.dart deleted file mode 100644 index 83cd352d53..0000000000 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/top_bar.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:app_flowy/workspace/application/menu/menu_bloc.dart'; -import 'package:app_flowy/workspace/presentation/home/home_sizes.dart'; -import 'package:flowy_infra/image.dart'; -import 'package:flowy_infra_ui/style_widget/icon_button.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flowy_infra/theme.dart'; - -class MenuTopBar extends StatelessWidget { - const MenuTopBar({Key? key}) : super(key: key); - @override - Widget build(BuildContext context) { - final theme = context.watch(); - return BlocBuilder( - builder: (context, state) { - return SizedBox( - height: HomeSizes.topBarHeight, - child: Row( - children: [ - (theme.isDark - ? svgWithSize("flowy_logo_dark_mode", const Size(92, 17)) - : svgWithSize("flowy_logo_with_text", const Size(92, 17))), - const Spacer(), - FlowyIconButton( - width: 28, - onPressed: () => context.read().add(const MenuEvent.collapse()), - iconPadding: const EdgeInsets.fromLTRB(4, 4, 4, 4), - icon: svg("home/hide_menu", color: theme.iconColor), - ) - ], - ), - ); - }, - ); - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/prelude.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/prelude.dart deleted file mode 100644 index ab03f3ab29..0000000000 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/prelude.dart +++ /dev/null @@ -1,5 +0,0 @@ -export '../stack_page/blank/blank_page.dart'; -export './edit_pannel/edit_pannel.dart'; -export './edit_pannel/pannel_animation.dart'; -export './home_top_bar.dart'; -export 'menu/menu.dart'; diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs b/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs index 241b359a9f..fec97d2f02 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs @@ -117,6 +117,7 @@ pub async fn create_view(sdk: &FlowySDKTest, app_id: &str, name: &str, desc: &st thumbnail: None, data_type: view_type, ext_data: "".to_string(), + plugin_type: 0, }; let view = FolderEventBuilder::new(sdk.clone()) .event(CreateView) diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index 4cb4a5e815..7b090792f3 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -90,6 +90,7 @@ async fn create_view(sdk: &FlowySDKTest, app_id: &str) -> View { thumbnail: Some("http://1.png".to_string()), data_type: ViewDataType::RichText, ext_data: "".to_string(), + plugin_type: 0, }; let view = FolderEventBuilder::new(sdk.clone()) From 6eddb7c8c5a592b38ef7fd1dd8202641fedc17da Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 1 Mar 2022 20:51:49 +0800 Subject: [PATCH 11/12] chore: serde ViewDataType as u8 --- frontend/rust-lib/Cargo.lock | 1 + shared-lib/Cargo.lock | 12 +++ shared-lib/flowy-folder-data-model/Cargo.toml | 1 + .../src/entities/view.rs | 99 +++++++++++-------- .../src/protobuf/model/mod.rs | 6 +- 5 files changed, 76 insertions(+), 43 deletions(-) diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 1f07ccdf24..9b8dbfc3bc 100755 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -1031,6 +1031,7 @@ dependencies = [ "protobuf", "serde", "serde_json", + "serde_repr", "strum", "strum_macros", "unicode-segmentation", diff --git a/shared-lib/Cargo.lock b/shared-lib/Cargo.lock index 8667d60930..18ade8da40 100644 --- a/shared-lib/Cargo.lock +++ b/shared-lib/Cargo.lock @@ -471,6 +471,7 @@ dependencies = [ "protobuf", "serde", "serde_json", + "serde_repr", "strum", "strum_macros", "unicode-segmentation", @@ -1580,6 +1581,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "serial_test" version = "0.5.1" diff --git a/shared-lib/flowy-folder-data-model/Cargo.toml b/shared-lib/flowy-folder-data-model/Cargo.toml index 3e8764b1bc..90422eaa53 100644 --- a/shared-lib/flowy-folder-data-model/Cargo.toml +++ b/shared-lib/flowy-folder-data-model/Cargo.toml @@ -19,6 +19,7 @@ chrono = { version = "0.4" } flowy-error-code = { path = "../flowy-error-code"} serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +serde_repr = "0.1" [build-dependencies] lib-infra = { path = "../lib-infra", features = ["protobuf_file_gen"] } diff --git a/shared-lib/flowy-folder-data-model/src/entities/view.rs b/shared-lib/flowy-folder-data-model/src/entities/view.rs index 3af0943dc0..a16a384be1 100644 --- a/shared-lib/flowy-folder-data-model/src/entities/view.rs +++ b/shared-lib/flowy-folder-data-model/src/entities/view.rs @@ -8,9 +8,8 @@ use crate::{ }, }; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; -use serde::de::Unexpected; -use serde::{de, de::Visitor, Deserializer}; use serde::{Deserialize, Serialize}; +use serde_repr::*; use std::convert::TryInto; #[derive(Eq, PartialEq, ProtoBuf, Default, Debug, Clone, Serialize, Deserialize)] @@ -81,7 +80,8 @@ impl std::convert::From for Trash { } } -#[derive(Eq, PartialEq, Debug, ProtoBuf_Enum, Clone, Serialize)] +#[derive(Eq, PartialEq, Debug, ProtoBuf_Enum, Clone, Serialize_repr, Deserialize_repr)] +#[repr(u8)] pub enum ViewDataType { RichText = 0, PlainText = 1, @@ -89,7 +89,7 @@ pub enum ViewDataType { impl std::default::Default for ViewDataType { fn default() -> Self { - ViewDataType::PlainText + ViewDataType::RichText } } @@ -287,39 +287,58 @@ impl TryInto for UpdateViewPayload { } } -impl<'de> Deserialize<'de> for ViewDataType { - fn deserialize(deserializer: D) -> Result>::Error> - where - D: Deserializer<'de>, - { - struct ViewTypeVisitor(); - - impl<'de> Visitor<'de> for ViewTypeVisitor { - type Value = ViewDataType; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("Plugin, RichText") - } - - fn visit_str(self, s: &str) -> Result - where - E: de::Error, - { - let view_type; - match s { - "Doc" | "RichText" => { - // Rename ViewType::Doc to ViewType::RichText, So we need to migrate the ViewType manually. - view_type = ViewDataType::RichText; - } - "Plugin" => { - view_type = ViewDataType::PlainText; - } - unknown => { - return Err(de::Error::invalid_value(Unexpected::Str(unknown), &self)); - } - } - Ok(view_type) - } - } - deserializer.deserialize_any(ViewTypeVisitor()) - } -} +// impl<'de> Deserialize<'de> for ViewDataType { +// fn deserialize(deserializer: D) -> Result>::Error> +// where +// D: Deserializer<'de>, +// { +// struct ViewTypeVisitor(); +// +// impl<'de> Visitor<'de> for ViewTypeVisitor { +// type Value = ViewDataType; +// fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { +// formatter.write_str("RichText, PlainText") +// } +// +// fn visit_u8(self, v: u8) -> Result +// where +// E: de::Error, +// { +// let data_type; +// match v { +// 0 => { +// data_type = ViewDataType::RichText; +// } +// 1 => { +// data_type = ViewDataType::PlainText; +// } +// _ => { +// return Err(de::Error::invalid_value(Unexpected::Unsigned(v as u64), &self)); +// } +// } +// Ok(data_type) +// } +// +// fn visit_str(self, s: &str) -> Result +// where +// E: de::Error, +// { +// let data_type; +// match s { +// "Doc" | "RichText" => { +// // Rename ViewDataType::Doc to ViewDataType::RichText, So we need to migrate the ViewType manually. +// data_type = ViewDataType::RichText; +// } +// "PlainText" => { +// data_type = ViewDataType::PlainText; +// } +// unknown => { +// return Err(de::Error::invalid_value(Unexpected::Str(unknown), &self)); +// } +// } +// Ok(data_type) +// } +// } +// deserializer.deserialize_any(ViewTypeVisitor()) +// } +// } diff --git a/shared-lib/flowy-user-data-model/src/protobuf/model/mod.rs b/shared-lib/flowy-user-data-model/src/protobuf/model/mod.rs index b9d261ebd8..e691c7e166 100644 --- a/shared-lib/flowy-user-data-model/src/protobuf/model/mod.rs +++ b/shared-lib/flowy-user-data-model/src/protobuf/model/mod.rs @@ -4,11 +4,11 @@ mod errors; pub use errors::*; -mod user_setting; -pub use user_setting::*; - mod user_profile; pub use user_profile::*; mod auth; pub use auth::*; + +mod user_setting; +pub use user_setting::*; From 8a0308703e14765ef21eae6dd99bedb719ed0155 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 1 Mar 2022 23:38:26 +0800 Subject: [PATCH 12/12] fix: compose folder error --- .../flowy-document/src/block_editor.rs | 2 +- .../tests/document/edit_script.rs | 2 +- .../tests/editor/attribute_test.rs | 2 +- .../flowy-document/tests/editor/mod.rs | 26 ++++++------- .../flowy-document/tests/editor/serde_test.rs | 2 +- .../rust-lib/flowy-folder/src/controller.rs | 4 +- .../src/services/persistence/migration.rs | 37 ++++++++++++++++++- .../src/services/persistence/mod.rs | 11 ++++-- .../flowy-folder/tests/workspace/helper.rs | 4 +- frontend/rust-lib/flowy-sdk/src/lib.rs | 4 +- .../rust-lib/flowy-sync/src/rev_manager.rs | 31 +++++++++------- .../src/client_document/default/mod.rs | 4 +- .../src/client_document/document_pad.rs | 6 +-- .../src/client_folder/builder.rs | 4 +- .../src/client_folder/folder_pad.rs | 6 +++ .../src/entities/document_info.rs | 2 +- .../src/entities/revision.rs | 2 +- .../src/server_document/document_pad.rs | 2 +- .../src/server_folder/folder_pad.rs | 2 +- shared-lib/flowy-collaboration/src/util.rs | 5 ++- shared-lib/lib-ot/src/core/delta/delta.rs | 16 ++++++-- 21 files changed, 117 insertions(+), 57 deletions(-) diff --git a/frontend/rust-lib/flowy-document/src/block_editor.rs b/frontend/rust-lib/flowy-document/src/block_editor.rs index 0f582d28c1..1ac0b99284 100644 --- a/frontend/rust-lib/flowy-document/src/block_editor.rs +++ b/frontend/rust-lib/flowy-document/src/block_editor.rs @@ -226,7 +226,7 @@ impl RevisionObjectBuilder for BlockInfoBuilder { Result::::Ok(BlockInfo { doc_id: object_id.to_owned(), - text: delta.to_json(), + text: delta.to_delta_json(), rev_id, base_rev_id, }) diff --git a/frontend/rust-lib/flowy-document/tests/document/edit_script.rs b/frontend/rust-lib/flowy-document/tests/document/edit_script.rs index 89d0119dfc..289fe20626 100644 --- a/frontend/rust-lib/flowy-document/tests/document/edit_script.rs +++ b/frontend/rust-lib/flowy-document/tests/document/edit_script.rs @@ -77,7 +77,7 @@ impl EditorTest { let delta = self.editor.doc_delta().await.unwrap(); if expected_delta != delta { eprintln!("✅ expect: {}", expected,); - eprintln!("❌ receive: {}", delta.to_json()); + eprintln!("❌ receive: {}", delta.to_delta_json()); } assert_eq!(expected_delta, delta); } diff --git a/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs b/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs index 53156ad185..261ce60b6c 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs @@ -774,7 +774,7 @@ fn delta_compose() { delta = delta.compose(&d).unwrap(); } assert_eq!( - delta.to_json(), + delta.to_delta_json(), r#"[{"insert":"a"},{"insert":"\n","attributes":{"list":"unchecked"}},{"insert":"\n"}]"# ); diff --git a/frontend/rust-lib/flowy-document/tests/editor/mod.rs b/frontend/rust-lib/flowy-document/tests/editor/mod.rs index 32c94bae9c..151652262f 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/mod.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/mod.rs @@ -108,20 +108,20 @@ impl TestBuilder { TestOp::Insert(delta_i, s, index) => { let document = &mut self.documents[*delta_i]; let delta = document.insert(*index, s).unwrap(); - tracing::debug!("Insert delta: {}", delta.to_json()); + tracing::debug!("Insert delta: {}", delta.to_delta_json()); self.deltas.insert(*delta_i, Some(delta)); } TestOp::Delete(delta_i, iv) => { let document = &mut self.documents[*delta_i]; let delta = document.replace(*iv, "").unwrap(); - tracing::trace!("Delete delta: {}", delta.to_json()); + tracing::trace!("Delete delta: {}", delta.to_delta_json()); self.deltas.insert(*delta_i, Some(delta)); } TestOp::Replace(delta_i, iv, s) => { let document = &mut self.documents[*delta_i]; let delta = document.replace(*iv, s).unwrap(); - tracing::trace!("Replace delta: {}", delta.to_json()); + tracing::trace!("Replace delta: {}", delta.to_delta_json()); self.deltas.insert(*delta_i, Some(delta)); } TestOp::InsertBold(delta_i, s, iv) => { @@ -133,7 +133,7 @@ impl TestBuilder { let document = &mut self.documents[*delta_i]; let attribute = RichTextAttribute::Bold(*enable); let delta = document.format(*iv, attribute).unwrap(); - tracing::trace!("Bold delta: {}", delta.to_json()); + tracing::trace!("Bold delta: {}", delta.to_delta_json()); self.deltas.insert(*delta_i, Some(delta)); } TestOp::Italic(delta_i, iv, enable) => { @@ -143,28 +143,28 @@ impl TestBuilder { false => RichTextAttribute::Italic(false), }; let delta = document.format(*iv, attribute).unwrap(); - tracing::trace!("Italic delta: {}", delta.to_json()); + tracing::trace!("Italic delta: {}", delta.to_delta_json()); self.deltas.insert(*delta_i, Some(delta)); } TestOp::Header(delta_i, iv, level) => { let document = &mut self.documents[*delta_i]; let attribute = RichTextAttribute::Header(*level); let delta = document.format(*iv, attribute).unwrap(); - tracing::trace!("Header delta: {}", delta.to_json()); + tracing::trace!("Header delta: {}", delta.to_delta_json()); self.deltas.insert(*delta_i, Some(delta)); } TestOp::Link(delta_i, iv, link) => { let document = &mut self.documents[*delta_i]; let attribute = RichTextAttribute::Link(link.to_owned()); let delta = document.format(*iv, attribute).unwrap(); - tracing::trace!("Link delta: {}", delta.to_json()); + tracing::trace!("Link delta: {}", delta.to_delta_json()); self.deltas.insert(*delta_i, Some(delta)); } TestOp::Bullet(delta_i, iv, enable) => { let document = &mut self.documents[*delta_i]; let attribute = RichTextAttribute::Bullet(*enable); let delta = document.format(*iv, attribute).unwrap(); - tracing::debug!("Bullet delta: {}", delta.to_json()); + tracing::debug!("Bullet delta: {}", delta.to_delta_json()); self.deltas.insert(*delta_i, Some(delta)); } @@ -194,15 +194,15 @@ impl TestBuilder { let delta_a = &self.documents[*delta_a_i].delta(); let delta_b = &self.documents[*delta_b_i].delta(); tracing::debug!("Invert: "); - tracing::debug!("a: {}", delta_a.to_json()); - tracing::debug!("b: {}", delta_b.to_json()); + tracing::debug!("a: {}", delta_a.to_delta_json()); + tracing::debug!("b: {}", delta_b.to_delta_json()); let (_, b_prime) = delta_a.transform(delta_b).unwrap(); let undo = b_prime.invert(delta_a); let new_delta = delta_a.compose(&b_prime).unwrap(); - tracing::debug!("new delta: {}", new_delta.to_json()); - tracing::debug!("undo delta: {}", undo.to_json()); + tracing::debug!("new delta: {}", new_delta.to_delta_json()); + tracing::debug!("undo delta: {}", undo.to_delta_json()); let new_delta_after_undo = new_delta.compose(&undo).unwrap(); @@ -238,7 +238,7 @@ impl TestBuilder { } TestOp::AssertPrimeJson(doc_i, expected) => { - let prime_json = self.primes[*doc_i].as_ref().unwrap().to_json(); + let prime_json = self.primes[*doc_i].as_ref().unwrap().to_delta_json(); let expected_prime: RichTextDelta = serde_json::from_str(expected).unwrap(); let target_prime: RichTextDelta = serde_json::from_str(&prime_json).unwrap(); diff --git a/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs b/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs index da64d4bcf8..32366d667a 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs @@ -92,7 +92,7 @@ fn delta_deserialize_null_test() { attribute.value = RichTextAttributeValue(None); let delta2 = DeltaBuilder::new().retain_with_attributes(7, attribute.into()).build(); - assert_eq!(delta2.to_json(), r#"[{"retain":7,"attributes":{"bold":""}}]"#); + assert_eq!(delta2.to_delta_json(), r#"[{"retain":7,"attributes":{"bold":""}}]"#); assert_eq!(delta1, delta2); } diff --git a/frontend/rust-lib/flowy-folder/src/controller.rs b/frontend/rust-lib/flowy-folder/src/controller.rs index 22c146f4f2..8ec6bc91b8 100644 --- a/frontend/rust-lib/flowy-folder/src/controller.rs +++ b/frontend/rust-lib/flowy-folder/src/controller.rs @@ -197,9 +197,9 @@ impl DefaultFolderBuilder { for app in workspace.apps.iter() { for (index, view) in app.belongings.iter().enumerate() { let view_data = if index == 0 { - initial_read_me().to_json() + initial_read_me().to_delta_json() } else { - initial_delta().to_json() + initial_delta().to_delta_json() }; view_controller.set_latest_view(view); let delta_data = Bytes::from(view_data); diff --git a/frontend/rust-lib/flowy-folder/src/services/persistence/migration.rs b/frontend/rust-lib/flowy-folder/src/services/persistence/migration.rs index a0ed9e42e9..258b8a1e55 100644 --- a/frontend/rust-lib/flowy-folder/src/services/persistence/migration.rs +++ b/frontend/rust-lib/flowy-folder/src/services/persistence/migration.rs @@ -1,3 +1,4 @@ +use crate::controller::FolderId; use crate::{ event_map::WorkspaceDatabase, services::persistence::{AppTableSql, TrashTableSql, ViewTableSql, WorkspaceTableSql}, @@ -10,9 +11,11 @@ use flowy_folder_data_model::entities::{ view::{RepeatedView, View}, workspace::Workspace, }; +use flowy_sync::{RevisionLoader, RevisionPersistence}; use std::sync::Arc; -pub(crate) const V1_MIGRATION: &str = "FOLDER_V1_MIGRATION"; +const V1_MIGRATION: &str = "FOLDER_V1_MIGRATION"; +const V2_MIGRATION: &str = "FOLDER_V2_MIGRATION"; pub(crate) struct FolderMigration { user_id: String, @@ -32,7 +35,7 @@ impl FolderMigration { if KV::get_bool(&key) { return Ok(None); } - tracing::trace!("Run folder version 1 migrations"); + let pool = self.database.db_pool()?; let conn = &*pool.get()?; let workspaces = conn.immediate_transaction::<_, FlowyError, _>(|| { @@ -62,6 +65,7 @@ impl FolderMigration { })?; if workspaces.is_empty() { + tracing::trace!("Run folder v1 migration, but workspace is empty"); KV::set_bool(&key, true); return Ok(None); } @@ -73,6 +77,35 @@ impl FolderMigration { let folder = FolderPad::new(workspaces, trash)?; KV::set_bool(&key, true); + tracing::trace!("Run folder v1 migration"); Ok(Some(folder)) } + + pub async fn run_v2_migration(&self, user_id: &str, folder_id: &FolderId) -> FlowyResult> { + let key = md5(format!("{}{}", self.user_id, V2_MIGRATION)); + if KV::get_bool(&key) { + return Ok(None); + } + let pool = self.database.db_pool()?; + let rev_persistence = Arc::new(RevisionPersistence::new(user_id, folder_id.as_ref(), pool.clone())); + let (revisions, _) = RevisionLoader { + object_id: folder_id.as_ref().to_owned(), + user_id: self.user_id.clone(), + cloud: None, + rev_persistence, + } + .load() + .await?; + + if revisions.is_empty() { + tracing::trace!("Run folder v2 migration, but revision is empty"); + KV::set_bool(&key, true); + return Ok(None); + } + + let pad = FolderPad::from_revisions(revisions)?; + KV::set_bool(&key, true); + tracing::trace!("Run folder v2 migration"); + Ok(Some(pad)) + } } diff --git a/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs b/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs index f4ceec5b88..77b6d2a6c4 100644 --- a/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs +++ b/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs @@ -2,6 +2,7 @@ mod migration; pub mod version_1; mod version_2; +use flowy_collaboration::client_folder::initial_folder_delta; use flowy_collaboration::{ client_folder::FolderPad, entities::revision::{Revision, RevisionState}, @@ -105,7 +106,10 @@ impl FolderPersistence { pub async fn initialize(&self, user_id: &str, folder_id: &FolderId) -> FlowyResult<()> { let migrations = FolderMigration::new(user_id, self.database.clone()); if let Some(migrated_folder) = migrations.run_v1_migration()? { - tracing::trace!("Save migration folder"); + self.save_folder(user_id, folder_id, migrated_folder).await?; + } + + if let Some(migrated_folder) = migrations.run_v2_migration(user_id, folder_id).await? { self.save_folder(user_id, folder_id, migrated_folder).await?; } @@ -114,7 +118,7 @@ impl FolderPersistence { pub async fn save_folder(&self, user_id: &str, folder_id: &FolderId, folder: FolderPad) -> FlowyResult<()> { let pool = self.database.db_pool()?; - let delta_data = folder.delta().to_bytes(); + let delta_data = initial_folder_delta(&folder)?.to_bytes(); let md5 = folder.md5(); let revision = Revision::new(folder_id.as_ref(), 0, 0, delta_data, user_id, md5); let record = RevisionRecord { @@ -123,8 +127,7 @@ impl FolderPersistence { write_to_disk: true, }; - let conn = pool.get()?; let disk_cache = mk_revision_disk_cache(user_id, pool); - disk_cache.create_revision_records(vec![record], &conn) + disk_cache.delete_and_insert_records(folder_id.as_ref(), None, vec![record]) } } diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs b/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs index fec97d2f02..7d823749df 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/helper.rs @@ -109,13 +109,13 @@ pub async fn delete_app(sdk: &FlowySDKTest, app_id: &str) { .await; } -pub async fn create_view(sdk: &FlowySDKTest, app_id: &str, name: &str, desc: &str, view_type: ViewDataType) -> View { +pub async fn create_view(sdk: &FlowySDKTest, app_id: &str, name: &str, desc: &str, data_type: ViewDataType) -> View { let request = CreateViewPayload { belong_to_id: app_id.to_string(), name: name.to_string(), desc: desc.to_string(), thumbnail: None, - data_type: view_type, + data_type, ext_data: "".to_string(), plugin_type: 0, }; diff --git a/frontend/rust-lib/flowy-sdk/src/lib.rs b/frontend/rust-lib/flowy-sdk/src/lib.rs index b335c37767..ad3480745b 100644 --- a/frontend/rust-lib/flowy-sdk/src/lib.rs +++ b/frontend/rust-lib/flowy-sdk/src/lib.rs @@ -67,7 +67,7 @@ fn crate_log_filter(level: String) -> String { filters.push(format!("flowy_folder={}", level)); filters.push(format!("flowy_user={}", level)); filters.push(format!("flowy_document={}", level)); - // filters.push(format!("flowy_collaboration={}", level)); + filters.push(format!("flowy_collaboration={}", "debug")); filters.push(format!("dart_notify={}", level)); filters.push(format!("lib_ot={}", level)); filters.push(format!("lib_ws={}", level)); @@ -76,7 +76,7 @@ fn crate_log_filter(level: String) -> String { filters.push(format!("dart_ffi={}", "info")); filters.push(format!("flowy_database={}", "info")); filters.push(format!("flowy_net={}", "info")); - filters.push(format!("flowy_sync={}", "info")); + filters.push(format!("flowy_sync={}", "trace")); filters.join(",") } diff --git a/frontend/rust-lib/flowy-sync/src/rev_manager.rs b/frontend/rust-lib/flowy-sync/src/rev_manager.rs index 468872428a..5583690913 100644 --- a/frontend/rust-lib/flowy-sync/src/rev_manager.rs +++ b/frontend/rust-lib/flowy-sync/src/rev_manager.rs @@ -55,8 +55,8 @@ impl RevisionManager { let (revisions, rev_id) = RevisionLoader { object_id: self.object_id.clone(), user_id: self.user_id.clone(), - cloud, - rev_cache: self.rev_persistence.clone(), + cloud: Some(cloud), + rev_persistence: self.rev_persistence.clone(), } .load() .await?; @@ -155,23 +155,28 @@ impl RevisionManager { } } -struct RevisionLoader { - object_id: String, - user_id: String, - cloud: Arc, - rev_cache: Arc, +pub struct RevisionLoader { + pub object_id: String, + pub user_id: String, + pub cloud: Option>, + pub rev_persistence: Arc, } impl RevisionLoader { - async fn load(&self) -> Result<(Vec, i64), FlowyError> { - let records = self.rev_cache.batch_get(&self.object_id)?; + pub async fn load(&self) -> Result<(Vec, i64), FlowyError> { + let records = self.rev_persistence.batch_get(&self.object_id)?; let revisions: Vec; let mut rev_id = 0; - if records.is_empty() { - let remote_revisions = self.cloud.fetch_object(&self.user_id, &self.object_id).await?; + if records.is_empty() && self.cloud.is_some() { + let remote_revisions = self + .cloud + .as_ref() + .unwrap() + .fetch_object(&self.user_id, &self.object_id) + .await?; for revision in &remote_revisions { rev_id = revision.rev_id; - let _ = self.rev_cache.add_ack_revision(revision).await?; + let _ = self.rev_persistence.add_ack_revision(revision).await?; } revisions = remote_revisions; } else { @@ -179,7 +184,7 @@ impl RevisionLoader { rev_id = record.revision.rev_id; if record.state == RevisionState::Sync { // Sync the records if their state is RevisionState::Sync. - let _ = self.rev_cache.sync_revision(&record.revision).await?; + let _ = self.rev_persistence.sync_revision(&record.revision).await?; } } revisions = records.into_iter().map(|record| record.revision).collect::<_>(); diff --git a/shared-lib/flowy-collaboration/src/client_document/default/mod.rs b/shared-lib/flowy-collaboration/src/client_document/default/mod.rs index c19349bf0b..35f674e41d 100644 --- a/shared-lib/flowy-collaboration/src/client_document/default/mod.rs +++ b/shared-lib/flowy-collaboration/src/client_document/default/mod.rs @@ -7,7 +7,7 @@ pub fn initial_delta() -> RichTextDelta { #[inline] pub fn initial_delta_string() -> String { - initial_delta().to_json() + initial_delta().to_delta_json() } #[inline] @@ -22,6 +22,6 @@ mod tests { #[test] fn load_read_me() { - println!("{}", initial_read_me().to_json()); + println!("{}", initial_read_me().to_delta_json()); } } diff --git a/shared-lib/flowy-collaboration/src/client_document/document_pad.rs b/shared-lib/flowy-collaboration/src/client_document/document_pad.rs index 2559955e6d..99a86769ce 100644 --- a/shared-lib/flowy-collaboration/src/client_document/document_pad.rs +++ b/shared-lib/flowy-collaboration/src/client_document/document_pad.rs @@ -59,7 +59,7 @@ impl ClientDocument { } pub fn to_json(&self) -> String { - self.delta.to_json() + self.delta.to_delta_json() } pub fn to_bytes(&self) -> Vec { @@ -84,7 +84,7 @@ impl ClientDocument { } pub fn set_delta(&mut self, data: RichTextDelta) { - tracing::trace!("document: {}", data.to_json()); + tracing::trace!("document: {}", data.to_delta_json()); self.delta = data; match &self.notify { @@ -96,7 +96,7 @@ impl ClientDocument { } pub fn compose_delta(&mut self, delta: RichTextDelta) -> Result<(), CollaborateError> { - tracing::trace!("{} compose {}", &self.delta.to_json(), delta.to_json()); + tracing::trace!("{} compose {}", &self.delta.to_delta_json(), delta.to_delta_json()); let composed_delta = self.delta.compose(&delta)?; let mut undo_delta = delta.invert(&self.delta); diff --git a/shared-lib/flowy-collaboration/src/client_folder/builder.rs b/shared-lib/flowy-collaboration/src/client_folder/builder.rs index 437977789f..c77c6ecf04 100644 --- a/shared-lib/flowy-collaboration/src/client_folder/builder.rs +++ b/shared-lib/flowy-collaboration/src/client_folder/builder.rs @@ -38,7 +38,9 @@ impl FolderPadBuilder { if delta.is_empty() { delta = default_folder_delta(); } - let folder_json = delta.apply("").unwrap(); + + // TODO: Reconvert from history if delta.to_str() failed. + let folder_json = delta.to_str()?; let mut folder: FolderPad = serde_json::from_str(&folder_json).map_err(|e| { CollaborateError::internal().context(format!("Deserialize json to root folder failed: {}", e)) })?; diff --git a/shared-lib/flowy-collaboration/src/client_folder/folder_pad.rs b/shared-lib/flowy-collaboration/src/client_folder/folder_pad.rs index 6e28ede769..4ce5a11c68 100644 --- a/shared-lib/flowy-collaboration/src/client_folder/folder_pad.rs +++ b/shared-lib/flowy-collaboration/src/client_folder/folder_pad.rs @@ -26,6 +26,12 @@ pub fn default_folder_delta() -> FolderDelta { .build() } +pub fn initial_folder_delta(folder_pad: &FolderPad) -> CollaborateResult { + let json = folder_pad.to_json()?; + let delta = PlainTextDeltaBuilder::new().insert(&json).build(); + Ok(delta) +} + impl std::default::Default for FolderPad { fn default() -> Self { FolderPad { diff --git a/shared-lib/flowy-collaboration/src/entities/document_info.rs b/shared-lib/flowy-collaboration/src/entities/document_info.rs index 5449dcd07a..a1cb853aab 100644 --- a/shared-lib/flowy-collaboration/src/entities/document_info.rs +++ b/shared-lib/flowy-collaboration/src/entities/document_info.rs @@ -46,7 +46,7 @@ impl std::convert::TryFrom for BlockInfo { } let delta = RichTextDelta::from_bytes(&revision.delta_data)?; - let doc_json = delta.to_json(); + let doc_json = delta.to_delta_json(); Ok(BlockInfo { doc_id: revision.object_id, diff --git a/shared-lib/flowy-collaboration/src/entities/revision.rs b/shared-lib/flowy-collaboration/src/entities/revision.rs index ec1ce54ebf..c85ba937fb 100644 --- a/shared-lib/flowy-collaboration/src/entities/revision.rs +++ b/shared-lib/flowy-collaboration/src/entities/revision.rs @@ -95,7 +95,7 @@ impl std::fmt::Debug for Revision { let _ = f.write_fmt(format_args!("rev_id {}, ", self.rev_id))?; match RichTextDelta::from_bytes(&self.delta_data) { Ok(delta) => { - let _ = f.write_fmt(format_args!("delta {:?}", delta.to_json()))?; + let _ = f.write_fmt(format_args!("delta {:?}", delta.to_delta_json()))?; } Err(e) => { let _ = f.write_fmt(format_args!("delta {:?}", e))?; diff --git a/shared-lib/flowy-collaboration/src/server_document/document_pad.rs b/shared-lib/flowy-collaboration/src/server_document/document_pad.rs index e7c02f5566..766fc5cb2a 100644 --- a/shared-lib/flowy-collaboration/src/server_document/document_pad.rs +++ b/shared-lib/flowy-collaboration/src/server_document/document_pad.rs @@ -39,7 +39,7 @@ impl RevisionSyncObject for ServerDocument { } fn to_json(&self) -> String { - self.delta.to_json() + self.delta.to_delta_json() } fn set_delta(&mut self, new_delta: Delta) { diff --git a/shared-lib/flowy-collaboration/src/server_folder/folder_pad.rs b/shared-lib/flowy-collaboration/src/server_folder/folder_pad.rs index a7c4746fea..eb1d6aa9dc 100644 --- a/shared-lib/flowy-collaboration/src/server_folder/folder_pad.rs +++ b/shared-lib/flowy-collaboration/src/server_folder/folder_pad.rs @@ -32,7 +32,7 @@ impl RevisionSyncObject for ServerFolder { } fn to_json(&self) -> String { - self.delta.to_json() + self.delta.to_delta_json() } fn set_delta(&mut self, new_delta: PlainTextDelta) { diff --git a/shared-lib/flowy-collaboration/src/util.rs b/shared-lib/flowy-collaboration/src/util.rs index f5f45f7f53..07db9cdbce 100644 --- a/shared-lib/flowy-collaboration/src/util.rs +++ b/shared-lib/flowy-collaboration/src/util.rs @@ -66,6 +66,7 @@ impl RevIdCounter { } } +#[tracing::instrument(level = "trace", skip(revisions), err)] pub fn make_delta_from_revisions(revisions: Vec) -> CollaborateResult> where T: Attributes + DeserializeOwned, @@ -186,7 +187,7 @@ pub fn make_folder_pb_from_revisions_pb( folder_delta = folder_delta.compose(&delta)?; } - let text = folder_delta.to_json(); + let text = folder_delta.to_delta_json(); let mut folder_info = FolderInfoPB::new(); folder_info.set_folder_id(folder_id.to_owned()); folder_info.set_text(text); @@ -236,7 +237,7 @@ pub fn make_document_info_pb_from_revisions_pb( document_delta = document_delta.compose(&delta)?; } - let text = document_delta.to_json(); + let text = document_delta.to_delta_json(); let mut block_info = BlockInfoPB::new(); block_info.set_doc_id(doc_id.to_owned()); block_info.set_text(text); diff --git a/shared-lib/lib-ot/src/core/delta/delta.rs b/shared-lib/lib-ot/src/core/delta/delta.rs index 0fc748a0e5..94dd904217 100644 --- a/shared-lib/lib-ot/src/core/delta/delta.rs +++ b/shared-lib/lib-ot/src/core/delta/delta.rs @@ -151,7 +151,13 @@ where pub fn apply(&self, s: &str) -> Result { let s: FlowyStr = s.into(); if s.utf16_size() != self.utf16_base_len { - return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build()); + return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength) + .msg(format!( + "Expected: {}, received: {}", + self.utf16_base_len, + s.utf16_size() + )) + .build()); } let mut new_s = String::new(); let code_point_iter = &mut s.utf16_code_unit_iter(); @@ -515,12 +521,16 @@ impl Delta where T: Attributes + serde::Serialize, { - pub fn to_json(&self) -> String { + pub fn to_delta_json(&self) -> String { serde_json::to_string(self).unwrap_or_else(|_| "".to_owned()) } + pub fn to_str(&self) -> Result { + self.apply("") + } + pub fn to_bytes(&self) -> Bytes { - let json = self.to_json(); + let json = self.to_delta_json(); Bytes::from(json.into_bytes()) } }