mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: support leaving workspace (#5007)
This commit is contained in:
parent
dc8f632e3e
commit
0e7b3c7db2
@ -5,12 +5,16 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
extension AFRolePBExtension on AFRolePB {
|
||||
bool get isOwner => this == AFRolePB.Owner;
|
||||
|
||||
bool get isMember => this == AFRolePB.Member;
|
||||
|
||||
bool get canInvite => isOwner;
|
||||
|
||||
bool get canDelete => isOwner;
|
||||
|
||||
bool get canUpdate => isOwner;
|
||||
|
||||
bool get canLeave => this != AFRolePB.Owner;
|
||||
|
||||
String get description {
|
||||
switch (this) {
|
||||
case AFRolePB.Owner:
|
||||
|
@ -190,4 +190,11 @@ class UserBackendService {
|
||||
..role = role;
|
||||
return UserEventUpdateWorkspaceMember(data).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> leaveWorkspace(
|
||||
String workspaceId,
|
||||
) async {
|
||||
final data = UserWorkspaceIdPB.create()..workspaceId = workspaceId;
|
||||
return UserEventLeaveWorkspace(data).send();
|
||||
}
|
||||
}
|
||||
|
@ -218,6 +218,30 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
|
||||
),
|
||||
);
|
||||
},
|
||||
leaveWorkspace: (workspaceId) async {
|
||||
final result = await _userService.leaveWorkspace(workspaceId);
|
||||
final workspaces = result.fold(
|
||||
(s) => state.workspaces
|
||||
.where((e) => e.workspaceId != workspaceId)
|
||||
.toList(),
|
||||
(e) => state.workspaces,
|
||||
);
|
||||
result.onSuccess((_) {
|
||||
// if leaving the current workspace, open the first workspace
|
||||
if (state.currentWorkspace?.workspaceId == workspaceId) {
|
||||
add(OpenWorkspace(workspaces.first.workspaceId));
|
||||
}
|
||||
});
|
||||
emit(
|
||||
state.copyWith(
|
||||
workspaces: workspaces,
|
||||
actionResult: UserWorkspaceActionResult(
|
||||
actionType: UserWorkspaceActionType.leave,
|
||||
result: result,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
@ -270,6 +294,8 @@ class UserWorkspaceEvent with _$UserWorkspaceEvent {
|
||||
String workspaceId,
|
||||
String icon,
|
||||
) = _UpdateWorkspaceIcon;
|
||||
const factory UserWorkspaceEvent.leaveWorkspace(String workspaceId) =
|
||||
LeaveWorkspace;
|
||||
}
|
||||
|
||||
enum UserWorkspaceActionType {
|
||||
@ -279,7 +305,8 @@ enum UserWorkspaceActionType {
|
||||
open,
|
||||
rename,
|
||||
updateIcon,
|
||||
fetchWorkspaces;
|
||||
fetchWorkspaces,
|
||||
leave;
|
||||
}
|
||||
|
||||
class UserWorkspaceActionResult {
|
||||
|
@ -112,6 +112,7 @@ class SidebarWorkspace extends StatelessWidget {
|
||||
break;
|
||||
case UserWorkspaceActionType.none:
|
||||
case UserWorkspaceActionType.fetchWorkspaces:
|
||||
case UserWorkspaceActionType.leave:
|
||||
message = null;
|
||||
break;
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/shared/af_role_pb_extension.dart';
|
||||
import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/members/workspace_member_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
||||
@ -13,6 +15,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
enum WorkspaceMoreAction {
|
||||
rename,
|
||||
delete,
|
||||
leave,
|
||||
}
|
||||
|
||||
class WorkspaceMoreActionList extends StatelessWidget {
|
||||
@ -25,9 +28,20 @@ class WorkspaceMoreActionList extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final myRole = context.read<WorkspaceMemberBloc>().state.myRole;
|
||||
final actions = [];
|
||||
if (myRole.isOwner) {
|
||||
actions.add(WorkspaceMoreAction.rename);
|
||||
actions.add(WorkspaceMoreAction.delete);
|
||||
} else if (myRole.canLeave) {
|
||||
actions.add(WorkspaceMoreAction.leave);
|
||||
}
|
||||
if (actions.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return PopoverActionList<_WorkspaceMoreActionWrapper>(
|
||||
direction: PopoverDirection.bottomWithCenterAligned,
|
||||
actions: WorkspaceMoreAction.values
|
||||
actions: actions
|
||||
.map((e) => _WorkspaceMoreActionWrapper(e, workspace))
|
||||
.toList(),
|
||||
buildChild: (controller) {
|
||||
@ -92,6 +106,20 @@ class _WorkspaceMoreActionWrapper extends CustomActionCell {
|
||||
);
|
||||
},
|
||||
).show(context);
|
||||
case WorkspaceMoreAction.leave:
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (_) => NavigatorOkCancelDialog(
|
||||
title: LocaleKeys.workspace_leaveCurrentWorkspace.tr(),
|
||||
message: LocaleKeys.workspace_leaveCurrentWorkspacePrompt.tr(),
|
||||
onOkPressed: () {
|
||||
workspaceBloc.add(
|
||||
UserWorkspaceEvent.leaveWorkspace(workspace.workspaceId),
|
||||
);
|
||||
},
|
||||
okTitle: LocaleKeys.button_yes.tr(),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
@ -103,6 +131,8 @@ class _WorkspaceMoreActionWrapper extends CustomActionCell {
|
||||
return LocaleKeys.button_delete.tr();
|
||||
case WorkspaceMoreAction.rename:
|
||||
return LocaleKeys.button_rename.tr();
|
||||
case WorkspaceMoreAction.leave:
|
||||
return LocaleKeys.workspace_leaveCurrentWorkspace.tr();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/shared/af_role_pb_extension.dart';
|
||||
import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_actions.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_icon.dart';
|
||||
@ -201,8 +200,7 @@ class WorkspaceMenuItem extends StatelessWidget {
|
||||
|
||||
return Row(
|
||||
children: [
|
||||
if (context.read<WorkspaceMemberBloc>().state.myRole.isOwner)
|
||||
WorkspaceMoreActionList(workspace: workspace),
|
||||
WorkspaceMoreActionList(workspace: workspace),
|
||||
const FlowySvg(
|
||||
FlowySvgs.blue_check_s,
|
||||
),
|
||||
|
@ -79,7 +79,9 @@
|
||||
"updateIconSuccess": "Updated workspace icon successfully",
|
||||
"updateIconFailed": "Updated workspace icon failed",
|
||||
"cannotDeleteTheOnlyWorkspace": "Cannot delete the only workspace",
|
||||
"fetchWorkspacesFailed": "Failed to fetch workspaces"
|
||||
"fetchWorkspacesFailed": "Failed to fetch workspaces",
|
||||
"leaveCurrentWorkspace": "Leave workspace",
|
||||
"leaveCurrentWorkspacePrompt": "Are you sure you want to leave the current workspace?"
|
||||
},
|
||||
"shareAction": {
|
||||
"buttonText": "Share",
|
||||
|
Loading…
Reference in New Issue
Block a user