From 36d8a326707abd580805b2759f9d495401f97d84 Mon Sep 17 00:00:00 2001 From: Richard Shiue <71320345+richardshiue@users.noreply.github.com> Date: Thu, 26 Dec 2024 14:41:03 +0800 Subject: [PATCH] chore: implement ui --- .../ai_chat/application/chat_bloc.dart | 3 ++ .../chat_select_sources_cubit.dart | 8 +++++ .../lib/plugins/ai_chat/chat_page.dart | 22 +++++++++---- .../chat_input/desktop_ai_prompt_input.dart | 4 +-- .../chat_input/select_sources_menu.dart | 31 +++++++++++++++++-- frontend/resources/translations/en.json | 3 +- 6 files changed, 60 insertions(+), 11 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart index 08d3d7063a650..63e13aa4321e4 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart @@ -259,6 +259,7 @@ class ChatBloc extends Bloc { .onFailure(Log.error); }, setRagOnly: (ragOnly) async { + emit(state.copyWith(onlyUseSelectedSources: ragOnly)); final payload = UpdateChatSettingsPB.create() ..chatId = ChatId(value: chatId) ..ragOnly = ragOnly; @@ -624,12 +625,14 @@ class ChatEvent with _$ChatEvent { @freezed class ChatState with _$ChatState { const factory ChatState({ + required bool onlyUseSelectedSources, required List selectedSourceIds, required LoadChatMessageStatus loadingState, required PromptResponseState promptResponseState, }) = _ChatState; factory ChatState.initial() => const ChatState( + onlyUseSelectedSources: false, selectedSourceIds: [], loadingState: LoadChatMessageStatus.loading, promptResponseState: PromptResponseState.ready, diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_select_sources_cubit.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_select_sources_cubit.dart index 06ead7d8d8134..25dd7f7e39213 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_select_sources_cubit.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_select_sources_cubit.dart @@ -107,6 +107,12 @@ class ChatSettingsCubit extends Cubit { List selectedSources = []; String filter = ''; + void updateOnlyUseSelectedSources(bool onlyUseSelectedSources) { + if (state.onlyUseSelectedSources != onlyUseSelectedSources) { + emit(state.copyWith(onlyUseSelectedSources: onlyUseSelectedSources)); + } + } + void updateSelectedSources(List newSelectedSourceIds) { selectedSourceIds = [...newSelectedSourceIds]; } @@ -380,11 +386,13 @@ class ChatSettingsCubit extends Cubit { @freezed class ChatSettingsState with _$ChatSettingsState { const factory ChatSettingsState({ + required bool onlyUseSelectedSources, required List visibleSources, required List selectedSources, }) = _ChatSettingsState; factory ChatSettingsState.initial() => const ChatSettingsState( + onlyUseSelectedSources: false, visibleSources: [], selectedSources: [], ); diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index dc6d9c649ce7a..626be04eb47ae 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -9,6 +9,7 @@ import 'package:appflowy_result/appflowy_result.dart'; import 'package:desktop_drop/desktop_drop.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_chat_core/flutter_chat_core.dart'; @@ -296,12 +297,21 @@ class _ChatContentPage extends StatelessWidget { ), ); }, - onUpdateSelectedSources: (ids) { - chatBloc.add( - ChatEvent.updateSelectedSources( - selectedSourcesIds: ids, - ), - ); + onUpdateSelectedSources: (ragOnly, ids) { + if (ragOnly != chatBloc.state.onlyUseSelectedSources) { + chatBloc.add( + ChatEvent.setRagOnly( + ragOnly: ragOnly, + ), + ); + } + if (!listEquals(ids, chatBloc.state.selectedSourceIds)) { + chatBloc.add( + ChatEvent.updateSelectedSources( + selectedSourcesIds: ids, + ), + ); + } }, ) : MobileAIPromptInput( diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/desktop_ai_prompt_input.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/desktop_ai_prompt_input.dart index a44f446433f99..e9146fceea9ea 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/desktop_ai_prompt_input.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/desktop_ai_prompt_input.dart @@ -32,7 +32,7 @@ class DesktopAIPromptInput extends StatefulWidget { final bool isStreaming; final void Function() onStopStreaming; final void Function(String, Map) onSubmitted; - final void Function(List) onUpdateSelectedSources; + final void Function(bool, List) onUpdateSelectedSources; @override State createState() => _DesktopAIPromptInputState(); @@ -497,7 +497,7 @@ class _PromptBottomActions extends StatelessWidget { final SendButtonState sendButtonState; final void Function() onSendPressed; final void Function() onStopStreaming; - final void Function(List) onUpdateSelectedSources; + final void Function(bool, List) onUpdateSelectedSources; @override Widget build(BuildContext context) { diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/select_sources_menu.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/select_sources_menu.dart index 47cfec9b4ae14..a1d221ae2280d 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/select_sources_menu.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/select_sources_menu.dart @@ -27,7 +27,7 @@ class PromptInputDesktopSelectSourcesButton extends StatefulWidget { required this.onUpdateSelectedSources, }); - final void Function(List) onUpdateSelectedSources; + final void Function(bool, List) onUpdateSelectedSources; @override State createState() => @@ -80,6 +80,7 @@ class _PromptInputDesktopSelectSourcesButtonState return BlocListener( listener: (context, state) { cubit + ..updateOnlyUseSelectedSources(state.onlyUseSelectedSources) ..updateSelectedSources(state.selectedSourceIds) ..updateSelectedStatus(); }, @@ -95,7 +96,10 @@ class _PromptInputDesktopSelectSourcesButtonState } }, onClose: () { - widget.onUpdateSelectedSources(cubit.selectedSourceIds); + widget.onUpdateSelectedSources( + cubit.state.onlyUseSelectedSources, + cubit.selectedSourceIds, + ); if (spaceView != null) { context.read().refreshSources(spaceView); } @@ -188,6 +192,29 @@ class _PopoverContent extends StatelessWidget { context.read().updateFilter(value), ), ), + Container( + margin: const EdgeInsets.fromLTRB(8, 0, 8, 8), + height: 30, + child: FlowyButton( + text: FlowyText( + LocaleKeys.chat_onlyUseRags.tr(), + overflow: TextOverflow.ellipsis, + ), + onTap: () { + context + .read() + .updateOnlyUseSelectedSources( + !state.onlyUseSelectedSources, + ); + }, + rightIcon: state.onlyUseSelectedSources + ? FlowySvg( + FlowySvgs.check_s, + color: Theme.of(context).colorScheme.primary, + ) + : null, + ), + ), _buildDivider(), Flexible( child: ListView( diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index 6cc508ed4aa50..2eb651c99782f 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -212,7 +212,8 @@ "addToPageButton": "Add to page", "addToPageTitle": "Add message to...", "addToNewPage": "Add to a new page", - "addToNewPageName": "Messages extracted from \"{}\"" + "addToNewPageName": "Messages extracted from \"{}\"", + "onlyUseRags": "Only use selected sources to generate response" }, "trash": { "text": "Trash",