mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-07-26 03:23:01 +00:00
chore: loading for search summary
This commit is contained in:
@ -94,15 +94,16 @@ class CommandPaletteBloc
|
||||
emit(
|
||||
state.copyWith(
|
||||
query: null,
|
||||
isLoading: false,
|
||||
searching: false,
|
||||
serverResponseItems: [],
|
||||
localResponseItems: [],
|
||||
combinedResponseItems: {},
|
||||
resultSummaries: [],
|
||||
generatingAIOverview: false,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
emit(state.copyWith(query: event.search, isLoading: true));
|
||||
emit(state.copyWith(query: event.search, searching: true));
|
||||
_activeQuery = event.search;
|
||||
|
||||
unawaited(
|
||||
@ -122,7 +123,8 @@ class CommandPaletteBloc
|
||||
add(
|
||||
CommandPaletteEvent.resultsChanged(
|
||||
searchId: '',
|
||||
isLoading: false,
|
||||
searching: false,
|
||||
generatingAIOverview: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -150,19 +152,23 @@ class CommandPaletteBloc
|
||||
searchId: searchId,
|
||||
localItems: items,
|
||||
),
|
||||
onServerItems: (items, searchId, isLoading) => _handleResultsUpdate(
|
||||
onServerItems: (items, searchId, searching, generatingAIOverview) =>
|
||||
_handleResultsUpdate(
|
||||
searchId: searchId,
|
||||
serverItems: items,
|
||||
isLoading: isLoading,
|
||||
searching: searching,
|
||||
generatingAIOverview: generatingAIOverview,
|
||||
),
|
||||
onSummaries: (summaries, searchId, isLoading) => _handleResultsUpdate(
|
||||
onSummaries: (summaries, searchId, searching, generatingAIOverview) =>
|
||||
_handleResultsUpdate(
|
||||
searchId: searchId,
|
||||
summaries: summaries,
|
||||
isLoading: isLoading,
|
||||
searching: searching,
|
||||
generatingAIOverview: generatingAIOverview,
|
||||
),
|
||||
onFinished: (searchId) => _handleResultsUpdate(
|
||||
searchId: searchId,
|
||||
isLoading: false,
|
||||
searching: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -172,7 +178,8 @@ class CommandPaletteBloc
|
||||
List<SearchResponseItemPB>? serverItems,
|
||||
List<LocalSearchResponseItemPB>? localItems,
|
||||
List<SearchSummaryPB>? summaries,
|
||||
bool isLoading = true,
|
||||
bool searching = true,
|
||||
bool generatingAIOverview = false,
|
||||
}) {
|
||||
if (_isActiveSearch(searchId)) {
|
||||
add(
|
||||
@ -181,7 +188,8 @@ class CommandPaletteBloc
|
||||
serverItems: serverItems,
|
||||
localItems: localItems,
|
||||
summaries: summaries,
|
||||
isLoading: isLoading,
|
||||
searching: searching,
|
||||
generatingAIOverview: generatingAIOverview,
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -223,7 +231,8 @@ class CommandPaletteBloc
|
||||
localResponseItems: event.localItems ?? state.localResponseItems,
|
||||
resultSummaries: event.summaries ?? state.resultSummaries,
|
||||
combinedResponseItems: combinedItems,
|
||||
isLoading: event.isLoading,
|
||||
searching: event.searching,
|
||||
generatingAIOverview: event.generatingAIOverview,
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -256,7 +265,8 @@ class CommandPaletteBloc
|
||||
localResponseItems: [],
|
||||
combinedResponseItems: {},
|
||||
resultSummaries: [],
|
||||
isLoading: false,
|
||||
searching: false,
|
||||
generatingAIOverview: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -283,7 +293,8 @@ class CommandPaletteEvent with _$CommandPaletteEvent {
|
||||
}) = _NewSearchStream;
|
||||
const factory CommandPaletteEvent.resultsChanged({
|
||||
required String searchId,
|
||||
required bool isLoading,
|
||||
required bool searching,
|
||||
required bool generatingAIOverview,
|
||||
List<SearchResponseItemPB>? serverItems,
|
||||
List<LocalSearchResponseItemPB>? localItems,
|
||||
List<SearchSummaryPB>? summaries,
|
||||
@ -324,12 +335,14 @@ class CommandPaletteState with _$CommandPaletteState {
|
||||
@Default({}) Map<String, SearchResultItem> combinedResponseItems,
|
||||
@Default([]) List<SearchSummaryPB> resultSummaries,
|
||||
@Default(null) SearchResponseStream? searchResponseStream,
|
||||
required bool isLoading,
|
||||
required bool searching,
|
||||
required bool generatingAIOverview,
|
||||
@Default([]) List<TrashPB> trash,
|
||||
@Default(null) String? searchId,
|
||||
}) = _CommandPaletteState;
|
||||
|
||||
factory CommandPaletteState.initial() => const CommandPaletteState(
|
||||
isLoading: false,
|
||||
searching: false,
|
||||
generatingAIOverview: false,
|
||||
);
|
||||
}
|
||||
|
@ -49,12 +49,14 @@ class SearchResponseStream {
|
||||
void Function(
|
||||
List<SearchResponseItemPB> items,
|
||||
String searchId,
|
||||
bool isLoading,
|
||||
bool searching,
|
||||
bool generatingAIOverview,
|
||||
)? _onServerItems;
|
||||
void Function(
|
||||
List<SearchSummaryPB> summaries,
|
||||
String searchId,
|
||||
bool isLoading,
|
||||
bool searching,
|
||||
bool generatingAIOverview,
|
||||
)? _onSummaries;
|
||||
|
||||
void Function(
|
||||
@ -78,14 +80,16 @@ class SearchResponseStream {
|
||||
_onServerItems?.call(
|
||||
searchState.response.searchResult.items,
|
||||
searchId,
|
||||
searchState.isLoading,
|
||||
searchState.response.searching,
|
||||
searchState.response.generatingAiSummary,
|
||||
);
|
||||
}
|
||||
if (searchState.response.hasSearchSummary()) {
|
||||
_onSummaries?.call(
|
||||
searchState.response.searchSummary.items,
|
||||
searchId,
|
||||
searchState.isLoading,
|
||||
searchState.response.searching,
|
||||
searchState.response.generatingAiSummary,
|
||||
);
|
||||
}
|
||||
|
||||
@ -105,11 +109,13 @@ class SearchResponseStream {
|
||||
List<SearchResponseItemPB> items,
|
||||
String searchId,
|
||||
bool isLoading,
|
||||
bool generatingAIOverview,
|
||||
)? onServerItems,
|
||||
required void Function(
|
||||
List<SearchSummaryPB> summaries,
|
||||
String searchId,
|
||||
bool isLoading,
|
||||
bool generatingAIOverview,
|
||||
)? onSummaries,
|
||||
required void Function(
|
||||
List<LocalSearchResponseItemPB> items,
|
||||
|
@ -144,7 +144,7 @@ class CommandPaletteModal extends StatelessWidget {
|
||||
// Change mainAxisSize to max so Expanded works correctly.
|
||||
Column(
|
||||
children: [
|
||||
SearchField(query: state.query, isLoading: state.isLoading),
|
||||
SearchField(query: state.query, isLoading: state.searching),
|
||||
if (state.query?.isEmpty ?? true) ...[
|
||||
const Divider(height: 0),
|
||||
Flexible(
|
||||
@ -167,7 +167,7 @@ class CommandPaletteModal extends StatelessWidget {
|
||||
// When there are no results and the query is not empty and not loading,
|
||||
// show the no results message, centered in the available space.
|
||||
else if ((state.query?.isNotEmpty ?? false) &&
|
||||
!state.isLoading) ...[
|
||||
!state.searching) ...[
|
||||
const Divider(height: 0),
|
||||
Expanded(
|
||||
child: const _NoResultsHint(),
|
||||
|
@ -207,9 +207,12 @@ class SearchResultPreview extends StatelessWidget {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
FlowyText(LocaleKeys.commandPalette_pagePreview.tr()),
|
||||
const Divider(
|
||||
thickness: 1,
|
||||
Opacity(
|
||||
opacity: 0.5,
|
||||
child: FlowyText(
|
||||
LocaleKeys.commandPalette_pagePreview.tr(),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
const VSpace(6),
|
||||
Expanded(
|
||||
|
@ -3,6 +3,7 @@ import 'package:appflowy/workspace/application/action_navigation/action_navigati
|
||||
import 'package:appflowy/workspace/application/action_navigation/navigation_action.dart';
|
||||
import 'package:appflowy/workspace/application/command_palette/command_palette_bloc.dart';
|
||||
import 'package:appflowy/workspace/application/command_palette/search_result_list_bloc.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
@ -11,6 +12,7 @@ import 'package:appflowy_backend/protobuf/flowy-search/result.pb.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_animate/flutter_animate.dart';
|
||||
|
||||
import 'search_result_cell.dart';
|
||||
import 'search_summary_cell.dart';
|
||||
@ -35,22 +37,37 @@ class SearchResultList extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
|
||||
Widget _buildSummariesSection() {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildSectionHeader(LocaleKeys.commandPalette_aiOverview.tr()),
|
||||
ListView.separated(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
itemCount: resultSummaries.length,
|
||||
separatorBuilder: (_, __) => const Divider(height: 0),
|
||||
itemBuilder: (_, index) => SearchSummaryCell(
|
||||
summary: resultSummaries[index],
|
||||
Widget _buildAIOverviewSection(BuildContext context) {
|
||||
final state = context.read<CommandPaletteBloc>().state;
|
||||
|
||||
if (state.generatingAIOverview) {
|
||||
return Row(
|
||||
children: [
|
||||
_buildSectionHeader(LocaleKeys.commandPalette_aiOverview.tr()),
|
||||
const HSpace(10),
|
||||
const AIOverviewIndicator(),
|
||||
],
|
||||
);
|
||||
}
|
||||
if (resultSummaries.isNotEmpty) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildSectionHeader(LocaleKeys.commandPalette_aiOverview.tr()),
|
||||
ListView.separated(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
itemCount: resultSummaries.length,
|
||||
separatorBuilder: (_, __) => const Divider(height: 0),
|
||||
itemBuilder: (_, index) => SearchSummaryCell(
|
||||
summary: resultSummaries[index],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
Widget _buildResultsSection(BuildContext context) {
|
||||
@ -83,6 +100,8 @@ class SearchResultList extends StatelessWidget {
|
||||
child: BlocProvider(
|
||||
create: (context) => SearchResultListBloc(),
|
||||
child: BlocListener<SearchResultListBloc, SearchResultListState>(
|
||||
listenWhen: (previous, current) =>
|
||||
previous.openPageId != current.openPageId,
|
||||
listener: (context, state) {
|
||||
if (state.openPageId != null) {
|
||||
FlowyOverlay.pop(context);
|
||||
@ -102,24 +121,28 @@ class SearchResultList extends StatelessWidget {
|
||||
shrinkWrap: true,
|
||||
physics: const ClampingScrollPhysics(),
|
||||
children: [
|
||||
if (resultSummaries.isNotEmpty) _buildSummariesSection(),
|
||||
_buildAIOverviewSection(context),
|
||||
const VSpace(10),
|
||||
if (resultItems.isNotEmpty) _buildResultsSection(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
const HSpace(10),
|
||||
if (resultItems.any((item) => item.content.isNotEmpty))
|
||||
if (resultItems.any((item) => item.content.isNotEmpty)) ...[
|
||||
const VerticalDivider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
Flexible(
|
||||
flex: 3,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
horizontal: 8,
|
||||
vertical: 16,
|
||||
),
|
||||
child: const SearchCellPreview(),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -145,3 +168,69 @@ class SearchCellPreview extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AIOverviewIndicator extends StatelessWidget {
|
||||
const AIOverviewIndicator({
|
||||
super.key,
|
||||
this.duration = const Duration(seconds: 1),
|
||||
});
|
||||
|
||||
final Duration duration;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final slice = Duration(milliseconds: duration.inMilliseconds ~/ 5);
|
||||
return SelectionContainer.disabled(
|
||||
child: SizedBox(
|
||||
height: 20,
|
||||
width: 100,
|
||||
child: SeparatedRow(
|
||||
separatorBuilder: () => const HSpace(4),
|
||||
children: [
|
||||
buildDot(const Color(0xFF9327FF))
|
||||
.animate(onPlay: (controller) => controller.repeat())
|
||||
.slideY(duration: slice, begin: 0, end: -1)
|
||||
.then()
|
||||
.slideY(begin: -1, end: 1)
|
||||
.then()
|
||||
.slideY(begin: 1, end: 0)
|
||||
.then()
|
||||
.slideY(duration: slice * 2, begin: 0, end: 0),
|
||||
buildDot(const Color(0xFFFB006D))
|
||||
.animate(onPlay: (controller) => controller.repeat())
|
||||
.slideY(duration: slice, begin: 0, end: 0)
|
||||
.then()
|
||||
.slideY(begin: 0, end: -1)
|
||||
.then()
|
||||
.slideY(begin: -1, end: 1)
|
||||
.then()
|
||||
.slideY(begin: 1, end: 0)
|
||||
.then()
|
||||
.slideY(begin: 0, end: 0),
|
||||
buildDot(const Color(0xFFFFCE00))
|
||||
.animate(onPlay: (controller) => controller.repeat())
|
||||
.slideY(duration: slice * 2, begin: 0, end: 0)
|
||||
.then()
|
||||
.slideY(duration: slice, begin: 0, end: -1)
|
||||
.then()
|
||||
.slideY(begin: -1, end: 1)
|
||||
.then()
|
||||
.slideY(begin: 1, end: 0),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildDot(Color color) {
|
||||
return SizedBox.square(
|
||||
dimension: 4,
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/ai_chat/presentation/message/ai_markdown_text.dart';
|
||||
import 'package:appflowy/workspace/application/command_palette/search_result_ext.dart';
|
||||
import 'package:appflowy/workspace/application/command_palette/search_result_list_bloc.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
@ -56,17 +57,50 @@ class SearchSummaryPreview extends StatelessWidget {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
FlowyText(LocaleKeys.commandPalette_aiOverviewSource.tr()),
|
||||
const Divider(
|
||||
thickness: 1,
|
||||
if (summary.highlights.isNotEmpty) ...[
|
||||
Opacity(
|
||||
opacity: 0.5,
|
||||
child: FlowyText(
|
||||
LocaleKeys.commandPalette_aiOverviewHighlights.tr(),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
const VSpace(6),
|
||||
SearchSummaryHighlight(text: summary.highlights),
|
||||
const VSpace(36),
|
||||
],
|
||||
|
||||
Opacity(
|
||||
opacity: 0.5,
|
||||
child: FlowyText(
|
||||
LocaleKeys.commandPalette_aiOverviewSource.tr(),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
// Sources
|
||||
const VSpace(6),
|
||||
...summary.sources.map((e) => SearchSummarySource(source: e)),
|
||||
|
||||
// Highlights
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SearchSummaryHighlight extends StatelessWidget {
|
||||
const SearchSummaryHighlight({
|
||||
required this.text,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final String text;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AIMarkdownText(markdown: text);
|
||||
}
|
||||
}
|
||||
|
||||
class SearchSummarySource extends StatelessWidget {
|
||||
const SearchSummarySource({
|
||||
required this.source,
|
||||
@ -78,18 +112,21 @@ class SearchSummarySource extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final icon = source.icon.getIcon();
|
||||
return SizedBox(
|
||||
height: 30,
|
||||
child: FlowyButton(
|
||||
leftIcon: icon,
|
||||
hoverColor:
|
||||
Theme.of(context).colorScheme.primary.withValues(alpha: 0.1),
|
||||
text: FlowyText(source.displayName),
|
||||
onTap: () {
|
||||
context.read<SearchResultListBloc>().add(
|
||||
SearchResultListEvent.openPage(pageId: source.id),
|
||||
);
|
||||
},
|
||||
return FlowyTooltip(
|
||||
message: LocaleKeys.commandPalette_clickToOpenPage.tr(),
|
||||
child: SizedBox(
|
||||
height: 30,
|
||||
child: FlowyButton(
|
||||
leftIcon: icon,
|
||||
hoverColor:
|
||||
Theme.of(context).colorScheme.primary.withValues(alpha: 0.1),
|
||||
text: FlowyText(source.displayName),
|
||||
onTap: () {
|
||||
context.read<SearchResultListBloc>().add(
|
||||
SearchResultListEvent.openPage(pageId: source.id),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -2699,7 +2699,9 @@
|
||||
"bestMatches": "Best matches",
|
||||
"aiOverview": "AI overview",
|
||||
"aiOverviewSource": "Reference sources",
|
||||
"aiOverviewHighlights": "Highlights",
|
||||
"pagePreview": "Content preview",
|
||||
"clickToOpenPage": "Click to open page",
|
||||
"recentHistory": "Recent history",
|
||||
"navigateHint": "to navigate",
|
||||
"loadingTooltip": "We are looking for results...",
|
||||
|
42
frontend/rust-lib/Cargo.lock
generated
42
frontend/rust-lib/Cargo.lock
generated
@ -493,7 +493,7 @@ checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
|
||||
[[package]]
|
||||
name = "app-error"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=873415478ed58686c98df578e2c39d07ddce6773#873415478ed58686c98df578e2c39d07ddce6773"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a11b94240946fa8f0549e5cf1c6505b7fa7e0a16#a11b94240946fa8f0549e5cf1c6505b7fa7e0a16"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
@ -513,7 +513,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "appflowy-ai-client"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=873415478ed58686c98df578e2c39d07ddce6773#873415478ed58686c98df578e2c39d07ddce6773"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a11b94240946fa8f0549e5cf1c6505b7fa7e0a16#a11b94240946fa8f0549e5cf1c6505b7fa7e0a16"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@ -1159,7 +1159,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "client-api"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=873415478ed58686c98df578e2c39d07ddce6773#873415478ed58686c98df578e2c39d07ddce6773"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a11b94240946fa8f0549e5cf1c6505b7fa7e0a16#a11b94240946fa8f0549e5cf1c6505b7fa7e0a16"
|
||||
dependencies = [
|
||||
"again",
|
||||
"anyhow",
|
||||
@ -1214,7 +1214,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "client-api-entity"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=873415478ed58686c98df578e2c39d07ddce6773#873415478ed58686c98df578e2c39d07ddce6773"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a11b94240946fa8f0549e5cf1c6505b7fa7e0a16#a11b94240946fa8f0549e5cf1c6505b7fa7e0a16"
|
||||
dependencies = [
|
||||
"collab-entity",
|
||||
"collab-rt-entity",
|
||||
@ -1227,7 +1227,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "client-websocket"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=873415478ed58686c98df578e2c39d07ddce6773#873415478ed58686c98df578e2c39d07ddce6773"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a11b94240946fa8f0549e5cf1c6505b7fa7e0a16#a11b94240946fa8f0549e5cf1c6505b7fa7e0a16"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
@ -1499,7 +1499,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-rt-entity"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=873415478ed58686c98df578e2c39d07ddce6773#873415478ed58686c98df578e2c39d07ddce6773"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a11b94240946fa8f0549e5cf1c6505b7fa7e0a16#a11b94240946fa8f0549e5cf1c6505b7fa7e0a16"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
@ -1521,7 +1521,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collab-rt-protocol"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=873415478ed58686c98df578e2c39d07ddce6773#873415478ed58686c98df578e2c39d07ddce6773"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a11b94240946fa8f0549e5cf1c6505b7fa7e0a16#a11b94240946fa8f0549e5cf1c6505b7fa7e0a16"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -1786,7 +1786,7 @@ dependencies = [
|
||||
"cssparser-macros",
|
||||
"dtoa-short",
|
||||
"itoa",
|
||||
"phf 0.11.2",
|
||||
"phf 0.8.0",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
@ -1969,7 +1969,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
|
||||
[[package]]
|
||||
name = "database-entity"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=873415478ed58686c98df578e2c39d07ddce6773#873415478ed58686c98df578e2c39d07ddce6773"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a11b94240946fa8f0549e5cf1c6505b7fa7e0a16#a11b94240946fa8f0549e5cf1c6505b7fa7e0a16"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bytes",
|
||||
@ -3459,7 +3459,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gotrue"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=873415478ed58686c98df578e2c39d07ddce6773#873415478ed58686c98df578e2c39d07ddce6773"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a11b94240946fa8f0549e5cf1c6505b7fa7e0a16#a11b94240946fa8f0549e5cf1c6505b7fa7e0a16"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"getrandom 0.2.10",
|
||||
@ -3474,7 +3474,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gotrue-entity"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=873415478ed58686c98df578e2c39d07ddce6773#873415478ed58686c98df578e2c39d07ddce6773"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a11b94240946fa8f0549e5cf1c6505b7fa7e0a16#a11b94240946fa8f0549e5cf1c6505b7fa7e0a16"
|
||||
dependencies = [
|
||||
"app-error",
|
||||
"jsonwebtoken",
|
||||
@ -4098,7 +4098,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "infra"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=873415478ed58686c98df578e2c39d07ddce6773#873415478ed58686c98df578e2c39d07ddce6773"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a11b94240946fa8f0549e5cf1c6505b7fa7e0a16#a11b94240946fa8f0549e5cf1c6505b7fa7e0a16"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@ -5189,7 +5189,7 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
|
||||
dependencies = [
|
||||
"phf_macros 0.8.0",
|
||||
"phf_macros",
|
||||
"phf_shared 0.8.0",
|
||||
"proc-macro-hack",
|
||||
]
|
||||
@ -5209,7 +5209,6 @@ version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
|
||||
dependencies = [
|
||||
"phf_macros 0.11.3",
|
||||
"phf_shared 0.11.2",
|
||||
]
|
||||
|
||||
@ -5277,19 +5276,6 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_macros"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216"
|
||||
dependencies = [
|
||||
"phf_generator 0.11.2",
|
||||
"phf_shared 0.11.2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.94",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.8.0"
|
||||
@ -6784,7 +6770,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "shared-entity"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=873415478ed58686c98df578e2c39d07ddce6773#873415478ed58686c98df578e2c39d07ddce6773"
|
||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a11b94240946fa8f0549e5cf1c6505b7fa7e0a16#a11b94240946fa8f0549e5cf1c6505b7fa7e0a16"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"app-error",
|
||||
|
@ -105,8 +105,8 @@ tantivy = { version = "0.24.0" }
|
||||
# Run the script.add_workspace_members:
|
||||
# scripts/tool/update_client_api_rev.sh new_rev_id
|
||||
# ⚠️⚠️⚠️️
|
||||
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "873415478ed58686c98df578e2c39d07ddce6773" }
|
||||
client-api-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "873415478ed58686c98df578e2c39d07ddce6773" }
|
||||
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a11b94240946fa8f0549e5cf1c6505b7fa7e0a16" }
|
||||
client-api-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a11b94240946fa8f0549e5cf1c6505b7fa7e0a16" }
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 0
|
||||
|
@ -77,6 +77,12 @@ impl SearchHandler for DocumentSearchHandler {
|
||||
};
|
||||
|
||||
// Execute document search.
|
||||
yield Ok(
|
||||
CreateSearchResultPBArgs::default().searching(true)
|
||||
.build()
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
let result_items = match cloud_service.document_search(&workspace_id, query.clone()).await {
|
||||
Ok(items) => items,
|
||||
Err(e) => {
|
||||
@ -114,7 +120,9 @@ impl SearchHandler for DocumentSearchHandler {
|
||||
let search_result = RepeatedSearchResponseItemPB { items };
|
||||
yield Ok(
|
||||
CreateSearchResultPBArgs::default()
|
||||
.searching(false)
|
||||
.search_result(Some(search_result))
|
||||
.generating_ai_summary(true)
|
||||
.build()
|
||||
.unwrap(),
|
||||
);
|
||||
@ -138,7 +146,7 @@ impl SearchHandler for DocumentSearchHandler {
|
||||
})
|
||||
.collect();
|
||||
|
||||
SearchSummaryPB { content: v.content, sources }
|
||||
SearchSummaryPB { content: v.content, sources, highlights: v.highlights }
|
||||
})
|
||||
.collect();
|
||||
|
||||
@ -146,12 +154,19 @@ impl SearchHandler for DocumentSearchHandler {
|
||||
yield Ok(
|
||||
CreateSearchResultPBArgs::default()
|
||||
.search_summary(Some(summary_result))
|
||||
.generating_ai_summary(false)
|
||||
.build()
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to generate search summary: {:?}", e);
|
||||
yield Ok(
|
||||
CreateSearchResultPBArgs::default()
|
||||
.generating_ai_summary(false)
|
||||
.build()
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -8,9 +8,6 @@ pub struct SearchStatePB {
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub search_id: String,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub is_loading: bool,
|
||||
}
|
||||
|
||||
#[derive(ProtoBuf_Enum, Debug, Default)]
|
||||
|
@ -18,6 +18,14 @@ pub struct SearchResponsePB {
|
||||
#[pb(index = 3, one_of)]
|
||||
#[builder(default)]
|
||||
pub local_search_result: Option<RepeatedLocalSearchResponseItemPB>,
|
||||
|
||||
#[pb(index = 4)]
|
||||
#[builder(default)]
|
||||
pub searching: bool,
|
||||
|
||||
#[pb(index = 5)]
|
||||
#[builder(default)]
|
||||
pub generating_ai_summary: bool,
|
||||
}
|
||||
|
||||
#[derive(ProtoBuf, Default, Debug, Clone)]
|
||||
@ -33,6 +41,9 @@ pub struct SearchSummaryPB {
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub sources: Vec<SearchSourcePB>,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub highlights: String,
|
||||
}
|
||||
|
||||
#[derive(ProtoBuf, Default, Debug, Clone)]
|
||||
|
@ -93,7 +93,6 @@ impl SearchManager {
|
||||
let resp = SearchStatePB {
|
||||
response: Some(search_result),
|
||||
search_id: search_id.clone(),
|
||||
is_loading: true,
|
||||
};
|
||||
if let Ok::<Vec<u8>, _>(data) = resp.try_into() {
|
||||
if let Err(err) = clone_sink.send(data).await {
|
||||
@ -111,7 +110,6 @@ impl SearchManager {
|
||||
let resp = SearchStatePB {
|
||||
response: None,
|
||||
search_id: search_id.clone(),
|
||||
is_loading: true,
|
||||
};
|
||||
if let Ok::<Vec<u8>, _>(data) = resp.try_into() {
|
||||
let _ = clone_sink.send(data).await;
|
||||
|
Reference in New Issue
Block a user