[flutter]: add delete and restore notification

This commit is contained in:
appflowy 2021-10-31 17:24:55 +08:00
parent 74c1e3fcc6
commit ded8eb5d1c
20 changed files with 453 additions and 76 deletions

View File

@ -20,7 +20,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
) async* { ) async* {
yield* event.map(initial: (e) async* { yield* event.map(initial: (e) async* {
listener.start( listener.start(
viewsChangeCallback: _handleViewsOrFail, viewsChangeCallback: _handleViewsChanged,
updatedCallback: (app) => add(AppEvent.appDidUpdate(app)), updatedCallback: (app) => add(AppEvent.appDidUpdate(app)),
); );
yield* _fetchViews(); yield* _fetchViews();
@ -37,11 +37,11 @@ class AppBloc extends Bloc<AppEvent, AppState> {
}, },
); );
}, didReceiveViews: (e) async* { }, didReceiveViews: (e) async* {
yield state.copyWith(views: e.views); yield* handleDidReceiveViews(e.views);
}, delete: (e) async* { }, delete: (e) async* {
final result = await appManager.delete(); final result = await appManager.delete();
yield result.fold( yield result.fold(
(l) => state.copyWith(successOrFailure: left(unit)), (unit) => state.copyWith(successOrFailure: left(unit)),
(error) => state.copyWith(successOrFailure: right(error)), (error) => state.copyWith(successOrFailure: right(error)),
); );
}, rename: (e) async* { }, rename: (e) async* {
@ -61,8 +61,8 @@ class AppBloc extends Bloc<AppEvent, AppState> {
return super.close(); return super.close();
} }
void _handleViewsOrFail(Either<List<View>, WorkspaceError> viewsOrFail) { void _handleViewsChanged(Either<List<View>, WorkspaceError> result) {
viewsOrFail.fold( result.fold(
(views) => add(AppEvent.didReceiveViews(views)), (views) => add(AppEvent.didReceiveViews(views)),
(error) { (error) {
Log.error(error); Log.error(error);
@ -70,6 +70,19 @@ class AppBloc extends Bloc<AppEvent, AppState> {
); );
} }
Stream<AppState> handleDidReceiveViews(List<View> views) async* {
final selectedView = state.selectedView;
AppState newState = state.copyWith(views: views);
if (selectedView != null) {
final index = views.indexWhere((element) => element.id == selectedView.id);
if (index != -1) {
newState = newState.copyWith(selectedView: null);
}
}
yield newState;
}
Stream<AppState> _fetchViews() async* { Stream<AppState> _fetchViews() async* {
final viewsOrFailed = await appManager.getViews(); final viewsOrFailed = await appManager.getViews();
yield viewsOrFailed.fold( yield viewsOrFailed.fold(

View File

@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'package:app_flowy/workspace/domain/i_view.dart';
import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter_quill/flutter_quill.dart';
import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_log/flowy_log.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
@ -12,24 +13,50 @@ part 'doc_bloc.freezed.dart';
class DocBloc extends Bloc<DocEvent, DocState> { class DocBloc extends Bloc<DocEvent, DocState> {
final IDoc docManager; final IDoc docManager;
final IViewListener listener;
late Document document; late Document document;
late StreamSubscription _subscription; late StreamSubscription _subscription;
DocBloc({required this.docManager}) : super(DocState.initial()); DocBloc({required this.docManager, required this.listener}) : super(DocState.initial());
@override @override
Stream<DocState> mapEventToState(DocEvent event) async* { Stream<DocState> mapEventToState(DocEvent event) async* {
yield* event.map(initial: _initial); yield* event.map(
initial: _initial,
deleted: (Deleted value) async* {
yield state.copyWith(isDeleted: true);
},
restore: (Restore value) async* {
yield state.copyWith(isDeleted: false);
},
);
} }
@override @override
Future<void> close() async { Future<void> close() async {
await listener.stop();
await _subscription.cancel(); await _subscription.cancel();
docManager.closeDoc(); docManager.closeDoc();
return super.close(); return super.close();
} }
Stream<DocState> _initial(Initial value) async* { Stream<DocState> _initial(Initial value) async* {
listener.deletedNotifier.addPublishListener((result) {
result.fold(
(view) => add(const DocEvent.deleted()),
(error) {},
);
});
listener.restoredNotifier.addPublishListener((result) {
result.fold(
(view) => add(const DocEvent.restore()),
(error) {},
);
});
listener.start();
final result = await docManager.readDoc(); final result = await docManager.readDoc();
yield result.fold( yield result.fold(
(doc) { (doc) {
@ -78,15 +105,21 @@ class DocBloc extends Bloc<DocEvent, DocState> {
@freezed @freezed
class DocEvent with _$DocEvent { class DocEvent with _$DocEvent {
const factory DocEvent.initial() = Initial; const factory DocEvent.initial() = Initial;
const factory DocEvent.deleted() = Deleted;
const factory DocEvent.restore() = Restore;
} }
@freezed @freezed
class DocState with _$DocState { class DocState with _$DocState {
const factory DocState({ const factory DocState({
required DocLoadState loadState, required DocLoadState loadState,
required bool isDeleted,
}) = _DocState; }) = _DocState;
factory DocState.initial() => const DocState(loadState: _Loading()); factory DocState.initial() => const DocState(
loadState: _Loading(),
isDeleted: false,
);
} }
@freezed @freezed

View File

@ -19,6 +19,14 @@ class _$DocEventTearOff {
Initial initial() { Initial initial() {
return const Initial(); return const Initial();
} }
Deleted deleted() {
return const Deleted();
}
Restore restore() {
return const Restore();
}
} }
/// @nodoc /// @nodoc
@ -29,22 +37,30 @@ mixin _$DocEvent {
@optionalTypeArgs @optionalTypeArgs
TResult when<TResult extends Object?>({ TResult when<TResult extends Object?>({
required TResult Function() initial, required TResult Function() initial,
required TResult Function() deleted,
required TResult Function() restore,
}) => }) =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({ TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial, TResult Function()? initial,
TResult Function()? deleted,
TResult Function()? restore,
required TResult orElse(), required TResult orElse(),
}) => }) =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
TResult map<TResult extends Object?>({ TResult map<TResult extends Object?>({
required TResult Function(Initial value) initial, required TResult Function(Initial value) initial,
required TResult Function(Deleted value) deleted,
required TResult Function(Restore value) restore,
}) => }) =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
TResult maybeMap<TResult extends Object?>({ TResult maybeMap<TResult extends Object?>({
TResult Function(Initial value)? initial, TResult Function(Initial value)? initial,
TResult Function(Deleted value)? deleted,
TResult Function(Restore value)? restore,
required TResult orElse(), required TResult orElse(),
}) => }) =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@ -103,6 +119,8 @@ class _$Initial implements Initial {
@optionalTypeArgs @optionalTypeArgs
TResult when<TResult extends Object?>({ TResult when<TResult extends Object?>({
required TResult Function() initial, required TResult Function() initial,
required TResult Function() deleted,
required TResult Function() restore,
}) { }) {
return initial(); return initial();
} }
@ -111,6 +129,8 @@ class _$Initial implements Initial {
@optionalTypeArgs @optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({ TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial, TResult Function()? initial,
TResult Function()? deleted,
TResult Function()? restore,
required TResult orElse(), required TResult orElse(),
}) { }) {
if (initial != null) { if (initial != null) {
@ -123,6 +143,8 @@ class _$Initial implements Initial {
@optionalTypeArgs @optionalTypeArgs
TResult map<TResult extends Object?>({ TResult map<TResult extends Object?>({
required TResult Function(Initial value) initial, required TResult Function(Initial value) initial,
required TResult Function(Deleted value) deleted,
required TResult Function(Restore value) restore,
}) { }) {
return initial(this); return initial(this);
} }
@ -131,6 +153,8 @@ class _$Initial implements Initial {
@optionalTypeArgs @optionalTypeArgs
TResult maybeMap<TResult extends Object?>({ TResult maybeMap<TResult extends Object?>({
TResult Function(Initial value)? initial, TResult Function(Initial value)? initial,
TResult Function(Deleted value)? deleted,
TResult Function(Restore value)? restore,
required TResult orElse(), required TResult orElse(),
}) { }) {
if (initial != null) { if (initial != null) {
@ -144,13 +168,188 @@ abstract class Initial implements DocEvent {
const factory Initial() = _$Initial; const factory Initial() = _$Initial;
} }
/// @nodoc
abstract class $DeletedCopyWith<$Res> {
factory $DeletedCopyWith(Deleted value, $Res Function(Deleted) then) =
_$DeletedCopyWithImpl<$Res>;
}
/// @nodoc
class _$DeletedCopyWithImpl<$Res> extends _$DocEventCopyWithImpl<$Res>
implements $DeletedCopyWith<$Res> {
_$DeletedCopyWithImpl(Deleted _value, $Res Function(Deleted) _then)
: super(_value, (v) => _then(v as Deleted));
@override
Deleted get _value => super._value as Deleted;
}
/// @nodoc
class _$Deleted implements Deleted {
const _$Deleted();
@override
String toString() {
return 'DocEvent.deleted()';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) || (other is Deleted);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() deleted,
required TResult Function() restore,
}) {
return deleted();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? deleted,
TResult Function()? restore,
required TResult orElse(),
}) {
if (deleted != null) {
return deleted();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Initial value) initial,
required TResult Function(Deleted value) deleted,
required TResult Function(Restore value) restore,
}) {
return deleted(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Initial value)? initial,
TResult Function(Deleted value)? deleted,
TResult Function(Restore value)? restore,
required TResult orElse(),
}) {
if (deleted != null) {
return deleted(this);
}
return orElse();
}
}
abstract class Deleted implements DocEvent {
const factory Deleted() = _$Deleted;
}
/// @nodoc
abstract class $RestoreCopyWith<$Res> {
factory $RestoreCopyWith(Restore value, $Res Function(Restore) then) =
_$RestoreCopyWithImpl<$Res>;
}
/// @nodoc
class _$RestoreCopyWithImpl<$Res> extends _$DocEventCopyWithImpl<$Res>
implements $RestoreCopyWith<$Res> {
_$RestoreCopyWithImpl(Restore _value, $Res Function(Restore) _then)
: super(_value, (v) => _then(v as Restore));
@override
Restore get _value => super._value as Restore;
}
/// @nodoc
class _$Restore implements Restore {
const _$Restore();
@override
String toString() {
return 'DocEvent.restore()';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) || (other is Restore);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() deleted,
required TResult Function() restore,
}) {
return restore();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? deleted,
TResult Function()? restore,
required TResult orElse(),
}) {
if (restore != null) {
return restore();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Initial value) initial,
required TResult Function(Deleted value) deleted,
required TResult Function(Restore value) restore,
}) {
return restore(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Initial value)? initial,
TResult Function(Deleted value)? deleted,
TResult Function(Restore value)? restore,
required TResult orElse(),
}) {
if (restore != null) {
return restore(this);
}
return orElse();
}
}
abstract class Restore implements DocEvent {
const factory Restore() = _$Restore;
}
/// @nodoc /// @nodoc
class _$DocStateTearOff { class _$DocStateTearOff {
const _$DocStateTearOff(); const _$DocStateTearOff();
_DocState call({required DocLoadState loadState}) { _DocState call({required DocLoadState loadState, required bool isDeleted}) {
return _DocState( return _DocState(
loadState: loadState, loadState: loadState,
isDeleted: isDeleted,
); );
} }
} }
@ -161,6 +360,7 @@ const $DocState = _$DocStateTearOff();
/// @nodoc /// @nodoc
mixin _$DocState { mixin _$DocState {
DocLoadState get loadState => throw _privateConstructorUsedError; DocLoadState get loadState => throw _privateConstructorUsedError;
bool get isDeleted => throw _privateConstructorUsedError;
@JsonKey(ignore: true) @JsonKey(ignore: true)
$DocStateCopyWith<DocState> get copyWith => $DocStateCopyWith<DocState> get copyWith =>
@ -171,7 +371,7 @@ mixin _$DocState {
abstract class $DocStateCopyWith<$Res> { abstract class $DocStateCopyWith<$Res> {
factory $DocStateCopyWith(DocState value, $Res Function(DocState) then) = factory $DocStateCopyWith(DocState value, $Res Function(DocState) then) =
_$DocStateCopyWithImpl<$Res>; _$DocStateCopyWithImpl<$Res>;
$Res call({DocLoadState loadState}); $Res call({DocLoadState loadState, bool isDeleted});
$DocLoadStateCopyWith<$Res> get loadState; $DocLoadStateCopyWith<$Res> get loadState;
} }
@ -187,12 +387,17 @@ class _$DocStateCopyWithImpl<$Res> implements $DocStateCopyWith<$Res> {
@override @override
$Res call({ $Res call({
Object? loadState = freezed, Object? loadState = freezed,
Object? isDeleted = freezed,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
loadState: loadState == freezed loadState: loadState == freezed
? _value.loadState ? _value.loadState
: loadState // ignore: cast_nullable_to_non_nullable : loadState // ignore: cast_nullable_to_non_nullable
as DocLoadState, as DocLoadState,
isDeleted: isDeleted == freezed
? _value.isDeleted
: isDeleted // ignore: cast_nullable_to_non_nullable
as bool,
)); ));
} }
@ -209,7 +414,7 @@ abstract class _$DocStateCopyWith<$Res> implements $DocStateCopyWith<$Res> {
factory _$DocStateCopyWith(_DocState value, $Res Function(_DocState) then) = factory _$DocStateCopyWith(_DocState value, $Res Function(_DocState) then) =
__$DocStateCopyWithImpl<$Res>; __$DocStateCopyWithImpl<$Res>;
@override @override
$Res call({DocLoadState loadState}); $Res call({DocLoadState loadState, bool isDeleted});
@override @override
$DocLoadStateCopyWith<$Res> get loadState; $DocLoadStateCopyWith<$Res> get loadState;
@ -227,12 +432,17 @@ class __$DocStateCopyWithImpl<$Res> extends _$DocStateCopyWithImpl<$Res>
@override @override
$Res call({ $Res call({
Object? loadState = freezed, Object? loadState = freezed,
Object? isDeleted = freezed,
}) { }) {
return _then(_DocState( return _then(_DocState(
loadState: loadState == freezed loadState: loadState == freezed
? _value.loadState ? _value.loadState
: loadState // ignore: cast_nullable_to_non_nullable : loadState // ignore: cast_nullable_to_non_nullable
as DocLoadState, as DocLoadState,
isDeleted: isDeleted == freezed
? _value.isDeleted
: isDeleted // ignore: cast_nullable_to_non_nullable
as bool,
)); ));
} }
} }
@ -240,14 +450,16 @@ class __$DocStateCopyWithImpl<$Res> extends _$DocStateCopyWithImpl<$Res>
/// @nodoc /// @nodoc
class _$_DocState implements _DocState { class _$_DocState implements _DocState {
const _$_DocState({required this.loadState}); const _$_DocState({required this.loadState, required this.isDeleted});
@override @override
final DocLoadState loadState; final DocLoadState loadState;
@override
final bool isDeleted;
@override @override
String toString() { String toString() {
return 'DocState(loadState: $loadState)'; return 'DocState(loadState: $loadState, isDeleted: $isDeleted)';
} }
@override @override
@ -256,12 +468,17 @@ class _$_DocState implements _DocState {
(other is _DocState && (other is _DocState &&
(identical(other.loadState, loadState) || (identical(other.loadState, loadState) ||
const DeepCollectionEquality() const DeepCollectionEquality()
.equals(other.loadState, loadState))); .equals(other.loadState, loadState)) &&
(identical(other.isDeleted, isDeleted) ||
const DeepCollectionEquality()
.equals(other.isDeleted, isDeleted)));
} }
@override @override
int get hashCode => int get hashCode =>
runtimeType.hashCode ^ const DeepCollectionEquality().hash(loadState); runtimeType.hashCode ^
const DeepCollectionEquality().hash(loadState) ^
const DeepCollectionEquality().hash(isDeleted);
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
@ -270,11 +487,14 @@ class _$_DocState implements _DocState {
} }
abstract class _DocState implements DocState { abstract class _DocState implements DocState {
const factory _DocState({required DocLoadState loadState}) = _$_DocState; const factory _DocState(
{required DocLoadState loadState, required bool isDeleted}) = _$_DocState;
@override @override
DocLoadState get loadState => throw _privateConstructorUsedError; DocLoadState get loadState => throw _privateConstructorUsedError;
@override @override
bool get isDeleted => throw _privateConstructorUsedError;
@override
@JsonKey(ignore: true) @JsonKey(ignore: true)
_$DocStateCopyWith<_DocState> get copyWith => _$DocStateCopyWith<_DocState> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;

View File

@ -20,7 +20,10 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
Stream<ViewState> mapEventToState(ViewEvent event) async* { Stream<ViewState> mapEventToState(ViewEvent event) async* {
yield* event.map( yield* event.map(
initial: (e) async* { initial: (e) async* {
listener.start(updatedCallback: (result) => add(ViewEvent.viewDidUpdate(result))); listener.updatedNotifier.addPublishListener((result) {
add(ViewEvent.viewDidUpdate(result));
});
listener.start();
yield state; yield state;
}, },
setIsEditing: (e) async* { setIsEditing: (e) async* {

View File

@ -1,9 +1,14 @@
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:flowy_infra/notifier.dart';
typedef ViewUpdatedCallback = void Function(Either<View, WorkspaceError>); typedef ViewUpdatedCallback = void Function(Either<View, WorkspaceError>);
typedef DeleteNotifierValue = Either<View, WorkspaceError>;
typedef UpdateNotifierValue = Either<View, WorkspaceError>;
typedef RestoreNotifierValue = Either<View, WorkspaceError>;
abstract class IView { abstract class IView {
View get view; View get view;
@ -15,7 +20,13 @@ abstract class IView {
} }
abstract class IViewListener { abstract class IViewListener {
void start({ViewUpdatedCallback? updatedCallback}); void start();
PublishNotifier<UpdateNotifierValue> get updatedNotifier;
PublishNotifier<DeleteNotifierValue> get deletedNotifier;
PublishNotifier<RestoreNotifierValue> get restoredNotifier;
Future<void> stop(); Future<void> stop();
} }

View File

@ -87,7 +87,12 @@ class HomeDepsResolver {
); );
// Doc // Doc
getIt.registerFactoryParam<DocBloc, String, void>((docId, _) => DocBloc(docManager: getIt<IDoc>(param1: docId))); getIt.registerFactoryParam<DocBloc, View, void>(
(view, _) => DocBloc(
docManager: getIt<IDoc>(param1: view.id),
listener: getIt<IViewListener>(param1: view),
),
);
// trash // trash
getIt.registerLazySingleton<TrashRepo>(() => TrashRepo()); getIt.registerLazySingleton<TrashRepo>(() => TrashRepo());

View File

@ -1,5 +1,6 @@
import 'package:app_flowy/workspace/domain/i_view.dart'; import 'package:app_flowy/workspace/domain/i_view.dart';
import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart'; import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart';
import 'package:flowy_infra/notifier.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
@ -40,12 +41,21 @@ class IViewListenerImpl extends IViewListener {
}); });
@override @override
void start({ViewUpdatedCallback? updatedCallback}) { void start() {
repo.startWatching(update: updatedCallback); repo.start();
} }
@override @override
Future<void> stop() async { Future<void> stop() async {
await repo.close(); await repo.close();
} }
@override
PublishNotifier<DeleteNotifierValue> get deletedNotifier => repo.deletedNotifier;
@override
PublishNotifier<UpdateNotifierValue> get updatedNotifier => repo.updatedNotifier;
@override
PublishNotifier<RestoreNotifierValue> get restoredNotifier => repo.updatedNotifier;
} }

View File

@ -11,6 +11,7 @@ import 'package:flowy_sdk/protobuf/flowy-workspace/view_update.pb.dart';
import 'package:flowy_sdk/rust_stream.dart'; import 'package:flowy_sdk/rust_stream.dart';
import 'package:app_flowy/workspace/domain/i_view.dart'; import 'package:app_flowy/workspace/domain/i_view.dart';
import 'package:flowy_infra/notifier.dart';
import 'helper.dart'; import 'helper.dart';
@ -52,7 +53,9 @@ class ViewRepository {
class ViewListenerRepository { class ViewListenerRepository {
StreamSubscription<SubscribeObject>? _subscription; StreamSubscription<SubscribeObject>? _subscription;
ViewUpdatedCallback? _update; PublishNotifier<UpdateNotifierValue> updatedNotifier = PublishNotifier<UpdateNotifierValue>();
PublishNotifier<DeleteNotifierValue> deletedNotifier = PublishNotifier<DeleteNotifierValue>();
PublishNotifier<RestoreNotifierValue> restoredNotifier = PublishNotifier<RestoreNotifierValue>();
late WorkspaceNotificationParser _parser; late WorkspaceNotificationParser _parser;
View view; View view;
@ -60,10 +63,7 @@ class ViewListenerRepository {
required this.view, required this.view,
}); });
void startWatching({ void start() {
ViewUpdatedCallback? update,
}) {
_update = update;
_parser = WorkspaceNotificationParser( _parser = WorkspaceNotificationParser(
id: view.id, id: view.id,
callback: (ty, result) { callback: (ty, result) {
@ -77,15 +77,22 @@ class ViewListenerRepository {
void _handleObservableType(WorkspaceNotification ty, Either<Uint8List, WorkspaceError> result) { void _handleObservableType(WorkspaceNotification ty, Either<Uint8List, WorkspaceError> result) {
switch (ty) { switch (ty) {
case WorkspaceNotification.ViewUpdated: case WorkspaceNotification.ViewUpdated:
if (_update != null) { result.fold(
result.fold( (payload) => updatedNotifier.value = left(View.fromBuffer(payload)),
(payload) { (error) => updatedNotifier.value = right(error),
final view = View.fromBuffer(payload); );
_update!(left(view)); break;
}, case WorkspaceNotification.ViewDeleted:
(error) => _update!(right(error)), result.fold(
); (payload) => deletedNotifier.value = left(View.fromBuffer(payload)),
} (error) => deletedNotifier.value = right(error),
);
break;
case WorkspaceNotification.ViewRestored:
result.fold(
(payload) => restoredNotifier.value = left(View.fromBuffer(payload)),
(error) => restoredNotifier.value = right(error),
);
break; break;
default: default:
break; break;

View File

@ -28,7 +28,7 @@ class _DocPageState extends State<DocPage> {
@override @override
void initState() { void initState() {
docBloc = getIt<DocBloc>(param1: super.widget.view.id)..add(const DocEvent.initial()); docBloc = getIt<DocBloc>(param1: super.widget.view)..add(const DocEvent.initial());
super.initState(); super.initState();
} }

View File

@ -15,7 +15,7 @@ class DocStackContext extends HomeStackContext {
DocStackContext({required View view, Key? key}) : _view = view { DocStackContext({required View view, Key? key}) : _view = view {
_listener = getIt<IViewListener>(param1: view); _listener = getIt<IViewListener>(param1: view);
_listener.start(updatedCallback: (result) { _listener.updatedNotifier.addPublishListener((result) {
result.fold( result.fold(
(newView) { (newView) {
_view = newView; _view = newView;
@ -24,6 +24,7 @@ class DocStackContext extends HomeStackContext {
(error) {}, (error) {},
); );
}); });
_listener.start();
} }
@override @override

View File

@ -68,7 +68,7 @@ class ViewSection extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// The ViewListNotifier will be updated after ViewListData changed passed by parent widget // The ViewSectionNotifier will be updated after AppDataNotifier changed passed by parent widget
return ChangeNotifierProxyProvider<AppDataNotifier, ViewSectionNotifier>( return ChangeNotifierProxyProvider<AppDataNotifier, ViewSectionNotifier>(
create: (_) { create: (_) {
final views = Provider.of<AppDataNotifier>(context, listen: false).views; final views = Provider.of<AppDataNotifier>(context, listen: false).views;

View File

@ -0,0 +1,20 @@
import 'package:flutter/material.dart';
class PublishNotifier<T> extends ChangeNotifier {
T? _value;
set value(T newValue) {
_value = newValue;
notifyListeners();
}
T? get currentValue => _value;
void addPublishListener(void Function(T) callback) {
super.addListener(() {
if (_value != null) {
callback(_value!);
}
});
}
}

View File

@ -19,6 +19,8 @@ class WorkspaceNotification extends $pb.ProtobufEnum {
static const WorkspaceNotification AppUpdated = WorkspaceNotification._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppUpdated'); static const WorkspaceNotification AppUpdated = WorkspaceNotification._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppUpdated');
static const WorkspaceNotification AppViewsChanged = WorkspaceNotification._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppViewsChanged'); static const WorkspaceNotification AppViewsChanged = WorkspaceNotification._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppViewsChanged');
static const WorkspaceNotification ViewUpdated = WorkspaceNotification._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewUpdated'); static const WorkspaceNotification ViewUpdated = WorkspaceNotification._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewUpdated');
static const WorkspaceNotification ViewDeleted = WorkspaceNotification._(32, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewDeleted');
static const WorkspaceNotification ViewRestored = WorkspaceNotification._(33, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewRestored');
static const WorkspaceNotification UserUnauthorized = WorkspaceNotification._(100, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserUnauthorized'); static const WorkspaceNotification UserUnauthorized = WorkspaceNotification._(100, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserUnauthorized');
static const WorkspaceNotification TrashUpdated = WorkspaceNotification._(1000, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TrashUpdated'); static const WorkspaceNotification TrashUpdated = WorkspaceNotification._(1000, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TrashUpdated');
@ -32,6 +34,8 @@ class WorkspaceNotification extends $pb.ProtobufEnum {
AppUpdated, AppUpdated,
AppViewsChanged, AppViewsChanged,
ViewUpdated, ViewUpdated,
ViewDeleted,
ViewRestored,
UserUnauthorized, UserUnauthorized,
TrashUpdated, TrashUpdated,
]; ];

View File

@ -21,10 +21,12 @@ const WorkspaceNotification$json = const {
const {'1': 'AppUpdated', '2': 21}, const {'1': 'AppUpdated', '2': 21},
const {'1': 'AppViewsChanged', '2': 24}, const {'1': 'AppViewsChanged', '2': 24},
const {'1': 'ViewUpdated', '2': 31}, const {'1': 'ViewUpdated', '2': 31},
const {'1': 'ViewDeleted', '2': 32},
const {'1': 'ViewRestored', '2': 33},
const {'1': 'UserUnauthorized', '2': 100}, const {'1': 'UserUnauthorized', '2': 100},
const {'1': 'TrashUpdated', '2': 1000}, const {'1': 'TrashUpdated', '2': 1000},
], ],
}; };
/// Descriptor for `WorkspaceNotification`. Decode as a `google.protobuf.EnumDescriptorProto`. /// Descriptor for `WorkspaceNotification`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List workspaceNotificationDescriptor = $convert.base64Decode('ChVXb3Jrc3BhY2VOb3RpZmljYXRpb24SCwoHVW5rbm93bhAAEhcKE1VzZXJDcmVhdGVXb3Jrc3BhY2UQChIXChNVc2VyRGVsZXRlV29ya3NwYWNlEAsSFAoQV29ya3NwYWNlVXBkYXRlZBAMEhgKFFdvcmtzcGFjZUxpc3RVcGRhdGVkEA0SGAoUV29ya3NwYWNlQXBwc0NoYW5nZWQQDhIOCgpBcHBVcGRhdGVkEBUSEwoPQXBwVmlld3NDaGFuZ2VkEBgSDwoLVmlld1VwZGF0ZWQQHxIUChBVc2VyVW5hdXRob3JpemVkEGQSEQoMVHJhc2hVcGRhdGVkEOgH'); final $typed_data.Uint8List workspaceNotificationDescriptor = $convert.base64Decode('ChVXb3Jrc3BhY2VOb3RpZmljYXRpb24SCwoHVW5rbm93bhAAEhcKE1VzZXJDcmVhdGVXb3Jrc3BhY2UQChIXChNVc2VyRGVsZXRlV29ya3NwYWNlEAsSFAoQV29ya3NwYWNlVXBkYXRlZBAMEhgKFFdvcmtzcGFjZUxpc3RVcGRhdGVkEA0SGAoUV29ya3NwYWNlQXBwc0NoYW5nZWQQDhIOCgpBcHBVcGRhdGVkEBUSEwoPQXBwVmlld3NDaGFuZ2VkEBgSDwoLVmlld1VwZGF0ZWQQHxIPCgtWaWV3RGVsZXRlZBAgEhAKDFZpZXdSZXN0b3JlZBAhEhQKEFVzZXJVbmF1dGhvcml6ZWQQZBIRCgxUcmFzaFVwZGF0ZWQQ6Ac=');

View File

@ -1025,5 +1025,5 @@ packages:
source: hosted source: hosted
version: "8.0.0" version: "8.0.0"
sdks: sdks:
dart: ">=2.14.0 <3.0.0" dart: ">=2.15.0-116.0.dev <3.0.0"
flutter: ">=2.5.0" flutter: ">=2.5.0"

View File

@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1 version: 1.0.0+1
environment: environment:
sdk: ">=2.12.0 <3.0.0" sdk: ">=2.15.0-116.0.dev <3.0.0"
# Dependencies specify other packages that your package needs in order to work. # Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions # To automatically upgrade your package dependencies to the latest versions

View File

@ -2,6 +2,8 @@ use flowy_dart_notify::DartNotifyBuilder;
use flowy_derive::ProtoBuf_Enum; use flowy_derive::ProtoBuf_Enum;
const OBSERVABLE_CATEGORY: &'static str = "Workspace"; const OBSERVABLE_CATEGORY: &'static str = "Workspace";
// Opti: Using the Rust macro to generate the serde code automatically that can
// be use directly in flutter
#[derive(ProtoBuf_Enum, Debug)] #[derive(ProtoBuf_Enum, Debug)]
pub(crate) enum WorkspaceNotification { pub(crate) enum WorkspaceNotification {
Unknown = 0, Unknown = 0,
@ -13,6 +15,8 @@ pub(crate) enum WorkspaceNotification {
AppUpdated = 21, AppUpdated = 21,
AppViewsChanged = 24, AppViewsChanged = 24,
ViewUpdated = 31, ViewUpdated = 31,
ViewDeleted = 32,
ViewRestored = 33,
UserUnauthorized = 100, UserUnauthorized = 100,
TrashUpdated = 1000, TrashUpdated = 1000,
} }

View File

@ -34,6 +34,8 @@ pub enum WorkspaceNotification {
AppUpdated = 21, AppUpdated = 21,
AppViewsChanged = 24, AppViewsChanged = 24,
ViewUpdated = 31, ViewUpdated = 31,
ViewDeleted = 32,
ViewRestored = 33,
UserUnauthorized = 100, UserUnauthorized = 100,
TrashUpdated = 1000, TrashUpdated = 1000,
} }
@ -54,6 +56,8 @@ impl ::protobuf::ProtobufEnum for WorkspaceNotification {
21 => ::std::option::Option::Some(WorkspaceNotification::AppUpdated), 21 => ::std::option::Option::Some(WorkspaceNotification::AppUpdated),
24 => ::std::option::Option::Some(WorkspaceNotification::AppViewsChanged), 24 => ::std::option::Option::Some(WorkspaceNotification::AppViewsChanged),
31 => ::std::option::Option::Some(WorkspaceNotification::ViewUpdated), 31 => ::std::option::Option::Some(WorkspaceNotification::ViewUpdated),
32 => ::std::option::Option::Some(WorkspaceNotification::ViewDeleted),
33 => ::std::option::Option::Some(WorkspaceNotification::ViewRestored),
100 => ::std::option::Option::Some(WorkspaceNotification::UserUnauthorized), 100 => ::std::option::Option::Some(WorkspaceNotification::UserUnauthorized),
1000 => ::std::option::Option::Some(WorkspaceNotification::TrashUpdated), 1000 => ::std::option::Option::Some(WorkspaceNotification::TrashUpdated),
_ => ::std::option::Option::None _ => ::std::option::Option::None
@ -71,6 +75,8 @@ impl ::protobuf::ProtobufEnum for WorkspaceNotification {
WorkspaceNotification::AppUpdated, WorkspaceNotification::AppUpdated,
WorkspaceNotification::AppViewsChanged, WorkspaceNotification::AppViewsChanged,
WorkspaceNotification::ViewUpdated, WorkspaceNotification::ViewUpdated,
WorkspaceNotification::ViewDeleted,
WorkspaceNotification::ViewRestored,
WorkspaceNotification::UserUnauthorized, WorkspaceNotification::UserUnauthorized,
WorkspaceNotification::TrashUpdated, WorkspaceNotification::TrashUpdated,
]; ];
@ -101,37 +107,42 @@ impl ::protobuf::reflect::ProtobufValue for WorkspaceNotification {
} }
static file_descriptor_proto_data: &'static [u8] = b"\ static file_descriptor_proto_data: &'static [u8] = b"\
\n\x10observable.proto*\xff\x01\n\x15WorkspaceNotification\x12\x0b\n\x07\ \n\x10observable.proto*\xa2\x02\n\x15WorkspaceNotification\x12\x0b\n\x07\
Unknown\x10\0\x12\x17\n\x13UserCreateWorkspace\x10\n\x12\x17\n\x13UserDe\ Unknown\x10\0\x12\x17\n\x13UserCreateWorkspace\x10\n\x12\x17\n\x13UserDe\
leteWorkspace\x10\x0b\x12\x14\n\x10WorkspaceUpdated\x10\x0c\x12\x18\n\ leteWorkspace\x10\x0b\x12\x14\n\x10WorkspaceUpdated\x10\x0c\x12\x18\n\
\x14WorkspaceListUpdated\x10\r\x12\x18\n\x14WorkspaceAppsChanged\x10\x0e\ \x14WorkspaceListUpdated\x10\r\x12\x18\n\x14WorkspaceAppsChanged\x10\x0e\
\x12\x0e\n\nAppUpdated\x10\x15\x12\x13\n\x0fAppViewsChanged\x10\x18\x12\ \x12\x0e\n\nAppUpdated\x10\x15\x12\x13\n\x0fAppViewsChanged\x10\x18\x12\
\x0f\n\x0bViewUpdated\x10\x1f\x12\x14\n\x10UserUnauthorized\x10d\x12\x11\ \x0f\n\x0bViewUpdated\x10\x1f\x12\x0f\n\x0bViewDeleted\x10\x20\x12\x10\n\
\n\x0cTrashUpdated\x10\xe8\x07J\xed\x03\n\x06\x12\x04\0\0\x0e\x01\n\x08\ \x0cViewRestored\x10!\x12\x14\n\x10UserUnauthorized\x10d\x12\x11\n\x0cTr\
\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x05\0\x12\x04\x02\0\x0e\x01\n\n\n\ ashUpdated\x10\xe8\x07J\xbf\x04\n\x06\x12\x04\0\0\x10\x01\n\x08\n\x01\
\x03\x05\0\x01\x12\x03\x02\x05\x1a\n\x0b\n\x04\x05\0\x02\0\x12\x03\x03\ \x0c\x12\x03\0\0\x12\n\n\n\x02\x05\0\x12\x04\x02\0\x10\x01\n\n\n\x03\x05\
\x04\x10\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x03\x04\x0b\n\x0c\n\x05\x05\ \0\x01\x12\x03\x02\x05\x1a\n\x0b\n\x04\x05\0\x02\0\x12\x03\x03\x04\x10\n\
\0\x02\0\x02\x12\x03\x03\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x04\ \x0c\n\x05\x05\0\x02\0\x01\x12\x03\x03\x04\x0b\n\x0c\n\x05\x05\0\x02\0\
\x04\x1d\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x04\x04\x17\n\x0c\n\x05\ \x02\x12\x03\x03\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x04\x04\x1d\n\
\x05\0\x02\x01\x02\x12\x03\x04\x1a\x1c\n\x0b\n\x04\x05\0\x02\x02\x12\x03\ \x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x04\x04\x17\n\x0c\n\x05\x05\0\x02\
\x05\x04\x1d\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\x05\x04\x17\n\x0c\n\ \x01\x02\x12\x03\x04\x1a\x1c\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x05\x04\
\x05\x05\0\x02\x02\x02\x12\x03\x05\x1a\x1c\n\x0b\n\x04\x05\0\x02\x03\x12\ \x1d\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\x05\x04\x17\n\x0c\n\x05\x05\0\
\x03\x06\x04\x1a\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\x06\x04\x14\n\x0c\ \x02\x02\x02\x12\x03\x05\x1a\x1c\n\x0b\n\x04\x05\0\x02\x03\x12\x03\x06\
\n\x05\x05\0\x02\x03\x02\x12\x03\x06\x17\x19\n\x0b\n\x04\x05\0\x02\x04\ \x04\x1a\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\x06\x04\x14\n\x0c\n\x05\
\x12\x03\x07\x04\x1e\n\x0c\n\x05\x05\0\x02\x04\x01\x12\x03\x07\x04\x18\n\ \x05\0\x02\x03\x02\x12\x03\x06\x17\x19\n\x0b\n\x04\x05\0\x02\x04\x12\x03\
\x0c\n\x05\x05\0\x02\x04\x02\x12\x03\x07\x1b\x1d\n\x0b\n\x04\x05\0\x02\ \x07\x04\x1e\n\x0c\n\x05\x05\0\x02\x04\x01\x12\x03\x07\x04\x18\n\x0c\n\
\x05\x12\x03\x08\x04\x1e\n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\x08\x04\ \x05\x05\0\x02\x04\x02\x12\x03\x07\x1b\x1d\n\x0b\n\x04\x05\0\x02\x05\x12\
\x18\n\x0c\n\x05\x05\0\x02\x05\x02\x12\x03\x08\x1b\x1d\n\x0b\n\x04\x05\0\ \x03\x08\x04\x1e\n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\x08\x04\x18\n\x0c\
\x02\x06\x12\x03\t\x04\x14\n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\t\x04\ \n\x05\x05\0\x02\x05\x02\x12\x03\x08\x1b\x1d\n\x0b\n\x04\x05\0\x02\x06\
\x0e\n\x0c\n\x05\x05\0\x02\x06\x02\x12\x03\t\x11\x13\n\x0b\n\x04\x05\0\ \x12\x03\t\x04\x14\n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\t\x04\x0e\n\x0c\
\x02\x07\x12\x03\n\x04\x19\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\n\x04\ \n\x05\x05\0\x02\x06\x02\x12\x03\t\x11\x13\n\x0b\n\x04\x05\0\x02\x07\x12\
\x13\n\x0c\n\x05\x05\0\x02\x07\x02\x12\x03\n\x16\x18\n\x0b\n\x04\x05\0\ \x03\n\x04\x19\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\n\x04\x13\n\x0c\n\
\x02\x08\x12\x03\x0b\x04\x15\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\x0b\ \x05\x05\0\x02\x07\x02\x12\x03\n\x16\x18\n\x0b\n\x04\x05\0\x02\x08\x12\
\x04\x0f\n\x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0b\x12\x14\n\x0b\n\x04\ \x03\x0b\x04\x15\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\x0b\x04\x0f\n\x0c\
\x05\0\x02\t\x12\x03\x0c\x04\x1b\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\x0c\ \n\x05\x05\0\x02\x08\x02\x12\x03\x0b\x12\x14\n\x0b\n\x04\x05\0\x02\t\x12\
\x04\x14\n\x0c\n\x05\x05\0\x02\t\x02\x12\x03\x0c\x17\x1a\n\x0b\n\x04\x05\ \x03\x0c\x04\x15\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\x0c\x04\x0f\n\x0c\n\
\0\x02\n\x12\x03\r\x04\x18\n\x0c\n\x05\x05\0\x02\n\x01\x12\x03\r\x04\x10\ \x05\x05\0\x02\t\x02\x12\x03\x0c\x12\x14\n\x0b\n\x04\x05\0\x02\n\x12\x03\
\n\x0c\n\x05\x05\0\x02\n\x02\x12\x03\r\x13\x17b\x06proto3\ \r\x04\x16\n\x0c\n\x05\x05\0\x02\n\x01\x12\x03\r\x04\x10\n\x0c\n\x05\x05\
\0\x02\n\x02\x12\x03\r\x13\x15\n\x0b\n\x04\x05\0\x02\x0b\x12\x03\x0e\x04\
\x1b\n\x0c\n\x05\x05\0\x02\x0b\x01\x12\x03\x0e\x04\x14\n\x0c\n\x05\x05\0\
\x02\x0b\x02\x12\x03\x0e\x17\x1a\n\x0b\n\x04\x05\0\x02\x0c\x12\x03\x0f\
\x04\x18\n\x0c\n\x05\x05\0\x02\x0c\x01\x12\x03\x0f\x04\x10\n\x0c\n\x05\
\x05\0\x02\x0c\x02\x12\x03\x0f\x13\x17b\x06proto3\
"; ";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -10,6 +10,8 @@ enum WorkspaceNotification {
AppUpdated = 21; AppUpdated = 21;
AppViewsChanged = 24; AppViewsChanged = 24;
ViewUpdated = 31; ViewUpdated = 31;
ViewDeleted = 32;
ViewRestored = 33;
UserUnauthorized = 100; UserUnauthorized = 100;
TrashUpdated = 1000; TrashUpdated = 1000;
} }

View File

@ -22,6 +22,7 @@ use flowy_document::{
use crate::{entities::trash::TrashType, errors::WorkspaceResult}; use crate::{entities::trash::TrashType, errors::WorkspaceResult};
use crate::entities::trash::TrashIdentifiers;
use futures::{FutureExt, StreamExt}; use futures::{FutureExt, StreamExt};
use std::{collections::HashSet, sync::Arc}; use std::{collections::HashSet, sync::Arc};
@ -263,16 +264,26 @@ async fn handle_trash_event(
let db_result = database.db_connection(); let db_result = database.db_connection();
match event { match event {
TrashEvent::NewTrash(identifiers, ret) | TrashEvent::Putback(identifiers, ret) => { TrashEvent::NewTrash(identifiers, ret) => {
let result = || { let result = || {
let conn = &*db_result?; let conn = &*db_result?;
let _ = conn.immediate_transaction::<_, WorkspaceError, _>(|| { let view_tables = get_view_table_from(identifiers, conn)?;
for identifier in identifiers.items { for view_table in view_tables {
let view_table = ViewTableSql::read_view(&identifier.id, conn)?; let _ = notify_views_changed(&view_table.belong_to_id, trash_can.clone(), conn)?;
let _ = notify_views_changed(&view_table.belong_to_id, trash_can.clone(), conn)?; notify_dart(view_table, WorkspaceNotification::ViewDeleted);
} }
Ok(()) Ok::<(), WorkspaceError>(())
})?; };
let _ = ret.send(result()).await;
},
TrashEvent::Putback(identifiers, ret) => {
let result = || {
let conn = &*db_result?;
let view_tables = get_view_table_from(identifiers, conn)?;
for view_table in view_tables {
let _ = notify_views_changed(&view_table.belong_to_id, trash_can.clone(), conn)?;
notify_dart(view_table, WorkspaceNotification::ViewRestored);
}
Ok::<(), WorkspaceError>(()) Ok::<(), WorkspaceError>(())
}; };
let _ = ret.send(result()).await; let _ = ret.send(result()).await;
@ -302,6 +313,26 @@ async fn handle_trash_event(
} }
} }
fn get_view_table_from(
identifiers: TrashIdentifiers,
conn: &SqliteConnection,
) -> Result<Vec<ViewTable>, WorkspaceError> {
let mut view_tables = vec![];
let _ = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
for identifier in identifiers.items {
let view_table = ViewTableSql::read_view(&identifier.id, conn)?;
view_tables.push(view_table);
}
Ok(())
})?;
Ok(view_tables)
}
fn notify_dart(view_table: ViewTable, notification: WorkspaceNotification) {
let view: View = view_table.into();
send_dart_notification(&view.id, notification).payload(view).send();
}
#[tracing::instrument(skip(belong_to_id, trash_can, conn), fields(view_count), err)] #[tracing::instrument(skip(belong_to_id, trash_can, conn), fields(view_count), err)]
fn notify_views_changed(belong_to_id: &str, trash_can: Arc<TrashCan>, conn: &SqliteConnection) -> WorkspaceResult<()> { fn notify_views_changed(belong_to_id: &str, trash_can: Arc<TrashCan>, conn: &SqliteConnection) -> WorkspaceResult<()> {
let repeated_view = read_local_belonging_view(belong_to_id, trash_can.clone(), conn)?; let repeated_view = read_local_belonging_view(belong_to_id, trash_can.clone(), conn)?;