chore: remove workspac id in user profile (#5962)

* chore: remove workspac id in user profile

* chore: fix test

* chore: clippy

* chore: clippy

* chore: fix cloud test

* chore: fix checklist test
This commit is contained in:
Nathan.fooo 2024-08-14 19:44:15 +08:00 committed by GitHub
parent fa230907ca
commit 8935b7158c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 76 additions and 71 deletions

View File

@ -47,31 +47,28 @@ void main() {
await tester.openSettingsPage(SettingsPage.account); await tester.openSettingsPage(SettingsPage.account);
await tester.enterUserName(name); await tester.enterUserName(name);
await tester.tapEscButton();
// wait 2 seconds for the sync to finish
await tester.pumpAndSettle(const Duration(seconds: 6)); await tester.pumpAndSettle(const Duration(seconds: 6));
}); await tester.logout();
await tester.pumpAndSettle(const Duration(seconds: 2));
testWidgets('get user icon and name from server', (tester) async {
await tester.initializeAppFlowy(
cloudType: AuthenticatorType.appflowyCloudSelfHost,
email: email,
);
await tester.tapGoogleLoginInButton();
await tester.expectToSeeHomePageWithGetStartedPage();
await tester.pumpAndSettle();
await tester.openSettings();
await tester.openSettingsPage(SettingsPage.account);
// Verify name
final profileSetting =
tester.widget(find.byType(UserProfileSetting)) as UserProfileSetting;
expect(profileSetting.name, name);
}); });
}); });
testWidgets('get user icon and name from server', (tester) async {
await tester.initializeAppFlowy(
cloudType: AuthenticatorType.appflowyCloudSelfHost,
email: email,
);
await tester.tapGoogleLoginInButton();
await tester.expectToSeeHomePageWithGetStartedPage();
await tester.pumpAndSettle();
await tester.openSettings();
await tester.openSettingsPage(SettingsPage.account);
// Verify name
final profileSetting =
tester.widget(find.byType(UserProfileSetting)) as UserProfileSetting;
expect(profileSetting.name, name);
});
} }

View File

@ -461,22 +461,22 @@ void main() {
tester.assertChecklistEditorVisible(visible: true); tester.assertChecklistEditorVisible(visible: true);
// create a new task with enter // create a new task with enter
await tester.createNewChecklistTask(name: "task 0", enter: true); await tester.createNewChecklistTask(name: "task 1", enter: true);
// assert that the task is displayed // assert that the task is displayed
tester.assertChecklistTaskInEditor( tester.assertChecklistTaskInEditor(
index: 0, index: 0,
name: "task 0", name: "task 1",
isChecked: false, isChecked: false,
); );
// update the task's name // update the task's name
await tester.renameChecklistTask(index: 0, name: "task 1"); await tester.renameChecklistTask(index: 0, name: "task 11");
// assert that the task's name is updated // assert that the task's name is updated
tester.assertChecklistTaskInEditor( tester.assertChecklistTaskInEditor(
index: 0, index: 0,
name: "task 1", name: "task 11",
isChecked: false, isChecked: false,
); );

View File

@ -80,7 +80,7 @@ extension AppFlowySettings on WidgetTester {
of: find.byType(UserProfileSetting), of: find.byType(UserProfileSetting),
matching: find.byFlowySvg(FlowySvgs.edit_s), matching: find.byFlowySvg(FlowySvgs.edit_s),
); );
await tap(editUsernameFinder); await tap(editUsernameFinder, warnIfMissed: false);
await pumpAndSettle(); await pumpAndSettle();
final userNameFinder = find.descendant( final userNameFinder = find.descendant(

View File

@ -15,8 +15,11 @@ part 'local_ai_on_boarding_bloc.freezed.dart';
class LocalAIOnBoardingBloc class LocalAIOnBoardingBloc
extends Bloc<LocalAIOnBoardingEvent, LocalAIOnBoardingState> { extends Bloc<LocalAIOnBoardingEvent, LocalAIOnBoardingState> {
LocalAIOnBoardingBloc(this.userProfile) LocalAIOnBoardingBloc(
: super(const LocalAIOnBoardingState()) { this.userProfile,
this.member,
this.workspaceId,
) : super(const LocalAIOnBoardingState()) {
_userService = UserBackendService(userId: userProfile.id); _userService = UserBackendService(userId: userProfile.id);
_successListenable = getIt<SubscriptionSuccessListenable>(); _successListenable = getIt<SubscriptionSuccessListenable>();
_successListenable.addListener(_onPaymentSuccessful); _successListenable.addListener(_onPaymentSuccessful);
@ -36,6 +39,8 @@ class LocalAIOnBoardingBloc
} }
final UserProfilePB userProfile; final UserProfilePB userProfile;
final WorkspaceMemberPB member;
final String workspaceId;
late final IUserBackendService _userService; late final IUserBackendService _userService;
late final SubscriptionSuccessListenable _successListenable; late final SubscriptionSuccessListenable _successListenable;
@ -48,7 +53,7 @@ class LocalAIOnBoardingBloc
addSubscription: (plan) async { addSubscription: (plan) async {
emit(state.copyWith(isLoading: true)); emit(state.copyWith(isLoading: true));
final result = await _userService.createSubscription( final result = await _userService.createSubscription(
userProfile.workspaceId, workspaceId,
plan, plan,
); );
@ -72,7 +77,7 @@ class LocalAIOnBoardingBloc
); );
}, },
(err) { (err) {
Log.error("Failed to get subscription plans: $err"); Log.warn("Failed to get subscription plans: $err");
}, },
); );
}, },
@ -86,7 +91,7 @@ class LocalAIOnBoardingBloc
} }
void _loadSubscriptionPlans() { void _loadSubscriptionPlans() {
final payload = UserWorkspaceIdPB()..workspaceId = userProfile.workspaceId; final payload = UserWorkspaceIdPB()..workspaceId = workspaceId;
UserEventGetWorkspaceSubscriptionInfo(payload).send().then((result) { UserEventGetWorkspaceSubscriptionInfo(payload).send().then((result) {
if (!isClosed) { if (!isClosed) {
add(LocalAIOnBoardingEvent.didGetSubscriptionPlans(result)); add(LocalAIOnBoardingEvent.didGetSubscriptionPlans(result));

View File

@ -11,8 +11,11 @@ import 'package:freezed_annotation/freezed_annotation.dart';
part 'settings_ai_bloc.freezed.dart'; part 'settings_ai_bloc.freezed.dart';
class SettingsAIBloc extends Bloc<SettingsAIEvent, SettingsAIState> { class SettingsAIBloc extends Bloc<SettingsAIEvent, SettingsAIState> {
SettingsAIBloc(this.userProfile, WorkspaceMemberPB? member) SettingsAIBloc(
: _userListener = UserListener(userProfile: userProfile), this.userProfile,
this.workspaceId,
WorkspaceMemberPB? member,
) : _userListener = UserListener(userProfile: userProfile),
_userService = UserBackendService(userId: userProfile.id), _userService = UserBackendService(userId: userProfile.id),
super(SettingsAIState(userProfile: userProfile, member: member)) { super(SettingsAIState(userProfile: userProfile, member: member)) {
_dispatch(); _dispatch();
@ -36,6 +39,7 @@ class SettingsAIBloc extends Bloc<SettingsAIEvent, SettingsAIState> {
final UserListener _userListener; final UserListener _userListener;
final UserProfilePB userProfile; final UserProfilePB userProfile;
final UserBackendService _userService; final UserBackendService _userService;
final String workspaceId;
@override @override
Future<void> close() async { Future<void> close() async {
@ -92,7 +96,7 @@ class SettingsAIBloc extends Bloc<SettingsAIEvent, SettingsAIState> {
AIModelPB? model, AIModelPB? model,
}) { }) {
final payload = UpdateUserWorkspaceSettingPB( final payload = UpdateUserWorkspaceSettingPB(
workspaceId: userProfile.workspaceId, workspaceId: workspaceId,
); );
if (disableSearchIndexing != null) { if (disableSearchIndexing != null) {
payload.disableSearchIndexing = disableSearchIndexing; payload.disableSearchIndexing = disableSearchIndexing;
@ -112,7 +116,7 @@ class SettingsAIBloc extends Bloc<SettingsAIEvent, SettingsAIState> {
); );
void _loadUserWorkspaceSetting() { void _loadUserWorkspaceSetting() {
final payload = UserWorkspaceIdPB(workspaceId: userProfile.workspaceId); final payload = UserWorkspaceIdPB(workspaceId: workspaceId);
UserEventGetWorkspaceSetting(payload).send().then((result) { UserEventGetWorkspaceSetting(payload).send().then((result) {
result.fold((settings) { result.fold((settings) {
if (!isClosed) { if (!isClosed) {
@ -133,7 +137,8 @@ class SettingsAIEvent with _$SettingsAIEvent {
) = _DidLoadWorkspaceSetting; ) = _DidLoadWorkspaceSetting;
const factory SettingsAIEvent.toggleAISearch() = _toggleAISearch; const factory SettingsAIEvent.toggleAISearch() = _toggleAISearch;
const factory SettingsAIEvent.refreshMember(WorkspaceMemberPB member) = _RefreshMember; const factory SettingsAIEvent.refreshMember(WorkspaceMemberPB member) =
_RefreshMember;
const factory SettingsAIEvent.selectModel(AIModelPB model) = _SelectAIModel; const factory SettingsAIEvent.selectModel(AIModelPB model) = _SelectAIModel;

View File

@ -6,7 +6,6 @@ import 'package:appflowy/workspace/presentation/settings/pages/setting_ai_view/m
import 'package:appflowy/workspace/presentation/settings/widgets/setting_appflowy_cloud.dart'; import 'package:appflowy/workspace/presentation/settings/widgets/setting_appflowy_cloud.dart';
import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra/theme_extension.dart';
import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
@ -40,15 +39,17 @@ class SettingsAIView extends StatelessWidget {
super.key, super.key,
required this.userProfile, required this.userProfile,
required this.member, required this.member,
required this.workspaceId,
}); });
final UserProfilePB userProfile; final UserProfilePB userProfile;
final WorkspaceMemberPB? member; final WorkspaceMemberPB? member;
final String workspaceId;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider<SettingsAIBloc>( return BlocProvider<SettingsAIBloc>(
create: (_) => SettingsAIBloc(userProfile, member) create: (_) => SettingsAIBloc(userProfile, workspaceId, member)
..add(const SettingsAIEvent.started()), ..add(const SettingsAIEvent.started()),
child: BlocBuilder<SettingsAIBloc, SettingsAIState>( child: BlocBuilder<SettingsAIBloc, SettingsAIState>(
builder: (context, state) { builder: (context, state) {
@ -63,6 +64,7 @@ class SettingsAIView extends StatelessWidget {
_LocalAIOnBoarding( _LocalAIOnBoarding(
userProfile: userProfile, userProfile: userProfile,
member: state.member!, member: state.member!,
workspaceId: workspaceId,
), ),
); );
} }
@ -127,9 +129,11 @@ class _LocalAIOnBoarding extends StatelessWidget {
const _LocalAIOnBoarding({ const _LocalAIOnBoarding({
required this.userProfile, required this.userProfile,
required this.member, required this.member,
required this.workspaceId,
}); });
final UserProfilePB userProfile; final UserProfilePB userProfile;
final WorkspaceMemberPB member; final WorkspaceMemberPB member;
final String workspaceId;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -137,12 +141,13 @@ class _LocalAIOnBoarding extends StatelessWidget {
return BillingGateGuard( return BillingGateGuard(
builder: (context) { builder: (context) {
return BlocProvider( return BlocProvider(
create: (context) => LocalAIOnBoardingBloc(userProfile) create: (context) =>
..add(const LocalAIOnBoardingEvent.started()), LocalAIOnBoardingBloc(userProfile, member, workspaceId)
..add(const LocalAIOnBoardingEvent.started()),
child: BlocBuilder<LocalAIOnBoardingBloc, LocalAIOnBoardingState>( child: BlocBuilder<LocalAIOnBoardingBloc, LocalAIOnBoardingState>(
builder: (context, state) { builder: (context, state) {
// Show the local AI settings if the user has purchased the AI Local plan // Show the local AI settings if the user has purchased the AI Local plan
if (kDebugMode || state.isPurchaseAILocal) { if (state.isPurchaseAILocal) {
return const LocalAISetting(); return const LocalAISetting();
} else { } else {
if (member.role.isOwner) { if (member.role.isOwner) {

View File

@ -120,7 +120,11 @@ class SettingsDialog extends StatelessWidget {
return const SettingsShortcutsView(); return const SettingsShortcutsView();
case SettingsPage.ai: case SettingsPage.ai:
if (user.authenticator == AuthenticatorPB.AppFlowyCloud) { if (user.authenticator == AuthenticatorPB.AppFlowyCloud) {
return SettingsAIView(userProfile: user, member: member); return SettingsAIView(
userProfile: user,
member: member,
workspaceId: workspaceId,
);
} else { } else {
return const AIFeatureOnlySupportedWhenUsingAppFlowyCloud(); return const AIFeatureOnlySupportedWhenUsingAppFlowyCloud();
} }

View File

@ -38,19 +38,18 @@ async fn af_cloud_add_workspace_member_test() {
user_localhost_af_cloud().await; user_localhost_af_cloud().await;
let test_1 = EventIntegrationTest::new().await; let test_1 = EventIntegrationTest::new().await;
let user_1 = test_1.af_cloud_sign_up().await; let user_1 = test_1.af_cloud_sign_up().await;
let workspace_id_1 = test_1.get_current_workspace().await.id;
let test_2 = EventIntegrationTest::new().await; let test_2 = EventIntegrationTest::new().await;
let user_2 = test_2.af_cloud_sign_up().await; let user_2 = test_2.af_cloud_sign_up().await;
let members = test_1.get_workspace_members(&user_1.workspace_id).await; let members = test_1.get_workspace_members(&workspace_id_1).await;
assert_eq!(members.len(), 1); assert_eq!(members.len(), 1);
assert_eq!(members[0].email, user_1.email); assert_eq!(members[0].email, user_1.email);
test_1 test_1.add_workspace_member(&workspace_id_1, &test_2).await;
.add_workspace_member(&user_1.workspace_id, &test_2)
.await;
let members = test_1.get_workspace_members(&user_1.workspace_id).await; let members = test_1.get_workspace_members(&workspace_id_1).await;
assert_eq!(members.len(), 2); assert_eq!(members.len(), 2);
assert_eq!(members[0].email, user_1.email); assert_eq!(members[0].email, user_1.email);
assert_eq!(members[1].email, user_2.email); assert_eq!(members[1].email, user_2.email);
@ -61,19 +60,18 @@ async fn af_cloud_delete_workspace_member_test() {
user_localhost_af_cloud().await; user_localhost_af_cloud().await;
let test_1 = EventIntegrationTest::new().await; let test_1 = EventIntegrationTest::new().await;
let user_1 = test_1.af_cloud_sign_up().await; let user_1 = test_1.af_cloud_sign_up().await;
let workspace_id_1 = test_1.get_current_workspace().await.id;
let test_2 = EventIntegrationTest::new().await; let test_2 = EventIntegrationTest::new().await;
let user_2 = test_2.af_cloud_sign_up().await; let user_2 = test_2.af_cloud_sign_up().await;
test_1 test_1.add_workspace_member(&workspace_id_1, &test_2).await;
.add_workspace_member(&user_1.workspace_id, &test_2)
.await;
test_1 test_1
.delete_workspace_member(&user_1.workspace_id, &user_2.email) .delete_workspace_member(&workspace_id_1, &user_2.email)
.await; .await;
let members = test_1.get_workspace_members(&user_1.workspace_id).await; let members = test_1.get_workspace_members(&workspace_id_1).await;
assert_eq!(members.len(), 1); assert_eq!(members.len(), 1);
assert_eq!(members[0].email, user_1.email); assert_eq!(members[0].email, user_1.email);
} }
@ -82,21 +80,20 @@ async fn af_cloud_delete_workspace_member_test() {
async fn af_cloud_leave_workspace_test() { async fn af_cloud_leave_workspace_test() {
user_localhost_af_cloud().await; user_localhost_af_cloud().await;
let test_1 = EventIntegrationTest::new().await; let test_1 = EventIntegrationTest::new().await;
let user_1 = test_1.af_cloud_sign_up().await; test_1.af_cloud_sign_up().await;
let workspace_id_1 = test_1.get_current_workspace().await.id;
let test_2 = EventIntegrationTest::new().await; let test_2 = EventIntegrationTest::new().await;
let user_2 = test_2.af_cloud_sign_up().await; let user_2 = test_2.af_cloud_sign_up().await;
test_1 test_1.add_workspace_member(&workspace_id_1, &test_2).await;
.add_workspace_member(&user_1.workspace_id, &test_2)
.await;
// test_2 should have 2 workspace // test_2 should have 2 workspace
let workspaces = get_synced_workspaces(&test_2, user_2.id).await; let workspaces = get_synced_workspaces(&test_2, user_2.id).await;
assert_eq!(workspaces.len(), 2); assert_eq!(workspaces.len(), 2);
// user_2 leaves the workspace // user_2 leaves the workspace
test_2.leave_workspace(&user_1.workspace_id).await; test_2.leave_workspace(&workspace_id_1).await;
// user_2 should have 1 workspace // user_2 should have 1 workspace
let workspaces = get_synced_workspaces(&test_2, user_2.id).await; let workspaces = get_synced_workspaces(&test_2, user_2.id).await;

View File

@ -163,9 +163,6 @@ async fn af_cloud_different_open_same_workspace_test() {
let owner_profile = test_runner.af_cloud_sign_up().await; let owner_profile = test_runner.af_cloud_sign_up().await;
let shared_workspace_id = test_runner.get_current_workspace().await.id.clone(); let shared_workspace_id = test_runner.get_current_workspace().await.id.clone();
// Verify that the workspace ID from the profile matches the current session's workspace ID.
assert_eq!(shared_workspace_id, owner_profile.workspace_id);
// Define the number of additional clients // Define the number of additional clients
let num_clients = 5; let num_clients = 5;
let mut clients = Vec::new(); let mut clients = Vec::new();
@ -183,7 +180,7 @@ async fn af_cloud_different_open_same_workspace_test() {
} }
test_runner test_runner
.add_workspace_member(&owner_profile.workspace_id, &client) .add_workspace_member(&shared_workspace_id, &client)
.await; .await;
clients.push((client, client_profile)); clients.push((client, client_profile));
} }

View File

@ -26,7 +26,6 @@ async fn anon_user_profile_get() {
assert_eq!(user_profile.id, user.id); assert_eq!(user_profile.id, user.id);
assert_eq!(user_profile.openai_key, user.openai_key); assert_eq!(user_profile.openai_key, user.openai_key);
assert_eq!(user_profile.stability_ai_key, user.stability_ai_key); assert_eq!(user_profile.stability_ai_key, user.stability_ai_key);
assert_eq!(user_profile.workspace_id, user.workspace_id);
assert_eq!(user_profile.authenticator, AuthenticatorPB::Local); assert_eq!(user_profile.authenticator, AuthenticatorPB::Local);
} }

View File

@ -351,7 +351,7 @@ impl Chat {
{ {
Ok(resp) => { Ok(resp) => {
// Save chat messages to local disk // Save chat messages to local disk
if let Err(err) = save_chat_message( if let Err(err) = save_chat_message_disk(
user_service.sqlite_connection(uid)?, user_service.sqlite_connection(uid)?,
&chat_id, &chat_id,
resp.messages.clone(), resp.messages.clone(),
@ -503,7 +503,7 @@ impl Chat {
} }
} }
fn save_chat_message( fn save_chat_message_disk(
conn: DBConnection, conn: DBConnection,
chat_id: &str, chat_id: &str,
messages: Vec<ChatMessage>, messages: Vec<ChatMessage>,
@ -565,7 +565,7 @@ pub(crate) fn save_and_notify_message(
message: ChatMessage, message: ChatMessage,
) -> Result<(), FlowyError> { ) -> Result<(), FlowyError> {
trace!("[Chat] save answer: answer={:?}", message); trace!("[Chat] save answer: answer={:?}", message);
save_chat_message( save_chat_message_disk(
user_service.sqlite_connection(uid)?, user_service.sqlite_connection(uid)?,
chat_id, chat_id,
vec![message.clone()], vec![message.clone()],

View File

@ -53,12 +53,9 @@ pub struct UserProfilePB {
pub encryption_type: EncryptionTypePB, pub encryption_type: EncryptionTypePB,
#[pb(index = 10)] #[pb(index = 10)]
pub workspace_id: String,
#[pb(index = 11)]
pub stability_ai_key: String, pub stability_ai_key: String,
#[pb(index = 12)] #[pb(index = 11)]
pub ai_model: AIModelPB, pub ai_model: AIModelPB,
} }
@ -90,7 +87,6 @@ impl From<UserProfile> for UserProfilePB {
authenticator: user_profile.authenticator.into(), authenticator: user_profile.authenticator.into(),
encryption_sign, encryption_sign,
encryption_type: encryption_ty, encryption_type: encryption_ty,
workspace_id: user_profile.workspace_id,
stability_ai_key: user_profile.stability_ai_key, stability_ai_key: user_profile.stability_ai_key,
ai_model: AIModelPB::from_str(&user_profile.ai_model).unwrap_or_default(), ai_model: AIModelPB::from_str(&user_profile.ai_model).unwrap_or_default(),
} }