fix: remove the deleted workspace from local storage

This commit is contained in:
Lucas.Xu 2024-04-01 16:43:38 +08:00
parent 75e51fdeea
commit 2f6cfbdd79
3 changed files with 77 additions and 15 deletions

View File

@ -14,6 +14,9 @@ import 'package:appflowy_backend/rust_stream.dart';
import 'package:appflowy_result/appflowy_result.dart'; import 'package:appflowy_result/appflowy_result.dart';
import 'package:flowy_infra/notifier.dart'; import 'package:flowy_infra/notifier.dart';
typedef DidUserWorkspaceUpdateCallback = void Function(
RepeatedUserWorkspacePB workspaces,
);
typedef UserProfileNotifyValue = FlowyResult<UserProfilePB, FlowyError>; typedef UserProfileNotifyValue = FlowyResult<UserProfilePB, FlowyError>;
typedef AuthNotifyValue = FlowyResult<void, FlowyError>; typedef AuthNotifyValue = FlowyResult<void, FlowyError>;
@ -27,14 +30,20 @@ class UserListener {
UserNotificationParser? _userParser; UserNotificationParser? _userParser;
StreamSubscription<SubscribeObject>? _subscription; StreamSubscription<SubscribeObject>? _subscription;
PublishNotifier<UserProfileNotifyValue>? _profileNotifier = PublishNotifier(); PublishNotifier<UserProfileNotifyValue>? _profileNotifier = PublishNotifier();
DidUserWorkspaceUpdateCallback? didUpdateUserWorkspaces;
void start({ void start({
void Function(UserProfileNotifyValue)? onProfileUpdated, void Function(UserProfileNotifyValue)? onProfileUpdated,
void Function(RepeatedUserWorkspacePB)? didUpdateUserWorkspaces,
}) { }) {
if (onProfileUpdated != null) { if (onProfileUpdated != null) {
_profileNotifier?.addPublishListener(onProfileUpdated); _profileNotifier?.addPublishListener(onProfileUpdated);
} }
if (didUpdateUserWorkspaces != null) {
this.didUpdateUserWorkspaces = didUpdateUserWorkspaces;
}
_userParser = UserNotificationParser( _userParser = UserNotificationParser(
id: _userProfile.id.toString(), id: _userProfile.id.toString(),
callback: _userNotificationCallback, callback: _userNotificationCallback,
@ -63,6 +72,14 @@ class UserListener {
(error) => _profileNotifier?.value = FlowyResult.failure(error), (error) => _profileNotifier?.value = FlowyResult.failure(error),
); );
break; break;
case user.UserNotification.DidUpdateUserWorkspaces:
result.map(
(r) {
final value = RepeatedUserWorkspacePB.fromBuffer(r);
didUpdateUserWorkspaces?.call(value);
},
);
break;
default: default:
break; break;
} }
@ -108,6 +125,7 @@ class UserWorkspaceListener {
_settingChangedNotifier?.value = FlowyResult.failure(error), _settingChangedNotifier?.value = FlowyResult.failure(error),
); );
break; break;
default: default:
break; break;
} }

View File

@ -3,6 +3,7 @@ import 'package:appflowy/core/config/kv_keys.dart';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/shared/feature_flags.dart'; import 'package:appflowy/shared/feature_flags.dart';
import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/user/application/user_listener.dart';
import 'package:appflowy/user/application/user_service.dart'; import 'package:appflowy/user/application/user_service.dart';
import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/code.pbenum.dart'; import 'package:appflowy_backend/protobuf/flowy-error/code.pbenum.dart';
@ -22,11 +23,18 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
UserWorkspaceBloc({ UserWorkspaceBloc({
required this.userProfile, required this.userProfile,
}) : _userService = UserBackendService(userId: userProfile.id), }) : _userService = UserBackendService(userId: userProfile.id),
_listener = UserListener(userProfile: userProfile),
super(UserWorkspaceState.initial()) { super(UserWorkspaceState.initial()) {
on<UserWorkspaceEvent>( on<UserWorkspaceEvent>(
(event, emit) async { (event, emit) async {
await event.when( await event.when(
initial: () async { initial: () async {
_listener
..didUpdateUserWorkspaces = (workspaces) {
add(UserWorkspaceEvent.updateWorkspaces(workspaces));
}
..start();
final result = await _fetchWorkspaces(); final result = await _fetchWorkspaces();
final isCollabWorkspaceOn = final isCollabWorkspaceOn =
userProfile.authenticator != AuthenticatorPB.Local && userProfile.authenticator != AuthenticatorPB.Local &&
@ -246,13 +254,30 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
), ),
); );
}, },
updateWorkspaces: (workspaces) async {
if (!const DeepCollectionEquality()
.equals(workspaces.items, state.workspaces)) {
emit(
state.copyWith(
workspaces: workspaces.items,
),
);
}
},
); );
}, },
); );
} }
@override
Future<void> close() {
_listener.stop();
return super.close();
}
final UserProfilePB userProfile; final UserProfilePB userProfile;
final UserBackendService _userService; final UserBackendService _userService;
final UserListener _listener;
Future< Future<
( (
@ -308,6 +333,9 @@ class UserWorkspaceEvent with _$UserWorkspaceEvent {
) = _UpdateWorkspaceIcon; ) = _UpdateWorkspaceIcon;
const factory UserWorkspaceEvent.leaveWorkspace(String workspaceId) = const factory UserWorkspaceEvent.leaveWorkspace(String workspaceId) =
LeaveWorkspace; LeaveWorkspace;
const factory UserWorkspaceEvent.updateWorkspaces(
RepeatedUserWorkspacePB workspaces,
) = UpdateWorkspaces;
} }
enum UserWorkspaceActionType { enum UserWorkspaceActionType {

View File

@ -332,14 +332,24 @@ pub fn save_user_workspaces(
) -> FlowyResult<()> { ) -> FlowyResult<()> {
let user_workspaces = user_workspaces let user_workspaces = user_workspaces
.iter() .iter()
.flat_map(|user_workspace| UserWorkspaceTable::try_from((uid, user_workspace)).ok()) .map(|user_workspace| UserWorkspaceTable::try_from((uid, user_workspace)))
.collect::<Vec<UserWorkspaceTable>>(); .collect::<Result<Vec<_>, _>>()?;
conn.immediate_transaction(|conn| { conn.immediate_transaction(|conn| {
for user_workspace in user_workspaces { let existing_ids = user_workspace_table::dsl::user_workspace_table
if let Err(err) = diesel::update( .select(user_workspace_table::id)
.load::<String>(conn)?;
let new_ids: Vec<String> = user_workspaces.iter().map(|w| w.id.clone()).collect();
let ids_to_delete: Vec<String> = existing_ids
.into_iter()
.filter(|id| !new_ids.contains(id))
.collect();
// insert or update the user workspaces
for user_workspace in &user_workspaces {
let affected_rows = diesel::update(
user_workspace_table::dsl::user_workspace_table user_workspace_table::dsl::user_workspace_table
.filter(user_workspace_table::id.eq(user_workspace.id.clone())), .filter(user_workspace_table::id.eq(&user_workspace.id)),
) )
.set(( .set((
user_workspace_table::name.eq(&user_workspace.name), user_workspace_table::name.eq(&user_workspace.name),
@ -347,18 +357,24 @@ pub fn save_user_workspaces(
user_workspace_table::database_storage_id.eq(&user_workspace.database_storage_id), user_workspace_table::database_storage_id.eq(&user_workspace.database_storage_id),
user_workspace_table::icon.eq(&user_workspace.icon), user_workspace_table::icon.eq(&user_workspace.icon),
)) ))
.execute(conn) .execute(conn)?;
.and_then(|rows| {
if rows == 0 { if affected_rows == 0 {
let _ = diesel::insert_into(user_workspace_table::table) diesel::insert_into(user_workspace_table::table)
.values(user_workspace) .values(user_workspace)
.execute(conn)?; .execute(conn)?;
}
Ok(())
}) {
tracing::error!("Error saving user workspace: {:?}", err);
} }
} }
// delete the user workspaces that are not in the new list
if !ids_to_delete.is_empty() {
diesel::delete(
user_workspace_table::dsl::user_workspace_table
.filter(user_workspace_table::id.eq_any(ids_to_delete)),
)
.execute(conn)?;
}
Ok::<(), FlowyError>(()) Ok::<(), FlowyError>(())
}) })
} }