Browse Source

[flutter]: close stream before docpage dispose

appflowy 3 years ago
parent
commit
c4a6342c96

+ 1 - 6
app_flowy/lib/workspace/application/doc/doc_bloc.dart

@@ -28,12 +28,7 @@ class DocBloc extends Bloc<DocEvent, DocState> {
     final docOrFail = await iDocImpl.readDoc();
     yield docOrFail.fold(
       (doc) {
-        final flowyDoc = FlowyDoc(
-            doc: doc,
-            data: _decodeJsonToDocument(
-              doc.data,
-            ),
-            iDocImpl: iDocImpl);
+        final flowyDoc = FlowyDoc(doc: doc, iDocImpl: iDocImpl);
         return DocState.loadDoc(flowyDoc);
       },
       (error) {

+ 5 - 12
app_flowy/lib/workspace/application/doc/doc_edit_bloc.dart

@@ -12,24 +12,17 @@ class DocEditBloc extends Bloc<DocEditEvent, DocEditState> {
   @override
   Stream<DocEditState> mapEventToState(DocEditEvent event) async* {
     yield* event.map(
-        initial: (e) async* {},
-        close: (Close value) async* {
-          iDocImpl.closeDoc();
-        },
-        changeset: (Changeset changeset) async* {
-          iDocImpl.applyChangeset(json: changeset.data);
-        },
-        save: (Save save) async* {
-          // no need to save
-        });
+      initial: (e) async* {},
+      close: (Close value) async* {
+        iDocImpl.closeDoc();
+      },
+    );
   }
 }
 
 @freezed
 abstract class DocEditEvent with _$DocEditEvent {
   const factory DocEditEvent.initial() = Initial;
-  const factory DocEditEvent.changeset(String data) = Changeset;
-  const factory DocEditEvent.save(String data) = Save;
   const factory DocEditEvent.close() = Close;
 }
 

+ 0 - 277
app_flowy/lib/workspace/application/doc/doc_edit_bloc.freezed.dart

@@ -20,18 +20,6 @@ class _$DocEditEventTearOff {
     return const Initial();
   }
 
-  Changeset changeset(String data) {
-    return Changeset(
-      data,
-    );
-  }
-
-  Save save(String data) {
-    return Save(
-      data,
-    );
-  }
-
   Close close() {
     return const Close();
   }
@@ -45,16 +33,12 @@ mixin _$DocEditEvent {
   @optionalTypeArgs
   TResult when<TResult extends Object?>({
     required TResult Function() initial,
-    required TResult Function(String data) changeset,
-    required TResult Function(String data) save,
     required TResult Function() close,
   }) =>
       throw _privateConstructorUsedError;
   @optionalTypeArgs
   TResult maybeWhen<TResult extends Object?>({
     TResult Function()? initial,
-    TResult Function(String data)? changeset,
-    TResult Function(String data)? save,
     TResult Function()? close,
     required TResult orElse(),
   }) =>
@@ -62,16 +46,12 @@ mixin _$DocEditEvent {
   @optionalTypeArgs
   TResult map<TResult extends Object?>({
     required TResult Function(Initial value) initial,
-    required TResult Function(Changeset value) changeset,
-    required TResult Function(Save value) save,
     required TResult Function(Close value) close,
   }) =>
       throw _privateConstructorUsedError;
   @optionalTypeArgs
   TResult maybeMap<TResult extends Object?>({
     TResult Function(Initial value)? initial,
-    TResult Function(Changeset value)? changeset,
-    TResult Function(Save value)? save,
     TResult Function(Close value)? close,
     required TResult orElse(),
   }) =>
@@ -132,8 +112,6 @@ class _$Initial implements Initial {
   @optionalTypeArgs
   TResult when<TResult extends Object?>({
     required TResult Function() initial,
-    required TResult Function(String data) changeset,
-    required TResult Function(String data) save,
     required TResult Function() close,
   }) {
     return initial();
@@ -143,8 +121,6 @@ class _$Initial implements Initial {
   @optionalTypeArgs
   TResult maybeWhen<TResult extends Object?>({
     TResult Function()? initial,
-    TResult Function(String data)? changeset,
-    TResult Function(String data)? save,
     TResult Function()? close,
     required TResult orElse(),
   }) {
@@ -158,8 +134,6 @@ class _$Initial implements Initial {
   @optionalTypeArgs
   TResult map<TResult extends Object?>({
     required TResult Function(Initial value) initial,
-    required TResult Function(Changeset value) changeset,
-    required TResult Function(Save value) save,
     required TResult Function(Close value) close,
   }) {
     return initial(this);
@@ -169,8 +143,6 @@ class _$Initial implements Initial {
   @optionalTypeArgs
   TResult maybeMap<TResult extends Object?>({
     TResult Function(Initial value)? initial,
-    TResult Function(Changeset value)? changeset,
-    TResult Function(Save value)? save,
     TResult Function(Close value)? close,
     required TResult orElse(),
   }) {
@@ -185,247 +157,6 @@ abstract class Initial implements DocEditEvent {
   const factory Initial() = _$Initial;
 }
 
-/// @nodoc
-abstract class $ChangesetCopyWith<$Res> {
-  factory $ChangesetCopyWith(Changeset value, $Res Function(Changeset) then) =
-      _$ChangesetCopyWithImpl<$Res>;
-  $Res call({String data});
-}
-
-/// @nodoc
-class _$ChangesetCopyWithImpl<$Res> extends _$DocEditEventCopyWithImpl<$Res>
-    implements $ChangesetCopyWith<$Res> {
-  _$ChangesetCopyWithImpl(Changeset _value, $Res Function(Changeset) _then)
-      : super(_value, (v) => _then(v as Changeset));
-
-  @override
-  Changeset get _value => super._value as Changeset;
-
-  @override
-  $Res call({
-    Object? data = freezed,
-  }) {
-    return _then(Changeset(
-      data == freezed
-          ? _value.data
-          : data // ignore: cast_nullable_to_non_nullable
-              as String,
-    ));
-  }
-}
-
-/// @nodoc
-
-class _$Changeset implements Changeset {
-  const _$Changeset(this.data);
-
-  @override
-  final String data;
-
-  @override
-  String toString() {
-    return 'DocEditEvent.changeset(data: $data)';
-  }
-
-  @override
-  bool operator ==(dynamic other) {
-    return identical(this, other) ||
-        (other is Changeset &&
-            (identical(other.data, data) ||
-                const DeepCollectionEquality().equals(other.data, data)));
-  }
-
-  @override
-  int get hashCode =>
-      runtimeType.hashCode ^ const DeepCollectionEquality().hash(data);
-
-  @JsonKey(ignore: true)
-  @override
-  $ChangesetCopyWith<Changeset> get copyWith =>
-      _$ChangesetCopyWithImpl<Changeset>(this, _$identity);
-
-  @override
-  @optionalTypeArgs
-  TResult when<TResult extends Object?>({
-    required TResult Function() initial,
-    required TResult Function(String data) changeset,
-    required TResult Function(String data) save,
-    required TResult Function() close,
-  }) {
-    return changeset(data);
-  }
-
-  @override
-  @optionalTypeArgs
-  TResult maybeWhen<TResult extends Object?>({
-    TResult Function()? initial,
-    TResult Function(String data)? changeset,
-    TResult Function(String data)? save,
-    TResult Function()? close,
-    required TResult orElse(),
-  }) {
-    if (changeset != null) {
-      return changeset(data);
-    }
-    return orElse();
-  }
-
-  @override
-  @optionalTypeArgs
-  TResult map<TResult extends Object?>({
-    required TResult Function(Initial value) initial,
-    required TResult Function(Changeset value) changeset,
-    required TResult Function(Save value) save,
-    required TResult Function(Close value) close,
-  }) {
-    return changeset(this);
-  }
-
-  @override
-  @optionalTypeArgs
-  TResult maybeMap<TResult extends Object?>({
-    TResult Function(Initial value)? initial,
-    TResult Function(Changeset value)? changeset,
-    TResult Function(Save value)? save,
-    TResult Function(Close value)? close,
-    required TResult orElse(),
-  }) {
-    if (changeset != null) {
-      return changeset(this);
-    }
-    return orElse();
-  }
-}
-
-abstract class Changeset implements DocEditEvent {
-  const factory Changeset(String data) = _$Changeset;
-
-  String get data => throw _privateConstructorUsedError;
-  @JsonKey(ignore: true)
-  $ChangesetCopyWith<Changeset> get copyWith =>
-      throw _privateConstructorUsedError;
-}
-
-/// @nodoc
-abstract class $SaveCopyWith<$Res> {
-  factory $SaveCopyWith(Save value, $Res Function(Save) then) =
-      _$SaveCopyWithImpl<$Res>;
-  $Res call({String data});
-}
-
-/// @nodoc
-class _$SaveCopyWithImpl<$Res> extends _$DocEditEventCopyWithImpl<$Res>
-    implements $SaveCopyWith<$Res> {
-  _$SaveCopyWithImpl(Save _value, $Res Function(Save) _then)
-      : super(_value, (v) => _then(v as Save));
-
-  @override
-  Save get _value => super._value as Save;
-
-  @override
-  $Res call({
-    Object? data = freezed,
-  }) {
-    return _then(Save(
-      data == freezed
-          ? _value.data
-          : data // ignore: cast_nullable_to_non_nullable
-              as String,
-    ));
-  }
-}
-
-/// @nodoc
-
-class _$Save implements Save {
-  const _$Save(this.data);
-
-  @override
-  final String data;
-
-  @override
-  String toString() {
-    return 'DocEditEvent.save(data: $data)';
-  }
-
-  @override
-  bool operator ==(dynamic other) {
-    return identical(this, other) ||
-        (other is Save &&
-            (identical(other.data, data) ||
-                const DeepCollectionEquality().equals(other.data, data)));
-  }
-
-  @override
-  int get hashCode =>
-      runtimeType.hashCode ^ const DeepCollectionEquality().hash(data);
-
-  @JsonKey(ignore: true)
-  @override
-  $SaveCopyWith<Save> get copyWith =>
-      _$SaveCopyWithImpl<Save>(this, _$identity);
-
-  @override
-  @optionalTypeArgs
-  TResult when<TResult extends Object?>({
-    required TResult Function() initial,
-    required TResult Function(String data) changeset,
-    required TResult Function(String data) save,
-    required TResult Function() close,
-  }) {
-    return save(data);
-  }
-
-  @override
-  @optionalTypeArgs
-  TResult maybeWhen<TResult extends Object?>({
-    TResult Function()? initial,
-    TResult Function(String data)? changeset,
-    TResult Function(String data)? save,
-    TResult Function()? close,
-    required TResult orElse(),
-  }) {
-    if (save != null) {
-      return save(data);
-    }
-    return orElse();
-  }
-
-  @override
-  @optionalTypeArgs
-  TResult map<TResult extends Object?>({
-    required TResult Function(Initial value) initial,
-    required TResult Function(Changeset value) changeset,
-    required TResult Function(Save value) save,
-    required TResult Function(Close value) close,
-  }) {
-    return save(this);
-  }
-
-  @override
-  @optionalTypeArgs
-  TResult maybeMap<TResult extends Object?>({
-    TResult Function(Initial value)? initial,
-    TResult Function(Changeset value)? changeset,
-    TResult Function(Save value)? save,
-    TResult Function(Close value)? close,
-    required TResult orElse(),
-  }) {
-    if (save != null) {
-      return save(this);
-    }
-    return orElse();
-  }
-}
-
-abstract class Save implements DocEditEvent {
-  const factory Save(String data) = _$Save;
-
-  String get data => throw _privateConstructorUsedError;
-  @JsonKey(ignore: true)
-  $SaveCopyWith<Save> get copyWith => throw _privateConstructorUsedError;
-}
-
 /// @nodoc
 abstract class $CloseCopyWith<$Res> {
   factory $CloseCopyWith(Close value, $Res Function(Close) then) =
@@ -464,8 +195,6 @@ class _$Close implements Close {
   @optionalTypeArgs
   TResult when<TResult extends Object?>({
     required TResult Function() initial,
-    required TResult Function(String data) changeset,
-    required TResult Function(String data) save,
     required TResult Function() close,
   }) {
     return close();
@@ -475,8 +204,6 @@ class _$Close implements Close {
   @optionalTypeArgs
   TResult maybeWhen<TResult extends Object?>({
     TResult Function()? initial,
-    TResult Function(String data)? changeset,
-    TResult Function(String data)? save,
     TResult Function()? close,
     required TResult orElse(),
   }) {
@@ -490,8 +217,6 @@ class _$Close implements Close {
   @optionalTypeArgs
   TResult map<TResult extends Object?>({
     required TResult Function(Initial value) initial,
-    required TResult Function(Changeset value) changeset,
-    required TResult Function(Save value) save,
     required TResult Function(Close value) close,
   }) {
     return close(this);
@@ -501,8 +226,6 @@ class _$Close implements Close {
   @optionalTypeArgs
   TResult maybeMap<TResult extends Object?>({
     TResult Function(Initial value)? initial,
-    TResult Function(Changeset value)? changeset,
-    TResult Function(Save value)? save,
     TResult Function(Close value)? close,
     required TResult orElse(),
   }) {

+ 29 - 17
app_flowy/lib/workspace/domain/i_doc.dart

@@ -1,5 +1,5 @@
 import 'dart:convert';
-
+import 'dart:async';
 import 'package:flowy_editor/flowy_editor.dart';
 import 'package:dartz/dartz.dart';
 // ignore: implementation_imports
@@ -8,40 +8,52 @@ import 'package:flowy_log/flowy_log.dart';
 import 'package:flowy_sdk/protobuf/flowy-document/doc.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
 
-class FlowyDoc implements EditorDeltaSender {
+class FlowyDoc {
   final DocDelta doc;
   final IDoc iDocImpl;
-  Document data;
+  late Document document;
+  late StreamSubscription _subscription;
+
+  FlowyDoc({required this.doc, required this.iDocImpl}) {
+    document = _decodeJsonToDocument(doc.data);
 
-  FlowyDoc({required this.doc, required this.data, required this.iDocImpl}) {
-    data.sender = this;
+    _subscription = document.changes.listen((event) {
+      final delta = event.item2;
+      final documentDelta = document.toDelta();
+      _composeDelta(delta, documentDelta);
+    });
   }
+
   String get id => doc.docId;
 
-  @override
-  void sendNewDelta(Delta changeset, Delta delta) async {
-    final json = jsonEncode(changeset.toJson());
+  Future<void> close() async {
+    await _subscription.cancel();
+  }
+
+  void _composeDelta(Delta composedDelta, Delta documentDelta) async {
+    final json = jsonEncode(composedDelta.toJson());
     Log.debug("Send json: $json");
-    final result = await iDocImpl.applyChangeset(json: json);
+    final result = await iDocImpl.composeDelta(json: json);
 
     result.fold((rustDoc) {
       // final json = utf8.decode(doc.data);
       final rustDelta = Delta.fromJson(jsonDecode(rustDoc.data));
-
-      if (delta != rustDelta) {
+      if (documentDelta != rustDelta) {
         Log.error("Receive : $rustDelta");
-        Log.error("Expected : $delta");
-      } else {
-        Log.info("Receive : $rustDelta");
-        Log.info("Expected : $delta");
+        Log.error("Expected : $documentDelta");
       }
     }, (r) => null);
   }
+
+  Document _decodeJsonToDocument(String data) {
+    final json = jsonDecode(data);
+    final document = Document.fromJson(json);
+    return document;
+  }
 }
 
 abstract class IDoc {
   Future<Either<DocDelta, WorkspaceError>> readDoc();
-  Future<Either<DocDelta, WorkspaceError>> applyChangeset(
-      {required String json});
+  Future<Either<DocDelta, WorkspaceError>> composeDelta({required String json});
   Future<Either<Unit, WorkspaceError>> closeDoc();
 }

+ 2 - 2
app_flowy/lib/workspace/infrastructure/i_doc_impl.dart

@@ -24,9 +24,9 @@ class IDocImpl extends IDoc {
   }
 
   @override
-  Future<Either<DocDelta, WorkspaceError>> applyChangeset(
+  Future<Either<DocDelta, WorkspaceError>> composeDelta(
       {required String json}) {
-    return repo.applyDelta(data: json);
+    return repo.composeDelta(data: json);
   }
 }
 

+ 7 - 2
app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart

@@ -1,4 +1,5 @@
 import 'package:dartz/dartz.dart';
+import 'package:flowy_log/flowy_log.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/protobuf/flowy-document/doc.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
@@ -15,7 +16,8 @@ class DocRepository {
     return WorkspaceEventOpenView(request).send();
   }
 
-  Future<Either<DocDelta, WorkspaceError>> applyDelta({required String data}) {
+  Future<Either<DocDelta, WorkspaceError>> composeDelta(
+      {required String data}) {
     final request = DocDelta.create()
       ..docId = docId
       ..data = data;
@@ -24,6 +26,9 @@ class DocRepository {
 
   Future<Either<Unit, WorkspaceError>> closeDoc(
       {String? name, String? desc, String? text}) {
-    throw UnimplementedError();
+    Log.error('Close the doc');
+    return Future(() {
+      return left(unit);
+    });
   }
 }

+ 23 - 9
app_flowy/lib/workspace/presentation/doc/doc_page.dart

@@ -8,31 +8,37 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 // ignore: must_be_immutable
-class DocPage extends StatelessWidget {
-  final FocusNode _focusNode = FocusNode();
+class DocPage extends StatefulWidget {
   late EditorController controller;
+  late DocEditBloc editBloc;
   final FlowyDoc doc;
 
   DocPage({Key? key, required this.doc}) : super(key: key) {
-    // getIt<EditorDeltaSender>(param1: doc.id))
-
+    editBloc = getIt<DocEditBloc>(param1: doc.id);
     controller = EditorController(
-      document: doc.data,
+      document: doc.document,
       selection: const TextSelection.collapsed(offset: 0),
     );
   }
 
+  @override
+  State<DocPage> createState() => _DocPageState();
+}
+
+class _DocPageState extends State<DocPage> {
+  final FocusNode _focusNode = FocusNode();
+
   @override
   Widget build(BuildContext context) {
-    return BlocProvider(
-      create: (context) => getIt<DocEditBloc>(param1: doc.id),
+    return BlocProvider.value(
+      value: widget.editBloc,
       child: BlocBuilder<DocEditBloc, DocEditState>(
         builder: (ctx, state) {
           return Column(
             mainAxisAlignment: MainAxisAlignment.spaceBetween,
             children: [
-              _renderEditor(controller),
-              _renderToolbar(controller),
+              _renderEditor(widget.controller),
+              _renderToolbar(widget.controller),
             ],
           );
         },
@@ -40,6 +46,14 @@ class DocPage extends StatelessWidget {
     );
   }
 
+  @override
+  Future<void> dispose() async {
+    widget.editBloc.add(const DocEditEvent.close());
+    widget.editBloc.close();
+    super.dispose();
+    await widget.doc.close();
+  }
+
   Widget _renderEditor(EditorController controller) {
     final editor = FlowyEditor(
       controller: controller,

+ 1 - 8
app_flowy/packages/flowy_editor/lib/src/model/document/document.dart

@@ -14,14 +14,9 @@ import 'node/line.dart';
 import 'node/node.dart';
 import 'package:flowy_log/flowy_log.dart';
 
-abstract class EditorDeltaSender {
-  void sendNewDelta(Delta changeset, Delta delta);
-}
-
 /// The rich text document
 class Document {
-  EditorDeltaSender? sender;
-  Document({this.sender}) : _delta = Delta()..insert('\n') {
+  Document() : _delta = Delta()..insert('\n') {
     _loadDocument(_delta);
   }
 
@@ -170,8 +165,6 @@ class Document {
       final changeset = delta;
 
       _delta = _delta.compose(delta);
-
-      sender?.sendNewDelta(changeset, _delta);
     } catch (e) {
       throw '_delta compose failed';
     }