From 4354227a0528947b8c87955947191df09b2c0083 Mon Sep 17 00:00:00 2001 From: Nathan Date: Wed, 7 May 2025 14:31:08 +0800 Subject: [PATCH] chore: enable select source when user is not anon --- .../prompt_input/desktop_prompt_input.dart | 15 +++- .../ai_chat/application/chat_user_cubit.dart | 78 +++++++++++++++++++ .../tests/chat/local_chat_test.rs | 1 - .../event-integration-test/tests/chat/mod.rs | 1 - 4 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_user_cubit.dart delete mode 100644 frontend/rust-lib/event-integration-test/tests/chat/local_chat_test.rs diff --git a/frontend/appflowy_flutter/lib/ai/widgets/prompt_input/desktop_prompt_input.dart b/frontend/appflowy_flutter/lib/ai/widgets/prompt_input/desktop_prompt_input.dart index 288110c5f2..1c79f6dbf0 100644 --- a/frontend/appflowy_flutter/lib/ai/widgets/prompt_input/desktop_prompt_input.dart +++ b/frontend/appflowy_flutter/lib/ai/widgets/prompt_input/desktop_prompt_input.dart @@ -1,5 +1,6 @@ import 'package:appflowy/ai/ai.dart'; import 'package:appflowy/plugins/ai_chat/application/chat_input_control_cubit.dart'; +import 'package:appflowy/plugins/ai_chat/application/chat_user_cubit.dart'; import 'package:appflowy/plugins/ai_chat/presentation/layout_define.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/util/theme_extension.dart'; @@ -47,6 +48,7 @@ class _DesktopPromptInputState extends State { final layerLink = LayerLink(); final overlayController = OverlayPortalController(); final inputControlCubit = ChatInputControlCubit(); + final chatUserCubit = ChatUserCubit(); final focusNode = FocusNode(); late SendButtonState sendButtonState; @@ -55,6 +57,7 @@ class _DesktopPromptInputState extends State { @override void initState() { super.initState(); + chatUserCubit.fetchUserProfile(); widget.textController.addListener(handleTextControllerChanged); focusNode @@ -88,13 +91,17 @@ class _DesktopPromptInputState extends State { focusNode.dispose(); widget.textController.removeListener(handleTextControllerChanged); inputControlCubit.close(); + chatUserCubit.close(); super.dispose(); } @override Widget build(BuildContext context) { - return BlocProvider.value( - value: inputControlCubit, + return MultiBlocProvider( + providers: [ + BlocProvider.value(value: inputControlCubit), + BlocProvider.value(value: chatUserCubit), + ], child: BlocListener( listener: (context, state) { state.maybeWhen( @@ -634,7 +641,9 @@ class _PromptBottomActions extends StatelessWidget { const Spacer(), - _selectSourcesButton(), + if (context.read().supportSelectSource()) + _selectSourcesButton(), + if (extraBottomActionButton != null) extraBottomActionButton!, // _mentionButton(context), if (state.supportChatWithFile) _attachmentButton(context), diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_user_cubit.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_user_cubit.dart new file mode 100644 index 0000000000..da21875078 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_user_cubit.dart @@ -0,0 +1,78 @@ +import 'package:appflowy/startup/startup.dart'; +import 'package:appflowy/user/application/auth/auth_service.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-user/workspace.pb.dart'; +import 'package:equatable/equatable.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +/// ChatUserCubit is responsible for fetching and storing the user profile +class ChatUserCubit extends Cubit { + ChatUserCubit() : super(ChatUserLoadingState()) { + fetchUserProfile(); + } + + /// Fetches the user profile from the AuthService + Future fetchUserProfile() async { + emit(ChatUserLoadingState()); + final userOrFailure = await getIt().getUser(); + + userOrFailure.fold( + (userProfile) => emit(ChatUserSuccessState(userProfile)), + (error) => emit(ChatUserFailureState(error)), + ); + } + + bool supportSelectSource() { + if (state is ChatUserSuccessState) { + final userProfile = (state as ChatUserSuccessState).userProfile; + if (userProfile.userAuthType == AuthTypePB.Server) { + return true; + } + } + return false; + } + + bool isValueWorkspace() { + if (state is ChatUserSuccessState) { + final userProfile = (state as ChatUserSuccessState).userProfile; + return userProfile.workspaceType == WorkspaceTypePB.LocalW && + userProfile.userAuthType != AuthTypePB.Local; + } + return false; + } + + /// Refreshes the user profile data + Future refresh() async { + await fetchUserProfile(); + } +} + +/// Base state class for ChatUserCubit +abstract class ChatUserState extends Equatable { + const ChatUserState(); + + @override + List get props => []; +} + +/// Loading state when fetching user profile +class ChatUserLoadingState extends ChatUserState {} + +/// Success state when user profile is fetched successfully +class ChatUserSuccessState extends ChatUserState { + const ChatUserSuccessState(this.userProfile); + final UserProfilePB userProfile; + + @override + List get props => [userProfile]; +} + +/// Failure state when fetching user profile fails +class ChatUserFailureState extends ChatUserState { + const ChatUserFailureState(this.error); + final FlowyError error; + + @override + List get props => [error]; +} diff --git a/frontend/rust-lib/event-integration-test/tests/chat/local_chat_test.rs b/frontend/rust-lib/event-integration-test/tests/chat/local_chat_test.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/frontend/rust-lib/event-integration-test/tests/chat/local_chat_test.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/rust-lib/event-integration-test/tests/chat/mod.rs b/frontend/rust-lib/event-integration-test/tests/chat/mod.rs index 7203432c70..773bdab81f 100644 --- a/frontend/rust-lib/event-integration-test/tests/chat/mod.rs +++ b/frontend/rust-lib/event-integration-test/tests/chat/mod.rs @@ -1,2 +1 @@ mod chat_message_test; -mod local_chat_test;