diff --git a/app_flowy/lib/workspace/application/app/app_listen_bloc.dart b/app_flowy/lib/workspace/application/app/app_listen_bloc.dart index 820c846345..657980867e 100644 --- a/app_flowy/lib/workspace/application/app/app_listen_bloc.dart +++ b/app_flowy/lib/workspace/application/app/app_listen_bloc.dart @@ -18,6 +18,7 @@ class AppListenBloc extends Bloc { yield* event.map(started: (_) async* { listener.start( addViewCallback: (viewsOrFail) => _handleViewsOrFail(viewsOrFail), + deleteViewCallback: (viewsOrFail) => _handleViewsOrFail(viewsOrFail), ); }, didReceiveViews: (ViewsReceived value) async* { yield value.viewsOrFail.fold( diff --git a/app_flowy/lib/workspace/application/view/view_bloc.dart b/app_flowy/lib/workspace/application/view/view_bloc.dart index 82f93f01b4..b8a9b98cab 100644 --- a/app_flowy/lib/workspace/application/view/view_bloc.dart +++ b/app_flowy/lib/workspace/application/view/view_bloc.dart @@ -1,4 +1,3 @@ -import 'package:app_flowy/workspace/domain/view_edit.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; @@ -10,49 +9,71 @@ part 'view_bloc.freezed.dart'; class ViewBloc extends Bloc { final IView iViewImpl; + final IViewListener listener; ViewBloc({ required this.iViewImpl, - }) : super(ViewState.initial(iViewImpl.view)); + required this.listener, + }) : super(ViewState.init(iViewImpl.view)); @override Stream mapEventToState(ViewEvent event) async* { - yield* event.map( - setIsSelected: (e) async* { - yield state.copyWith(isSelected: e.isSelected); - }, - setIsEditing: (e) async* { - yield state.copyWith(isEditing: e.isEditing); - }, - setAction: (e) async* { - yield state.copyWith(action: e.action); - }, + yield* event.map(initial: (e) async* { + listener.start(updatedCallback: (result) => add(ViewEvent.viewDidUpdate(result))); + yield state; + }, setIsEditing: (e) async* { + yield state.copyWith(isEditing: e.isEditing); + }, viewDidUpdate: (e) async* { + yield* _handleViewDidUpdate(e.result); + }, rename: (e) async* { + final result = await iViewImpl.rename(e.newName); + yield result.fold( + (l) => state.copyWith(successOrFailure: left(unit)), + (error) => state.copyWith(successOrFailure: right(error)), + ); + }, delete: (e) async* { + final result = await iViewImpl.pushIntoTrash(); + yield result.fold( + (l) => state.copyWith(successOrFailure: left(unit)), + (error) => state.copyWith(successOrFailure: right(error)), + ); + }); + } + + Stream _handleViewDidUpdate(Either result) async* { + yield result.fold( + (view) => state.copyWith(view: view, successOrFailure: left(unit)), + (error) => state.copyWith(successOrFailure: right(error)), ); } + + @override + Future close() async { + await listener.stop(); + return super.close(); + } } @freezed class ViewEvent with _$ViewEvent { - const factory ViewEvent.setIsSelected(bool isSelected) = SetSelected; + const factory ViewEvent.initial() = Initial; const factory ViewEvent.setIsEditing(bool isEditing) = SetEditing; - const factory ViewEvent.setAction(Option action) = SetAction; + const factory ViewEvent.rename(String newName) = Rename; + const factory ViewEvent.delete() = Delete; + const factory ViewEvent.viewDidUpdate(Either result) = ViewDidUpdate; } @freezed class ViewState with _$ViewState { const factory ViewState({ required View view, - required bool isSelected, required bool isEditing, - required Option action, required Either successOrFailure, }) = _ViewState; - factory ViewState.initial(View view) => ViewState( + factory ViewState.init(View view) => ViewState( view: view, - isSelected: false, isEditing: false, - action: none(), successOrFailure: left(unit), ); } diff --git a/app_flowy/lib/workspace/application/view/view_bloc.freezed.dart b/app_flowy/lib/workspace/application/view/view_bloc.freezed.dart index 1c8d0c1f0c..1977c21159 100644 --- a/app_flowy/lib/workspace/application/view/view_bloc.freezed.dart +++ b/app_flowy/lib/workspace/application/view/view_bloc.freezed.dart @@ -16,10 +16,8 @@ final _privateConstructorUsedError = UnsupportedError( class _$ViewEventTearOff { const _$ViewEventTearOff(); - SetSelected setIsSelected(bool isSelected) { - return SetSelected( - isSelected, - ); + Initial initial() { + return const Initial(); } SetEditing setIsEditing(bool isEditing) { @@ -28,9 +26,19 @@ class _$ViewEventTearOff { ); } - SetAction setAction(Option action) { - return SetAction( - action, + Rename rename(String newName) { + return Rename( + newName, + ); + } + + Delete delete() { + return const Delete(); + } + + ViewDidUpdate viewDidUpdate(Either result) { + return ViewDidUpdate( + result, ); } } @@ -42,31 +50,40 @@ const $ViewEvent = _$ViewEventTearOff(); mixin _$ViewEvent { @optionalTypeArgs TResult when({ - required TResult Function(bool isSelected) setIsSelected, + required TResult Function() initial, required TResult Function(bool isEditing) setIsEditing, - required TResult Function(Option action) setAction, + required TResult Function(String newName) rename, + required TResult Function() delete, + required TResult Function(Either result) + viewDidUpdate, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeWhen({ - TResult Function(bool isSelected)? setIsSelected, + TResult Function()? initial, TResult Function(bool isEditing)? setIsEditing, - TResult Function(Option action)? setAction, + TResult Function(String newName)? rename, + TResult Function()? delete, + TResult Function(Either result)? viewDidUpdate, required TResult orElse(), }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult map({ - required TResult Function(SetSelected value) setIsSelected, + required TResult Function(Initial value) initial, required TResult Function(SetEditing value) setIsEditing, - required TResult Function(SetAction value) setAction, + required TResult Function(Rename value) rename, + required TResult Function(Delete value) delete, + required TResult Function(ViewDidUpdate value) viewDidUpdate, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeMap({ - TResult Function(SetSelected value)? setIsSelected, + TResult Function(Initial value)? initial, TResult Function(SetEditing value)? setIsEditing, - TResult Function(SetAction value)? setAction, + TResult Function(Rename value)? rename, + TResult Function(Delete value)? delete, + TResult Function(ViewDidUpdate value)? viewDidUpdate, required TResult orElse(), }) => throw _privateConstructorUsedError; @@ -88,87 +105,64 @@ class _$ViewEventCopyWithImpl<$Res> implements $ViewEventCopyWith<$Res> { } /// @nodoc -abstract class $SetSelectedCopyWith<$Res> { - factory $SetSelectedCopyWith( - SetSelected value, $Res Function(SetSelected) then) = - _$SetSelectedCopyWithImpl<$Res>; - $Res call({bool isSelected}); +abstract class $InitialCopyWith<$Res> { + factory $InitialCopyWith(Initial value, $Res Function(Initial) then) = + _$InitialCopyWithImpl<$Res>; } /// @nodoc -class _$SetSelectedCopyWithImpl<$Res> extends _$ViewEventCopyWithImpl<$Res> - implements $SetSelectedCopyWith<$Res> { - _$SetSelectedCopyWithImpl( - SetSelected _value, $Res Function(SetSelected) _then) - : super(_value, (v) => _then(v as SetSelected)); +class _$InitialCopyWithImpl<$Res> extends _$ViewEventCopyWithImpl<$Res> + implements $InitialCopyWith<$Res> { + _$InitialCopyWithImpl(Initial _value, $Res Function(Initial) _then) + : super(_value, (v) => _then(v as Initial)); @override - SetSelected get _value => super._value as SetSelected; - - @override - $Res call({ - Object? isSelected = freezed, - }) { - return _then(SetSelected( - isSelected == freezed - ? _value.isSelected - : isSelected // ignore: cast_nullable_to_non_nullable - as bool, - )); - } + Initial get _value => super._value as Initial; } /// @nodoc -class _$SetSelected implements SetSelected { - const _$SetSelected(this.isSelected); - - @override - final bool isSelected; +class _$Initial implements Initial { + const _$Initial(); @override String toString() { - return 'ViewEvent.setIsSelected(isSelected: $isSelected)'; + return 'ViewEvent.initial()'; } @override bool operator ==(dynamic other) { - return identical(this, other) || - (other is SetSelected && - (identical(other.isSelected, isSelected) || - const DeepCollectionEquality() - .equals(other.isSelected, isSelected))); + return identical(this, other) || (other is Initial); } @override - int get hashCode => - runtimeType.hashCode ^ const DeepCollectionEquality().hash(isSelected); - - @JsonKey(ignore: true) - @override - $SetSelectedCopyWith get copyWith => - _$SetSelectedCopyWithImpl(this, _$identity); + int get hashCode => runtimeType.hashCode; @override @optionalTypeArgs TResult when({ - required TResult Function(bool isSelected) setIsSelected, + required TResult Function() initial, required TResult Function(bool isEditing) setIsEditing, - required TResult Function(Option action) setAction, + required TResult Function(String newName) rename, + required TResult Function() delete, + required TResult Function(Either result) + viewDidUpdate, }) { - return setIsSelected(isSelected); + return initial(); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(bool isSelected)? setIsSelected, + TResult Function()? initial, TResult Function(bool isEditing)? setIsEditing, - TResult Function(Option action)? setAction, + TResult Function(String newName)? rename, + TResult Function()? delete, + TResult Function(Either result)? viewDidUpdate, required TResult orElse(), }) { - if (setIsSelected != null) { - return setIsSelected(isSelected); + if (initial != null) { + return initial(); } return orElse(); } @@ -176,35 +170,34 @@ class _$SetSelected implements SetSelected { @override @optionalTypeArgs TResult map({ - required TResult Function(SetSelected value) setIsSelected, + required TResult Function(Initial value) initial, required TResult Function(SetEditing value) setIsEditing, - required TResult Function(SetAction value) setAction, + required TResult Function(Rename value) rename, + required TResult Function(Delete value) delete, + required TResult Function(ViewDidUpdate value) viewDidUpdate, }) { - return setIsSelected(this); + return initial(this); } @override @optionalTypeArgs TResult maybeMap({ - TResult Function(SetSelected value)? setIsSelected, + TResult Function(Initial value)? initial, TResult Function(SetEditing value)? setIsEditing, - TResult Function(SetAction value)? setAction, + TResult Function(Rename value)? rename, + TResult Function(Delete value)? delete, + TResult Function(ViewDidUpdate value)? viewDidUpdate, required TResult orElse(), }) { - if (setIsSelected != null) { - return setIsSelected(this); + if (initial != null) { + return initial(this); } return orElse(); } } -abstract class SetSelected implements ViewEvent { - const factory SetSelected(bool isSelected) = _$SetSelected; - - bool get isSelected => throw _privateConstructorUsedError; - @JsonKey(ignore: true) - $SetSelectedCopyWith get copyWith => - throw _privateConstructorUsedError; +abstract class Initial implements ViewEvent { + const factory Initial() = _$Initial; } /// @nodoc @@ -271,9 +264,12 @@ class _$SetEditing implements SetEditing { @override @optionalTypeArgs TResult when({ - required TResult Function(bool isSelected) setIsSelected, + required TResult Function() initial, required TResult Function(bool isEditing) setIsEditing, - required TResult Function(Option action) setAction, + required TResult Function(String newName) rename, + required TResult Function() delete, + required TResult Function(Either result) + viewDidUpdate, }) { return setIsEditing(isEditing); } @@ -281,9 +277,11 @@ class _$SetEditing implements SetEditing { @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(bool isSelected)? setIsSelected, + TResult Function()? initial, TResult Function(bool isEditing)? setIsEditing, - TResult Function(Option action)? setAction, + TResult Function(String newName)? rename, + TResult Function()? delete, + TResult Function(Either result)? viewDidUpdate, required TResult orElse(), }) { if (setIsEditing != null) { @@ -295,9 +293,11 @@ class _$SetEditing implements SetEditing { @override @optionalTypeArgs TResult map({ - required TResult Function(SetSelected value) setIsSelected, + required TResult Function(Initial value) initial, required TResult Function(SetEditing value) setIsEditing, - required TResult Function(SetAction value) setAction, + required TResult Function(Rename value) rename, + required TResult Function(Delete value) delete, + required TResult Function(ViewDidUpdate value) viewDidUpdate, }) { return setIsEditing(this); } @@ -305,9 +305,11 @@ class _$SetEditing implements SetEditing { @override @optionalTypeArgs TResult maybeMap({ - TResult Function(SetSelected value)? setIsSelected, + TResult Function(Initial value)? initial, TResult Function(SetEditing value)? setIsEditing, - TResult Function(SetAction value)? setAction, + TResult Function(Rename value)? rename, + TResult Function(Delete value)? delete, + TResult Function(ViewDidUpdate value)? viewDidUpdate, required TResult orElse(), }) { if (setIsEditing != null) { @@ -327,84 +329,89 @@ abstract class SetEditing implements ViewEvent { } /// @nodoc -abstract class $SetActionCopyWith<$Res> { - factory $SetActionCopyWith(SetAction value, $Res Function(SetAction) then) = - _$SetActionCopyWithImpl<$Res>; - $Res call({Option action}); +abstract class $RenameCopyWith<$Res> { + factory $RenameCopyWith(Rename value, $Res Function(Rename) then) = + _$RenameCopyWithImpl<$Res>; + $Res call({String newName}); } /// @nodoc -class _$SetActionCopyWithImpl<$Res> extends _$ViewEventCopyWithImpl<$Res> - implements $SetActionCopyWith<$Res> { - _$SetActionCopyWithImpl(SetAction _value, $Res Function(SetAction) _then) - : super(_value, (v) => _then(v as SetAction)); +class _$RenameCopyWithImpl<$Res> extends _$ViewEventCopyWithImpl<$Res> + implements $RenameCopyWith<$Res> { + _$RenameCopyWithImpl(Rename _value, $Res Function(Rename) _then) + : super(_value, (v) => _then(v as Rename)); @override - SetAction get _value => super._value as SetAction; + Rename get _value => super._value as Rename; @override $Res call({ - Object? action = freezed, + Object? newName = freezed, }) { - return _then(SetAction( - action == freezed - ? _value.action - : action // ignore: cast_nullable_to_non_nullable - as Option, + return _then(Rename( + newName == freezed + ? _value.newName + : newName // ignore: cast_nullable_to_non_nullable + as String, )); } } /// @nodoc -class _$SetAction implements SetAction { - const _$SetAction(this.action); +class _$Rename implements Rename { + const _$Rename(this.newName); @override - final Option action; + final String newName; @override String toString() { - return 'ViewEvent.setAction(action: $action)'; + return 'ViewEvent.rename(newName: $newName)'; } @override bool operator ==(dynamic other) { return identical(this, other) || - (other is SetAction && - (identical(other.action, action) || - const DeepCollectionEquality().equals(other.action, action))); + (other is Rename && + (identical(other.newName, newName) || + const DeepCollectionEquality().equals(other.newName, newName))); } @override int get hashCode => - runtimeType.hashCode ^ const DeepCollectionEquality().hash(action); + runtimeType.hashCode ^ const DeepCollectionEquality().hash(newName); @JsonKey(ignore: true) @override - $SetActionCopyWith get copyWith => - _$SetActionCopyWithImpl(this, _$identity); + $RenameCopyWith get copyWith => + _$RenameCopyWithImpl(this, _$identity); @override @optionalTypeArgs TResult when({ - required TResult Function(bool isSelected) setIsSelected, + required TResult Function() initial, required TResult Function(bool isEditing) setIsEditing, - required TResult Function(Option action) setAction, + required TResult Function(String newName) rename, + required TResult Function() delete, + required TResult Function(Either result) + viewDidUpdate, }) { - return setAction(action); + return rename(newName); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(bool isSelected)? setIsSelected, + TResult Function()? initial, TResult Function(bool isEditing)? setIsEditing, - TResult Function(Option action)? setAction, + TResult Function(String newName)? rename, + TResult Function()? delete, + TResult Function(Either result)? viewDidUpdate, required TResult orElse(), }) { - if (setAction != null) { - return setAction(action); + if (rename != null) { + return rename(newName); } return orElse(); } @@ -412,34 +419,262 @@ class _$SetAction implements SetAction { @override @optionalTypeArgs TResult map({ - required TResult Function(SetSelected value) setIsSelected, + required TResult Function(Initial value) initial, required TResult Function(SetEditing value) setIsEditing, - required TResult Function(SetAction value) setAction, + required TResult Function(Rename value) rename, + required TResult Function(Delete value) delete, + required TResult Function(ViewDidUpdate value) viewDidUpdate, }) { - return setAction(this); + return rename(this); } @override @optionalTypeArgs TResult maybeMap({ - TResult Function(SetSelected value)? setIsSelected, + TResult Function(Initial value)? initial, TResult Function(SetEditing value)? setIsEditing, - TResult Function(SetAction value)? setAction, + TResult Function(Rename value)? rename, + TResult Function(Delete value)? delete, + TResult Function(ViewDidUpdate value)? viewDidUpdate, required TResult orElse(), }) { - if (setAction != null) { - return setAction(this); + if (rename != null) { + return rename(this); } return orElse(); } } -abstract class SetAction implements ViewEvent { - const factory SetAction(Option action) = _$SetAction; +abstract class Rename implements ViewEvent { + const factory Rename(String newName) = _$Rename; - Option get action => throw _privateConstructorUsedError; + String get newName => throw _privateConstructorUsedError; @JsonKey(ignore: true) - $SetActionCopyWith get copyWith => + $RenameCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DeleteCopyWith<$Res> { + factory $DeleteCopyWith(Delete value, $Res Function(Delete) then) = + _$DeleteCopyWithImpl<$Res>; +} + +/// @nodoc +class _$DeleteCopyWithImpl<$Res> extends _$ViewEventCopyWithImpl<$Res> + implements $DeleteCopyWith<$Res> { + _$DeleteCopyWithImpl(Delete _value, $Res Function(Delete) _then) + : super(_value, (v) => _then(v as Delete)); + + @override + Delete get _value => super._value as Delete; +} + +/// @nodoc + +class _$Delete implements Delete { + const _$Delete(); + + @override + String toString() { + return 'ViewEvent.delete()'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || (other is Delete); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function(bool isEditing) setIsEditing, + required TResult Function(String newName) rename, + required TResult Function() delete, + required TResult Function(Either result) + viewDidUpdate, + }) { + return delete(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function(bool isEditing)? setIsEditing, + TResult Function(String newName)? rename, + TResult Function()? delete, + TResult Function(Either result)? viewDidUpdate, + required TResult orElse(), + }) { + if (delete != null) { + return delete(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(Initial value) initial, + required TResult Function(SetEditing value) setIsEditing, + required TResult Function(Rename value) rename, + required TResult Function(Delete value) delete, + required TResult Function(ViewDidUpdate value) viewDidUpdate, + }) { + return delete(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(Initial value)? initial, + TResult Function(SetEditing value)? setIsEditing, + TResult Function(Rename value)? rename, + TResult Function(Delete value)? delete, + TResult Function(ViewDidUpdate value)? viewDidUpdate, + required TResult orElse(), + }) { + if (delete != null) { + return delete(this); + } + return orElse(); + } +} + +abstract class Delete implements ViewEvent { + const factory Delete() = _$Delete; +} + +/// @nodoc +abstract class $ViewDidUpdateCopyWith<$Res> { + factory $ViewDidUpdateCopyWith( + ViewDidUpdate value, $Res Function(ViewDidUpdate) then) = + _$ViewDidUpdateCopyWithImpl<$Res>; + $Res call({Either result}); +} + +/// @nodoc +class _$ViewDidUpdateCopyWithImpl<$Res> extends _$ViewEventCopyWithImpl<$Res> + implements $ViewDidUpdateCopyWith<$Res> { + _$ViewDidUpdateCopyWithImpl( + ViewDidUpdate _value, $Res Function(ViewDidUpdate) _then) + : super(_value, (v) => _then(v as ViewDidUpdate)); + + @override + ViewDidUpdate get _value => super._value as ViewDidUpdate; + + @override + $Res call({ + Object? result = freezed, + }) { + return _then(ViewDidUpdate( + result == freezed + ? _value.result + : result // ignore: cast_nullable_to_non_nullable + as Either, + )); + } +} + +/// @nodoc + +class _$ViewDidUpdate implements ViewDidUpdate { + const _$ViewDidUpdate(this.result); + + @override + final Either result; + + @override + String toString() { + return 'ViewEvent.viewDidUpdate(result: $result)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other is ViewDidUpdate && + (identical(other.result, result) || + const DeepCollectionEquality().equals(other.result, result))); + } + + @override + int get hashCode => + runtimeType.hashCode ^ const DeepCollectionEquality().hash(result); + + @JsonKey(ignore: true) + @override + $ViewDidUpdateCopyWith get copyWith => + _$ViewDidUpdateCopyWithImpl(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function(bool isEditing) setIsEditing, + required TResult Function(String newName) rename, + required TResult Function() delete, + required TResult Function(Either result) + viewDidUpdate, + }) { + return viewDidUpdate(result); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function(bool isEditing)? setIsEditing, + TResult Function(String newName)? rename, + TResult Function()? delete, + TResult Function(Either result)? viewDidUpdate, + required TResult orElse(), + }) { + if (viewDidUpdate != null) { + return viewDidUpdate(result); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(Initial value) initial, + required TResult Function(SetEditing value) setIsEditing, + required TResult Function(Rename value) rename, + required TResult Function(Delete value) delete, + required TResult Function(ViewDidUpdate value) viewDidUpdate, + }) { + return viewDidUpdate(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(Initial value)? initial, + TResult Function(SetEditing value)? setIsEditing, + TResult Function(Rename value)? rename, + TResult Function(Delete value)? delete, + TResult Function(ViewDidUpdate value)? viewDidUpdate, + required TResult orElse(), + }) { + if (viewDidUpdate != null) { + return viewDidUpdate(this); + } + return orElse(); + } +} + +abstract class ViewDidUpdate implements ViewEvent { + const factory ViewDidUpdate(Either result) = + _$ViewDidUpdate; + + Either get result => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $ViewDidUpdateCopyWith get copyWith => throw _privateConstructorUsedError; } @@ -449,15 +684,11 @@ class _$ViewStateTearOff { _ViewState call( {required View view, - required bool isSelected, required bool isEditing, - required Option action, required Either successOrFailure}) { return _ViewState( view: view, - isSelected: isSelected, isEditing: isEditing, - action: action, successOrFailure: successOrFailure, ); } @@ -469,9 +700,7 @@ const $ViewState = _$ViewStateTearOff(); /// @nodoc mixin _$ViewState { View get view => throw _privateConstructorUsedError; - bool get isSelected => throw _privateConstructorUsedError; bool get isEditing => throw _privateConstructorUsedError; - Option get action => throw _privateConstructorUsedError; Either get successOrFailure => throw _privateConstructorUsedError; @@ -486,9 +715,7 @@ abstract class $ViewStateCopyWith<$Res> { _$ViewStateCopyWithImpl<$Res>; $Res call( {View view, - bool isSelected, bool isEditing, - Option action, Either successOrFailure}); } @@ -503,9 +730,7 @@ class _$ViewStateCopyWithImpl<$Res> implements $ViewStateCopyWith<$Res> { @override $Res call({ Object? view = freezed, - Object? isSelected = freezed, Object? isEditing = freezed, - Object? action = freezed, Object? successOrFailure = freezed, }) { return _then(_value.copyWith( @@ -513,18 +738,10 @@ class _$ViewStateCopyWithImpl<$Res> implements $ViewStateCopyWith<$Res> { ? _value.view : view // ignore: cast_nullable_to_non_nullable as View, - isSelected: isSelected == freezed - ? _value.isSelected - : isSelected // ignore: cast_nullable_to_non_nullable - as bool, isEditing: isEditing == freezed ? _value.isEditing : isEditing // ignore: cast_nullable_to_non_nullable as bool, - action: action == freezed - ? _value.action - : action // ignore: cast_nullable_to_non_nullable - as Option, successOrFailure: successOrFailure == freezed ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable @@ -541,9 +758,7 @@ abstract class _$ViewStateCopyWith<$Res> implements $ViewStateCopyWith<$Res> { @override $Res call( {View view, - bool isSelected, bool isEditing, - Option action, Either successOrFailure}); } @@ -559,9 +774,7 @@ class __$ViewStateCopyWithImpl<$Res> extends _$ViewStateCopyWithImpl<$Res> @override $Res call({ Object? view = freezed, - Object? isSelected = freezed, Object? isEditing = freezed, - Object? action = freezed, Object? successOrFailure = freezed, }) { return _then(_ViewState( @@ -569,18 +782,10 @@ class __$ViewStateCopyWithImpl<$Res> extends _$ViewStateCopyWithImpl<$Res> ? _value.view : view // ignore: cast_nullable_to_non_nullable as View, - isSelected: isSelected == freezed - ? _value.isSelected - : isSelected // ignore: cast_nullable_to_non_nullable - as bool, isEditing: isEditing == freezed ? _value.isEditing : isEditing // ignore: cast_nullable_to_non_nullable as bool, - action: action == freezed - ? _value.action - : action // ignore: cast_nullable_to_non_nullable - as Option, successOrFailure: successOrFailure == freezed ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable @@ -594,25 +799,19 @@ class __$ViewStateCopyWithImpl<$Res> extends _$ViewStateCopyWithImpl<$Res> class _$_ViewState implements _ViewState { const _$_ViewState( {required this.view, - required this.isSelected, required this.isEditing, - required this.action, required this.successOrFailure}); @override final View view; @override - final bool isSelected; - @override final bool isEditing; @override - final Option action; - @override final Either successOrFailure; @override String toString() { - return 'ViewState(view: $view, isSelected: $isSelected, isEditing: $isEditing, action: $action, successOrFailure: $successOrFailure)'; + return 'ViewState(view: $view, isEditing: $isEditing, successOrFailure: $successOrFailure)'; } @override @@ -621,14 +820,9 @@ class _$_ViewState implements _ViewState { (other is _ViewState && (identical(other.view, view) || const DeepCollectionEquality().equals(other.view, view)) && - (identical(other.isSelected, isSelected) || - const DeepCollectionEquality() - .equals(other.isSelected, isSelected)) && (identical(other.isEditing, isEditing) || const DeepCollectionEquality() .equals(other.isEditing, isEditing)) && - (identical(other.action, action) || - const DeepCollectionEquality().equals(other.action, action)) && (identical(other.successOrFailure, successOrFailure) || const DeepCollectionEquality() .equals(other.successOrFailure, successOrFailure))); @@ -638,9 +832,7 @@ class _$_ViewState implements _ViewState { int get hashCode => runtimeType.hashCode ^ const DeepCollectionEquality().hash(view) ^ - const DeepCollectionEquality().hash(isSelected) ^ const DeepCollectionEquality().hash(isEditing) ^ - const DeepCollectionEquality().hash(action) ^ const DeepCollectionEquality().hash(successOrFailure); @JsonKey(ignore: true) @@ -652,20 +844,14 @@ class _$_ViewState implements _ViewState { abstract class _ViewState implements ViewState { const factory _ViewState( {required View view, - required bool isSelected, required bool isEditing, - required Option action, required Either successOrFailure}) = _$_ViewState; @override View get view => throw _privateConstructorUsedError; @override - bool get isSelected => throw _privateConstructorUsedError; - @override bool get isEditing => throw _privateConstructorUsedError; @override - Option get action => throw _privateConstructorUsedError; - @override Either get successOrFailure => throw _privateConstructorUsedError; @override diff --git a/app_flowy/lib/workspace/domain/i_app.dart b/app_flowy/lib/workspace/domain/i_app.dart index 677cee657f..d9f092d959 100644 --- a/app_flowy/lib/workspace/domain/i_app.dart +++ b/app_flowy/lib/workspace/domain/i_app.dart @@ -13,7 +13,10 @@ abstract class IApp { } abstract class IAppListenr { - void start({AppCreateViewCallback? addViewCallback, AppUpdatedCallback? updatedCallback}); + void start( + {AppCreateViewCallback? addViewCallback, + AppDeleteViewCallback? deleteViewCallback, + AppUpdatedCallback? updatedCallback}); Future stop(); } diff --git a/app_flowy/lib/workspace/domain/i_view.dart b/app_flowy/lib/workspace/domain/i_view.dart index e43eb528c7..8d128bd2dd 100644 --- a/app_flowy/lib/workspace/domain/i_view.dart +++ b/app_flowy/lib/workspace/domain/i_view.dart @@ -9,7 +9,7 @@ abstract class IView { Future> pushIntoTrash(); - Future> rename(String newName); + Future> rename(String newName); } abstract class IViewListener { diff --git a/app_flowy/lib/workspace/infrastructure/deps_resolver.dart b/app_flowy/lib/workspace/infrastructure/deps_resolver.dart index 5c39b9f103..9466c89f21 100644 --- a/app_flowy/lib/workspace/infrastructure/deps_resolver.dart +++ b/app_flowy/lib/workspace/infrastructure/deps_resolver.dart @@ -67,7 +67,12 @@ class HomeDepsResolver { getIt.registerFactoryParam( (appId, _) => AppListenBloc(getIt(param1: appId))); - getIt.registerFactoryParam((view, _) => ViewBloc(iViewImpl: getIt(param1: view))); + getIt.registerFactoryParam( + (view, _) => ViewBloc( + iViewImpl: getIt(param1: view), + listener: getIt(param1: view), + ), + ); getIt.registerFactoryParam((docId, _) => DocBloc(iDocImpl: getIt(param1: docId))); diff --git a/app_flowy/lib/workspace/infrastructure/i_app_impl.dart b/app_flowy/lib/workspace/infrastructure/i_app_impl.dart index 31ee833882..0698fd7ae7 100644 --- a/app_flowy/lib/workspace/infrastructure/i_app_impl.dart +++ b/app_flowy/lib/workspace/infrastructure/i_app_impl.dart @@ -34,13 +34,16 @@ class IAppListenerhImpl extends IAppListenr { required this.repo, }); - @override - void start({AppCreateViewCallback? addViewCallback, AppUpdatedCallback? updatedCallback}) { - repo.startListen(createView: addViewCallback, update: updatedCallback); - } - @override Future stop() async { await repo.close(); } + + @override + void start( + {AppCreateViewCallback? addViewCallback, + AppDeleteViewCallback? deleteViewCallback, + AppUpdatedCallback? updatedCallback}) { + repo.startListen(createView: addViewCallback, deleteView: deleteViewCallback, update: updatedCallback); + } } diff --git a/app_flowy/lib/workspace/infrastructure/i_view_impl.dart b/app_flowy/lib/workspace/infrastructure/i_view_impl.dart index 393fc3541a..6d774be988 100644 --- a/app_flowy/lib/workspace/infrastructure/i_view_impl.dart +++ b/app_flowy/lib/workspace/infrastructure/i_view_impl.dart @@ -14,11 +14,16 @@ class IViewImpl extends IView { @override Future> pushIntoTrash() { - return repo.updateView(isTrash: true); + return repo.updateView(isTrash: true).then((result) { + return result.fold( + (_) => left(unit), + (error) => right(error), + ); + }); } @override - Future> rename(String newName) { + Future> rename(String newName) { return repo.updateView(name: newName); } } diff --git a/app_flowy/lib/workspace/infrastructure/repos/helper.dart b/app_flowy/lib/workspace/infrastructure/repos/helper.dart index b0dc3484ed..81f6aadc4c 100644 --- a/app_flowy/lib/workspace/infrastructure/repos/helper.dart +++ b/app_flowy/lib/workspace/infrastructure/repos/helper.dart @@ -34,12 +34,10 @@ import 'package:dartz/dartz.dart'; // } // } -typedef UserObservableCallback = void Function( - UserObservable, Either); +typedef UserObservableCallback = void Function(UserObservable, Either); class UserObservableParser extends ObservableParser { - UserObservableParser( - {required String id, required UserObservableCallback callback}) + UserObservableParser({required String id, required UserObservableCallback callback}) : super( id: id, callback: callback, @@ -48,13 +46,10 @@ class UserObservableParser extends ObservableParser { ); } -typedef WorkspaceObservableCallback = void Function( - WorkspaceObservable, Either); +typedef WorkspaceObservableCallback = void Function(WorkspaceObservable, Either); -class WorkspaceObservableParser - extends ObservableParser { - WorkspaceObservableParser( - {required String id, required WorkspaceObservableCallback callback}) +class WorkspaceObservableParser extends ObservableParser { + WorkspaceObservableParser({required String id, required WorkspaceObservableCallback callback}) : super( id: id, callback: callback, @@ -70,11 +65,7 @@ class ObservableParser { T? Function(int) tyParser; E Function(Uint8List) errorParser; - ObservableParser( - {required this.id, - required this.callback, - required this.errorParser, - required this.tyParser}); + ObservableParser({required this.id, required this.callback, required this.errorParser, required this.tyParser}); void parse(ObservableSubject subject) { if (subject.id != id) { return; diff --git a/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart b/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart index 8aab2cbb01..c21cf193d9 100644 --- a/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart +++ b/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart @@ -26,7 +26,7 @@ class ViewRepository { return WorkspaceEventReadView(request).send(); } - Future> updateView({String? name, String? desc, bool? isTrash}) { + Future> updateView({String? name, String? desc, bool? isTrash}) { final request = UpdateViewRequest.create()..viewId = view.id; if (name != null) { diff --git a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart index 8c6c688e55..9d436c141a 100644 --- a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart +++ b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart @@ -9,7 +9,6 @@ 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_infra_ui/widget/spacing.dart'; -import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -22,50 +21,43 @@ import 'package:app_flowy/workspace/presentation/widgets/menu/widget/app/menu_ap // ignore: must_be_immutable class ViewSectionItem extends StatelessWidget { - final ViewBloc bloc; + final bool isSelected; + final View view; final void Function(View) onSelected; ViewSectionItem({ Key? key, - required View view, - required bool isSelected, + required this.view, + required this.isSelected, required this.onSelected, - }) : bloc = getIt(param1: view), - super(key: ValueKey(view.id)) { - bloc.add(ViewEvent.setIsSelected(isSelected)); - } + }) : super(key: ValueKey('$view.id/$isSelected')); @override Widget build(BuildContext context) { final theme = context.watch(); - - return BlocProvider.value( - value: bloc, - child: BlocListener( - listenWhen: (p, c) => p.action != c.action, - listener: (context, state) { - state.action.fold(() => null, (action) { - Log.info('$action'); - }); + return MultiBlocProvider( + providers: [ + BlocProvider(create: (ctx) => getIt(param1: view)..add(const ViewEvent.initial())), + ], + child: BlocBuilder( + builder: (context, state) { + return InkWell( + onTap: () { + onSelected(context.read().state.view); + getIt().setStack(state.view.intoStackContext()); + }, + child: FlowyHover( + config: HoverDisplayConfig(hoverColor: theme.bg3), + builder: (context, onHover) => _render(context, onHover, state), + isOnSelected: () => state.isEditing || isSelected, + ), + ); }, - child: BlocBuilder( - builder: (context, state) { - return InkWell( - onTap: () => onSelected(context.read().state.view), - child: FlowyHover( - config: HoverDisplayConfig(hoverColor: theme.bg3), - builder: (context, onHover) => _render(context, onHover), - isOnSelected: () => state.isEditing || state.isSelected, - ), - ); - }, - ), ), ); } - Widget _render(BuildContext context, bool onHover) { - final state = context.read().state; + Widget _render(BuildContext context, bool onHover, ViewState state) { List children = [ SizedBox(width: 16, height: 16, child: state.view.thumbnail()), const HSpace(6), @@ -75,13 +67,10 @@ class ViewSectionItem extends StatelessWidget { if (onHover || state.isEditing) { children.add(const Spacer()); children.add(ViewDisclosureButton( - onTap: () { - context.read().add(const ViewEvent.setIsEditing(true)); - getIt().setStack(state.view.intoStackContext()); - }, + onTap: () => context.read().add(const ViewEvent.setIsEditing(true)), onSelected: (action) { context.read().add(const ViewEvent.setIsEditing(false)); - context.read().add(ViewEvent.setAction(action)); + _handleAction(context, action); }, )); } @@ -94,6 +83,20 @@ class ViewSectionItem extends StatelessWidget { ), ); } + + void _handleAction(BuildContext context, dartz.Option action) { + action.foldRight({}, (action, previous) { + switch (action) { + case ViewAction.rename: + + // TODO: Handle this case. + break; + case ViewAction.delete: + context.read().add(const ViewEvent.delete()); + break; + } + }); + } } // [[Widget: LifeCycle]] diff --git a/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart b/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart index a5144e565e..6fc9e9f198 100644 --- a/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart +++ b/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart @@ -207,14 +207,14 @@ class WorkspaceEventUpdateView { UpdateViewRequest request; WorkspaceEventUpdateView(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.UpdateView.toString() ..payload = requestToBytes(this.request); return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( - (bytes) => left(unit), + (okBytes) => left(View.fromBuffer(okBytes)), (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), )); } diff --git a/rust-lib/flowy-dart-notify/src/lib.rs b/rust-lib/flowy-dart-notify/src/lib.rs index cd471519d4..588b3ccce2 100644 --- a/rust-lib/flowy-dart-notify/src/lib.rs +++ b/rust-lib/flowy-dart-notify/src/lib.rs @@ -72,7 +72,6 @@ impl DartNotifyBuilder { error, }; - log::debug!("Notify {}", subject); match DartStreamSender::post(subject) { Ok(_) => {}, Err(error) => log::error!("Send observable subject failed: {}", error), diff --git a/rust-lib/flowy-workspace/src/event.rs b/rust-lib/flowy-workspace/src/event.rs index 3a9d5a6b76..b71b5c9993 100644 --- a/rust-lib/flowy-workspace/src/event.rs +++ b/rust-lib/flowy-workspace/src/event.rs @@ -40,7 +40,7 @@ pub enum WorkspaceEvent { #[event(input = "QueryViewRequest", output = "View")] ReadView = 202, - #[event(input = "UpdateViewRequest")] + #[event(input = "UpdateViewRequest", output = "View")] UpdateView = 203, #[event(input = "DeleteViewRequest")] diff --git a/rust-lib/flowy-workspace/src/services/view_controller.rs b/rust-lib/flowy-workspace/src/services/view_controller.rs index 0c6703e332..8540486144 100644 --- a/rust-lib/flowy-workspace/src/services/view_controller.rs +++ b/rust-lib/flowy-workspace/src/services/view_controller.rs @@ -58,7 +58,7 @@ impl ViewController { let _ = self.save_view(view.clone(), conn)?; self.document.create(CreateDocParams::new(&view.id, params.data))?; - let repeated_view = self.read_local_views_belong_to(&view.belong_to_id, conn)?; + let repeated_view = self.sql.read_views_belong_to(&view.belong_to_id, Some(false), conn)?; dart_notify(&view.belong_to_id, WorkspaceObservable::AppCreateView) .payload(repeated_view) .send(); @@ -96,7 +96,10 @@ impl ViewController { let view_table = self.sql.delete_view(¶ms.view_id, conn)?; let _ = self.document.delete(params.into())?; - let repeated_view = self.read_local_views_belong_to(&view_table.belong_to_id, conn)?; + let repeated_view = self + .sql + .read_views_belong_to(&view_table.belong_to_id, Some(false), conn)?; + dart_notify(&view_table.belong_to_id, WorkspaceObservable::AppDeleteView) .payload(repeated_view) .send(); @@ -111,26 +114,45 @@ impl ViewController { pub(crate) async fn read_views_belong_to(&self, belong_to_id: &str) -> Result { // TODO: read from server let conn = self.database.db_connection()?; - let repeated_view = self.read_local_views_belong_to(belong_to_id, &*conn)?; + let repeated_view = self.sql.read_views_belong_to(belong_to_id, Some(false), &*conn)?; Ok(repeated_view) } - pub(crate) async fn update_view(&self, params: UpdateViewParams) -> Result<(), WorkspaceError> { + #[tracing::instrument(level = "debug", skip(self, params), fields(dart_notify) err)] + pub(crate) async fn update_view(&self, params: UpdateViewParams) -> Result { let conn = &*self.database.db_connection()?; let changeset = ViewTableChangeset::new(params.clone()); let view_id = changeset.id.clone(); - conn.immediate_transaction::<_, WorkspaceError, _>(|| { + let updated_view = conn.immediate_transaction::<_, WorkspaceError, _>(|| { let _ = self.sql.update_view(changeset, conn)?; let view: View = self.sql.read_view(&view_id, None, conn)?.into(); - dart_notify(&view_id, WorkspaceObservable::ViewUpdated) - .payload(view) - .send(); - Ok(()) + + if params.is_trash.is_some() { + let repeated_view = self.sql.read_views_belong_to(&view.belong_to_id, Some(false), conn)?; + tracing::Span::current().record( + "dart_notify", + &format!("{:?}: {}", WorkspaceObservable::AppDeleteView, &view.belong_to_id).as_str(), + ); + dart_notify(&view.belong_to_id, WorkspaceObservable::AppDeleteView) + .payload(repeated_view) + .send(); + } else { + tracing::Span::current().record( + "dart_notify", + &format!("{:?}: {}", WorkspaceObservable::ViewUpdated, &view_id).as_str(), + ); + + dart_notify(&view_id, WorkspaceObservable::ViewUpdated) + .payload(view.clone()) + .send(); + } + + Ok(view) })?; let _ = self.update_view_on_server(params); - Ok(()) + Ok(updated_view) } pub(crate) async fn apply_doc_delta(&self, params: DocDelta) -> Result { @@ -197,20 +219,4 @@ impl ViewController { }); Ok(()) } - - // belong_to_id will be the app_id or view_id. - fn read_local_views_belong_to( - &self, - belong_to_id: &str, - conn: &SqliteConnection, - ) -> Result { - let views = self - .sql - .read_views_belong_to(belong_to_id, conn)? - .into_iter() - .map(|view_table| view_table.into()) - .collect::>(); - - Ok(RepeatedView { items: views }) - } } diff --git a/rust-lib/flowy-workspace/src/sql_tables/view/view_sql.rs b/rust-lib/flowy-workspace/src/sql_tables/view/view_sql.rs index 17a0c813f6..41b7b14d57 100644 --- a/rust-lib/flowy-workspace/src/sql_tables/view/view_sql.rs +++ b/rust-lib/flowy-workspace/src/sql_tables/view/view_sql.rs @@ -1,4 +1,5 @@ use crate::{ + entities::view::{RepeatedView, View}, errors::WorkspaceError, sql_tables::view::{ViewTable, ViewTableChangeset}, }; @@ -37,16 +38,27 @@ impl ViewTableSql { Ok(view_table) } + // belong_to_id will be the app_id or view_id. pub(crate) fn read_views_belong_to( &self, belong_to_id: &str, + is_trash: Option, conn: &SqliteConnection, - ) -> Result, WorkspaceError> { - let view_tables = dsl::view_table + ) -> Result { + let mut filter = dsl::view_table .filter(view_table::belong_to_id.eq(belong_to_id)) - .load::(conn)?; + .into_boxed(); + if let Some(is_trash) = is_trash { + filter = filter.filter(view_table::is_trash.eq(is_trash)); + } + let view_tables = filter.load::(conn)?; - Ok(view_tables) + let views = view_tables + .into_iter() + .map(|view_table| view_table.into()) + .collect::>(); + + Ok(RepeatedView { items: views }) } pub(crate) fn update_view(