fix: view title update issue

This commit is contained in:
appflowy 2022-05-05 21:15:01 +08:00
parent 448c134704
commit 2f2b69d1a6
11 changed files with 113 additions and 82 deletions

View File

@ -12,17 +12,17 @@ import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/dart_notification.pb.dart' as user; import 'package:flowy_sdk/protobuf/flowy-user/dart_notification.pb.dart' as user;
import 'package:flowy_sdk/rust_stream.dart'; import 'package:flowy_sdk/rust_stream.dart';
typedef UserProfileDidUpdate = Either<UserProfile, FlowyError>; typedef UserProfileNotifyValue = Either<UserProfile, FlowyError>;
typedef AuthDidUpdate = Either<Unit, FlowyError>; typedef AuthNotifyValue = Either<Unit, FlowyError>;
typedef WorkspaceListDidUpdate = Either<List<Workspace>, FlowyError>; typedef WorkspaceListNotifyValue = Either<List<Workspace>, FlowyError>;
typedef WorkspaceSettingDidUpdate = Either<CurrentWorkspaceSetting, FlowyError>; typedef WorkspaceSettingNotifyValue = Either<CurrentWorkspaceSetting, FlowyError>;
class UserListener { class UserListener {
StreamSubscription<SubscribeObject>? _subscription; StreamSubscription<SubscribeObject>? _subscription;
final _profileNotifier = PublishNotifier<UserProfileDidUpdate>(); final _profileNotifier = PublishNotifier<UserProfileNotifyValue>();
final _authNotifier = PublishNotifier<AuthDidUpdate>(); final _authNotifier = PublishNotifier<AuthNotifyValue>();
final _workspaceListNotifier = PublishNotifier<WorkspaceListDidUpdate>(); final _workspaceListNotifier = PublishNotifier<WorkspaceListNotifyValue>();
final _workSettingNotifier = PublishNotifier<WorkspaceSettingDidUpdate>(); final _workSettingNotifier = PublishNotifier<WorkspaceSettingNotifyValue>();
FolderNotificationParser? _workspaceParser; FolderNotificationParser? _workspaceParser;
UserNotificationParser? _userParser; UserNotificationParser? _userParser;
@ -32,32 +32,32 @@ class UserListener {
}) : _user = user; }) : _user = user;
void start({ void start({
void Function(AuthDidUpdate)? authDidChange, void Function(AuthNotifyValue)? onAuthChanged,
void Function(UserProfileDidUpdate)? profileDidUpdate, void Function(UserProfileNotifyValue)? onProfileUpdated,
void Function(WorkspaceListDidUpdate)? workspaceListDidUpdate, void Function(WorkspaceListNotifyValue)? onWorkspaceListUpdated,
void Function(WorkspaceSettingDidUpdate)? workspaceSettingDidUpdate, void Function(WorkspaceSettingNotifyValue)? onWorkspaceSettingUpdated,
}) { }) {
if (authDidChange != null) { if (onAuthChanged != null) {
_authNotifier.addListener(() { _authNotifier.addListener(() {
authDidChange(_authNotifier.currentValue!); onAuthChanged(_authNotifier.currentValue!);
}); });
} }
if (profileDidUpdate != null) { if (onProfileUpdated != null) {
_profileNotifier.addListener(() { _profileNotifier.addListener(() {
profileDidUpdate(_profileNotifier.currentValue!); onProfileUpdated(_profileNotifier.currentValue!);
}); });
} }
if (workspaceListDidUpdate != null) { if (onWorkspaceListUpdated != null) {
_workspaceListNotifier.addListener(() { _workspaceListNotifier.addListener(() {
workspaceListDidUpdate(_workspaceListNotifier.currentValue!); onWorkspaceListUpdated(_workspaceListNotifier.currentValue!);
}); });
} }
if (workspaceSettingDidUpdate != null) { if (onWorkspaceSettingUpdated != null) {
_workSettingNotifier.addListener(() { _workSettingNotifier.addListener(() {
workspaceSettingDidUpdate(_workSettingNotifier.currentValue!); onWorkspaceSettingUpdated(_workSettingNotifier.currentValue!);
}); });
} }

View File

@ -41,7 +41,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
void _startListening() { void _startListening() {
appListener.start( appListener.start(
viewsChanged: (result) { onViewsChanged: (result) {
result.fold( result.fold(
(views) { (views) {
if (!isClosed) { if (!isClosed) {
@ -51,7 +51,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
(error) => Log.error(error), (error) => Log.error(error),
); );
}, },
appUpdated: (app) { onAppUpdated: (app) {
if (!isClosed) { if (!isClosed) {
add(AppEvent.appDidUpdate(app)); add(AppEvent.appDidUpdate(app));
} }
@ -97,7 +97,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
@override @override
Future<void> close() async { Future<void> close() async {
await appListener.close(); await appListener.stop();
return super.close(); return super.close();
} }

View File

@ -24,9 +24,9 @@ class AppListener {
required this.appId, required this.appId,
}); });
void start({ViewsDidChangeCallback? viewsChanged, AppDidUpdateCallback? appUpdated}) { void start({ViewsDidChangeCallback? onViewsChanged, AppDidUpdateCallback? onAppUpdated}) {
_viewsChanged = viewsChanged; _viewsChanged = onViewsChanged;
_updated = appUpdated; _updated = onAppUpdated;
_parser = FolderNotificationParser(id: appId, callback: _bservableCallback); _parser = FolderNotificationParser(id: appId, callback: _bservableCallback);
_subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
} }
@ -60,7 +60,7 @@ class AppListener {
} }
} }
Future<void> close() async { Future<void> stop() async {
_parser = null; _parser = null;
await _subscription?.cancel(); await _subscription?.cancel();
_viewsChanged = null; _viewsChanged = null;

View File

@ -59,7 +59,7 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
@override @override
Future<void> close() async { Future<void> close() async {
await listener.close(); await listener.stop();
if (_subscription != null) { if (_subscription != null) {
await _subscription?.cancel(); await _subscription?.cancel();
@ -70,21 +70,20 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
} }
Future<void> _initial(Initial value, Emitter<DocumentState> emit) async { Future<void> _initial(Initial value, Emitter<DocumentState> emit) async {
listener.deletedNotifier.addPublishListener((result) { listener.start(
result.fold( onViewDeleted: (result) {
(view) => add(const DocumentEvent.deleted()), result.fold(
(error) {}, (view) => add(const DocumentEvent.deleted()),
); (error) {},
}); );
},
listener.restoredNotifier.addPublishListener((result) { onViewRestored: (result) {
result.fold( result.fold(
(view) => add(const DocumentEvent.restore()), (view) => add(const DocumentEvent.restore()),
(error) {}, (error) {},
); );
}); },
);
listener.start();
final result = await service.openDocument(docId: view.id); final result = await service.openDocument(docId: view.id);
result.fold( result.fold(
(block) { (block) {

View File

@ -20,10 +20,10 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
await event.map( await event.map(
initial: (_Initial value) { initial: (_Initial value) {
_listener.start( _listener.start(
authDidChange: (result) { onAuthChanged: (result) {
_authDidChanged(result); _authDidChanged(result);
}, },
workspaceSettingDidUpdate: (result) { onWorkspaceSettingUpdated: (result) {
result.fold( result.fold(
(setting) => add(HomeEvent.didReceiveWorkspaceSetting(setting)), (setting) => add(HomeEvent.didReceiveWorkspaceSetting(setting)),
(r) => Log.error(r), (r) => Log.error(r),

View File

@ -20,8 +20,8 @@ class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
await event.map( await event.map(
initial: (_) async { initial: (_) async {
userListener.start( userListener.start(
profileDidUpdate: _profileUpdated, onProfileUpdated: _profileUpdated,
workspaceListDidUpdate: _workspaceListUpdated, onWorkspaceListUpdated: _workspaceListUpdated,
); );
await _initUser(); await _initUser();
}, },

View File

@ -21,12 +21,9 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
on<ViewEvent>((event, emit) async { on<ViewEvent>((event, emit) async {
await event.map( await event.map(
initial: (e) { initial: (e) {
// TODO: Listener can be refactored to a stream. listener.start(onViewUpdated: (result) {
listener.updatedNotifier.addPublishListener((result) {
// emit.forEach(stream, onData: onData)
add(ViewEvent.viewDidUpdate(result)); add(ViewEvent.viewDidUpdate(result));
}); });
listener.start();
emit(state); emit(state);
}, },
setIsEditing: (e) { setIsEditing: (e) {
@ -34,14 +31,12 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
}, },
viewDidUpdate: (e) { viewDidUpdate: (e) {
e.result.fold( e.result.fold(
(view) => (view) => emit(state.copyWith(view: view, successOrFailure: left(unit))),
emit(state.copyWith(view: view, successOrFailure: left(unit))),
(error) => emit(state.copyWith(successOrFailure: right(error))), (error) => emit(state.copyWith(successOrFailure: right(error))),
); );
}, },
rename: (e) async { rename: (e) async {
final result = final result = await service.updateView(viewId: view.id, name: e.newName);
await service.updateView(viewId: view.id, name: e.newName);
emit( emit(
result.fold( result.fold(
(l) => state.copyWith(successOrFailure: left(unit)), (l) => state.copyWith(successOrFailure: left(unit)),
@ -74,7 +69,7 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
@override @override
Future<void> close() async { Future<void> close() async {
await listener.close(); await listener.stop();
return super.close(); return super.close();
} }
} }
@ -86,8 +81,7 @@ class ViewEvent with _$ViewEvent {
const factory ViewEvent.rename(String newName) = Rename; const factory ViewEvent.rename(String newName) = Rename;
const factory ViewEvent.delete() = Delete; const factory ViewEvent.delete() = Delete;
const factory ViewEvent.duplicate() = Duplicate; const factory ViewEvent.duplicate() = Duplicate;
const factory ViewEvent.viewDidUpdate(Either<View, FlowyError> result) = const factory ViewEvent.viewDidUpdate(Either<View, FlowyError> result) = ViewDidUpdate;
ViewDidUpdate;
} }
@freezed @freezed

View File

@ -15,9 +15,9 @@ typedef RestoreViewNotifiedValue = Either<View, FlowyError>;
class ViewListener { class ViewListener {
StreamSubscription<SubscribeObject>? _subscription; StreamSubscription<SubscribeObject>? _subscription;
PublishNotifier<UpdateViewNotifiedValue> updatedNotifier = PublishNotifier<UpdateViewNotifiedValue>(); final PublishNotifier<UpdateViewNotifiedValue> _updatedViewNotifier = PublishNotifier();
PublishNotifier<DeleteViewNotifyValue> deletedNotifier = PublishNotifier<DeleteViewNotifyValue>(); final PublishNotifier<DeleteViewNotifyValue> _deletedNotifier = PublishNotifier();
PublishNotifier<RestoreViewNotifiedValue> restoredNotifier = PublishNotifier<RestoreViewNotifiedValue>(); final PublishNotifier<RestoreViewNotifiedValue> _restoredNotifier = PublishNotifier();
FolderNotificationParser? _parser; FolderNotificationParser? _parser;
View view; View view;
@ -25,7 +25,29 @@ class ViewListener {
required this.view, required this.view,
}); });
void start() { void start({
void Function(UpdateViewNotifiedValue)? onViewUpdated,
void Function(DeleteViewNotifyValue)? onViewDeleted,
void Function(RestoreViewNotifiedValue)? onViewRestored,
}) {
if (onViewUpdated != null) {
_updatedViewNotifier.addListener(() {
onViewUpdated(_updatedViewNotifier.currentValue!);
});
}
if (onViewDeleted != null) {
_deletedNotifier.addListener(() {
onViewDeleted(_deletedNotifier.currentValue!);
});
}
if (onViewRestored != null) {
_restoredNotifier.addListener(() {
onViewRestored(_restoredNotifier.currentValue!);
});
}
_parser = FolderNotificationParser( _parser = FolderNotificationParser(
id: view.id, id: view.id,
callback: (ty, result) { callback: (ty, result) {
@ -40,20 +62,20 @@ class ViewListener {
switch (ty) { switch (ty) {
case FolderNotification.ViewUpdated: case FolderNotification.ViewUpdated:
result.fold( result.fold(
(payload) => updatedNotifier.value = left(View.fromBuffer(payload)), (payload) => _updatedViewNotifier.value = left(View.fromBuffer(payload)),
(error) => updatedNotifier.value = right(error), (error) => _updatedViewNotifier.value = right(error),
); );
break; break;
case FolderNotification.ViewDeleted: case FolderNotification.ViewDeleted:
result.fold( result.fold(
(payload) => deletedNotifier.value = left(View.fromBuffer(payload)), (payload) => _deletedNotifier.value = left(View.fromBuffer(payload)),
(error) => deletedNotifier.value = right(error), (error) => _deletedNotifier.value = right(error),
); );
break; break;
case FolderNotification.ViewRestored: case FolderNotification.ViewRestored:
result.fold( result.fold(
(payload) => restoredNotifier.value = left(View.fromBuffer(payload)), (payload) => _restoredNotifier.value = left(View.fromBuffer(payload)),
(error) => restoredNotifier.value = right(error), (error) => _restoredNotifier.value = right(error),
); );
break; break;
default: default:
@ -61,11 +83,11 @@ class ViewListener {
} }
} }
Future<void> close() async { Future<void> stop() async {
_parser = null; _parser = null;
await _subscription?.cancel(); await _subscription?.cancel();
updatedNotifier.dispose(); _updatedViewNotifier.dispose();
deletedNotifier.dispose(); _deletedNotifier.dispose();
restoredNotifier.dispose(); _restoredNotifier.dispose();
} }
} }

View File

@ -17,7 +17,7 @@ class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
(event, emit) async { (event, emit) async {
await event.map(initial: (e) async { await event.map(initial: (e) async {
userListener.start( userListener.start(
workspaceListDidUpdate: (result) => add(WelcomeEvent.workspacesReveived(result)), onWorkspaceListUpdated: (result) => add(WelcomeEvent.workspacesReveived(result)),
); );
// //
await _fetchWorkspaces(emit); await _fetchWorkspaces(emit);

View File

@ -60,7 +60,7 @@ class DocumentPlugin implements Plugin {
DocumentPlugin({required PluginType pluginType, required View view, Key? key}) : _view = view { DocumentPlugin({required PluginType pluginType, required View view, Key? key}) : _view = view {
_pluginType = pluginType; _pluginType = pluginType;
_listener = getIt<ViewListener>(param1: view); _listener = getIt<ViewListener>(param1: view);
_listener?.updatedNotifier.addPublishListener((result) { _listener?.start(onViewUpdated: (result) {
result.fold( result.fold(
(newView) { (newView) {
_view = newView; _view = newView;
@ -69,12 +69,11 @@ class DocumentPlugin implements Plugin {
(error) {}, (error) {},
); );
}); });
_listener?.start();
} }
@override @override
void dispose() { void dispose() {
_listener?.close(); _listener?.stop();
_listener = null; _listener = null;
} }

View File

@ -1,5 +1,7 @@
import 'package:app_flowy/workspace/application/view/view_listener.dart';
import 'package:app_flowy/workspace/application/view/view_service.dart'; import 'package:app_flowy/workspace/application/view/view_service.dart';
import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -16,12 +18,26 @@ class ViewLeftBarItem extends StatefulWidget {
class _ViewLeftBarItemState extends State<ViewLeftBarItem> { class _ViewLeftBarItemState extends State<ViewLeftBarItem> {
final _controller = TextEditingController(); final _controller = TextEditingController();
final _focusNode = FocusNode(); final _focusNode = FocusNode();
late ViewService serviceService; late ViewService _viewService;
late ViewListener _viewListener;
late View view;
@override @override
void initState() { void initState() {
serviceService = ViewService(/*view: widget.view*/); view = widget.view;
_viewService = ViewService();
_focusNode.addListener(_handleFocusChanged); _focusNode.addListener(_handleFocusChanged);
_viewListener = ViewListener(view: widget.view);
_viewListener.start(onViewUpdated: (result) {
result.fold(
(updatedView) {
if (mounted) {
setState(() => view = updatedView);
}
},
(err) => Log.error(err),
);
});
super.initState(); super.initState();
} }
@ -30,12 +46,13 @@ class _ViewLeftBarItemState extends State<ViewLeftBarItem> {
_controller.dispose(); _controller.dispose();
_focusNode.removeListener(_handleFocusChanged); _focusNode.removeListener(_handleFocusChanged);
_focusNode.dispose(); _focusNode.dispose();
_viewListener.stop();
super.dispose(); super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_controller.text = widget.view.name; _controller.text = view.name;
final theme = context.watch<AppTheme>(); final theme = context.watch<AppTheme>();
return IntrinsicWidth( return IntrinsicWidth(
@ -63,12 +80,12 @@ class _ViewLeftBarItemState extends State<ViewLeftBarItem> {
void _handleFocusChanged() { void _handleFocusChanged() {
if (_controller.text.isEmpty) { if (_controller.text.isEmpty) {
_controller.text = widget.view.name; _controller.text = view.name;
return; return;
} }
if (_controller.text != widget.view.name) { if (_controller.text != view.name) {
serviceService.updateView(viewId: widget.view.id, name: _controller.text); _viewService.updateView(viewId: view.id, name: _controller.text);
} }
} }
} }