mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-09-26 08:53:40 +00:00
fix: some mobile search LR issues (#7836)
This commit is contained in:
parent
1f54946a0e
commit
15bfdfb550
@ -36,7 +36,7 @@ void main() {
|
|||||||
expect(find.byType(MobileSearchRecentList), findsNothing);
|
expect(find.byType(MobileSearchRecentList), findsNothing);
|
||||||
expect(find.byType(MobileSearchResultList), findsOneWidget);
|
expect(find.byType(MobileSearchResultList), findsOneWidget);
|
||||||
expect(
|
expect(
|
||||||
find.text(LocaleKeys.search_noResultForSearching.tr(args: [query])),
|
find.text(LocaleKeys.search_noResultForSearching.tr()),
|
||||||
findsOneWidget,
|
findsOneWidget,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -47,9 +47,10 @@ class NotificationReminderBloc
|
|||||||
status: NotificationReminderStatus.error,
|
status: NotificationReminderStatus.error,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final layout = view!.layout;
|
final layout = view.layout;
|
||||||
|
|
||||||
if (layout.isDocumentView) {
|
if (layout.isDocumentView) {
|
||||||
final node = await _getContent(reminder);
|
final node = await _getContent(reminder);
|
||||||
|
@ -163,6 +163,7 @@ class _MobileBottomSheetEditLinkWidgetState
|
|||||||
decoration: LinkStyle.buildLinkTextFieldInputDecoration(
|
decoration: LinkStyle.buildLinkTextFieldInputDecoration(
|
||||||
LocaleKeys.document_toolbar_linkNameHint.tr(),
|
LocaleKeys.document_toolbar_linkNameHint.tr(),
|
||||||
contentPadding: EdgeInsets.all(14),
|
contentPadding: EdgeInsets.all(14),
|
||||||
|
radius: 12,
|
||||||
context,
|
context,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
|
||||||
import 'package:appflowy/workspace/application/command_palette/command_palette_bloc.dart';
|
import 'package:appflowy/workspace/application/command_palette/command_palette_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/command_palette/search_result_ext.dart';
|
import 'package:appflowy/workspace/application/command_palette/search_result_ext.dart';
|
||||||
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-search/result.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-search/result.pb.dart';
|
||||||
import 'package:appflowy_ui/appflowy_ui.dart';
|
import 'package:appflowy_ui/appflowy_ui.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@ -28,7 +25,7 @@ class MobileSearchResultCell extends StatelessWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
buildIcon(),
|
buildIcon(theme),
|
||||||
HSpace(12),
|
HSpace(12),
|
||||||
Flexible(
|
Flexible(
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -57,36 +54,17 @@ class MobileSearchResultCell extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildIcon() {
|
Widget buildIcon(AppFlowyThemeData theme) {
|
||||||
final icon = item.icon;
|
final icon = item.icon;
|
||||||
if (icon.ty == ResultIconTypePB.Emoji) {
|
if (icon.ty == ResultIconTypePB.Emoji) {
|
||||||
return icon.getIcon(size: 16.0, lineHeight: 20 / 16) ?? SizedBox.shrink();
|
|
||||||
} else {
|
|
||||||
return icon.getIcon(size: 20) ?? SizedBox.shrink();
|
return icon.getIcon(size: 20) ?? SizedBox.shrink();
|
||||||
|
} else {
|
||||||
|
return icon.getIcon(size: 20, iconColor: theme.iconColorScheme.primary) ??
|
||||||
|
SizedBox.shrink();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildPath(CommandPaletteState state, AppFlowyThemeData theme) {
|
Widget buildPath(CommandPaletteState state, AppFlowyThemeData theme) {
|
||||||
bool isInTrash = false;
|
|
||||||
for (final view in state.trash) {
|
|
||||||
if (view.id == item.id) {
|
|
||||||
isInTrash = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isInTrash) {
|
|
||||||
return Row(
|
|
||||||
children: [
|
|
||||||
const FlowySvg(FlowySvgs.trash_s, size: Size.square(20)),
|
|
||||||
const HSpace(4.0),
|
|
||||||
Text(
|
|
||||||
'${LocaleKeys.trash_text.tr()} / ${item.displayName}',
|
|
||||||
style: theme.textStyle.body
|
|
||||||
.standard(color: theme.textColorScheme.secondary),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => ViewAncestorBloc(item.id),
|
create: (context) => ViewAncestorBloc(item.id),
|
||||||
child: BlocBuilder<ViewAncestorBloc, ViewAncestorState>(
|
child: BlocBuilder<ViewAncestorBloc, ViewAncestorState>(
|
||||||
@ -105,7 +83,6 @@ class MobileSearchResultCell extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Widget buildSummary(AppFlowyThemeData theme) {
|
Widget buildSummary(AppFlowyThemeData theme) {
|
||||||
if (item.content.isEmpty) {
|
if (item.content.isEmpty) {
|
||||||
|
@ -61,24 +61,19 @@ class MobileSearchScreen extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Scaffold(
|
return Provider.value(
|
||||||
body: SafeArea(
|
|
||||||
bottom: false,
|
|
||||||
child: Provider.value(
|
|
||||||
value: userProfile,
|
value: userProfile,
|
||||||
child: MobileSearchPage(
|
child: MobileSearchPage(
|
||||||
userProfile: userProfile,
|
userProfile: userProfile,
|
||||||
workspaceLatestPB: latest,
|
workspaceLatestPB: latest,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MobileSearchPage extends StatelessWidget {
|
class MobileSearchPage extends StatefulWidget {
|
||||||
const MobileSearchPage({
|
const MobileSearchPage({
|
||||||
super.key,
|
super.key,
|
||||||
required this.userProfile,
|
required this.userProfile,
|
||||||
@ -88,32 +83,63 @@ class MobileSearchPage extends StatelessWidget {
|
|||||||
final UserProfilePB userProfile;
|
final UserProfilePB userProfile;
|
||||||
final WorkspaceLatestPB workspaceLatestPB;
|
final WorkspaceLatestPB workspaceLatestPB;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MobileSearchPage> createState() => _MobileSearchPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MobileSearchPageState extends State<MobileSearchPage> {
|
||||||
bool get enableShowAISearch =>
|
bool get enableShowAISearch =>
|
||||||
userProfile.workspaceType == WorkspaceTypePB.ServerW;
|
widget.userProfile.workspaceType == WorkspaceTypePB.ServerW;
|
||||||
|
|
||||||
|
final focusNode = FocusNode();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
focusNode.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<CommandPaletteBloc, CommandPaletteState>(
|
return BlocBuilder<CommandPaletteBloc, CommandPaletteState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return Padding(
|
return SafeArea(
|
||||||
|
child: Scaffold(
|
||||||
|
body: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
MobileSearchTextfield(
|
MobileSearchTextfield(
|
||||||
|
focusNode: focusNode,
|
||||||
hintText: enableShowAISearch
|
hintText: enableShowAISearch
|
||||||
? LocaleKeys.search_searchOrAskAI.tr()
|
? LocaleKeys.search_searchOrAskAI.tr()
|
||||||
: LocaleKeys.search_label.tr(),
|
: LocaleKeys.search_label.tr(),
|
||||||
query: state.query ?? '',
|
query: state.query ?? '',
|
||||||
onChanged: (value) => context
|
onChanged: (value) =>
|
||||||
.read<CommandPaletteBloc>()
|
context.read<CommandPaletteBloc>().add(
|
||||||
.add(CommandPaletteEvent.searchChanged(search: value)),
|
CommandPaletteEvent.searchChanged(search: value),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (enableShowAISearch)
|
if (enableShowAISearch)
|
||||||
MobileSearchAskAiEntrance(query: state.query),
|
MobileSearchAskAiEntrance(query: state.query),
|
||||||
Flexible(child: SafeArea(child: MobileSearchResult())),
|
Flexible(
|
||||||
|
child: NotificationListener(
|
||||||
|
child: MobileSearchResult(),
|
||||||
|
onNotification: (t) {
|
||||||
|
if (t is ScrollUpdateNotification) {
|
||||||
|
if (focusNode.hasFocus) {
|
||||||
|
focusNode.unfocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -6,6 +6,7 @@ import 'package:appflowy/workspace/application/command_palette/command_palette_b
|
|||||||
import 'package:appflowy/workspace/application/command_palette/search_result_list_bloc.dart';
|
import 'package:appflowy/workspace/application/command_palette/search_result_list_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/recent/recent_views_bloc.dart';
|
import 'package:appflowy/workspace/application/recent/recent_views_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/view/view_service.dart';
|
import 'package:appflowy/workspace/application/view/view_service.dart';
|
||||||
|
import 'package:appflowy_backend/log.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:appflowy_result/appflowy_result.dart';
|
import 'package:appflowy_result/appflowy_result.dart';
|
||||||
import 'package:appflowy_ui/appflowy_ui.dart';
|
import 'package:appflowy_ui/appflowy_ui.dart';
|
||||||
@ -36,13 +37,18 @@ class MobileSearchRecentList extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = AppFlowyTheme.of(context);
|
final theme = AppFlowyTheme.of(context);
|
||||||
|
final commandPaletteState = context.read<CommandPaletteBloc>().state;
|
||||||
|
|
||||||
|
final trashIdSet = commandPaletteState.trash.map((e) => e.id).toSet();
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) =>
|
create: (context) =>
|
||||||
RecentViewsBloc()..add(const RecentViewsEvent.initial()),
|
RecentViewsBloc()..add(const RecentViewsEvent.initial()),
|
||||||
child: BlocBuilder<RecentViewsBloc, RecentViewsState>(
|
child: BlocBuilder<RecentViewsBloc, RecentViewsState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final List<ViewPB> recentViews =
|
final List<ViewPB> recentViews = state.views
|
||||||
state.views.map((e) => e.item).toSet().toList();
|
.map((e) => e.item)
|
||||||
|
.where((e) => !trashIdSet.contains(e.id))
|
||||||
|
.toList();
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -115,7 +121,7 @@ class _MobileSearchResultListState extends State<MobileSearchResultList> {
|
|||||||
children: [
|
children: [
|
||||||
const VSpace(16),
|
const VSpace(16),
|
||||||
Text(
|
Text(
|
||||||
LocaleKeys.search_bestMatch.tr(),
|
LocaleKeys.commandPalette_bestMatches.tr(),
|
||||||
style: theme.textStyle.body
|
style: theme.textStyle.body
|
||||||
.enhanced(color: theme.textColorScheme.secondary),
|
.enhanced(color: theme.textColorScheme.secondary),
|
||||||
),
|
),
|
||||||
@ -130,6 +136,10 @@ class _MobileSearchResultListState extends State<MobileSearchResultList> {
|
|||||||
.fold((s) => s, (s) => null);
|
.fold((s) => s, (s) => null);
|
||||||
if (view != null && context.mounted) {
|
if (view != null && context.mounted) {
|
||||||
await _goToView(context, view);
|
await _goToView(context, view);
|
||||||
|
} else {
|
||||||
|
Log.error(
|
||||||
|
'tapping search result, view not found: ${item.id}',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: MobileSearchResultCell(
|
child: MobileSearchResultCell(
|
||||||
@ -161,12 +171,13 @@ class _MobileSearchResultListState extends State<MobileSearchResultList> {
|
|||||||
),
|
),
|
||||||
const VSpace(12),
|
const VSpace(12),
|
||||||
Text(
|
Text(
|
||||||
LocaleKeys.search_noResultForSearching.tr(args: [query]),
|
LocaleKeys.search_noResultForSearching.tr(),
|
||||||
style: theme.textStyle.body.enhanced(color: textColor),
|
style: theme.textStyle.body.enhanced(color: textColor),
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
|
textAlign: TextAlign.center,
|
||||||
LocaleKeys.search_noResultForSearchingHint.tr(),
|
LocaleKeys.search_noResultForSearchingHint.tr(),
|
||||||
style: theme.textStyle.caption.standard(color: textColor),
|
style: theme.textStyle.caption.standard(color: textColor),
|
||||||
),
|
),
|
||||||
|
@ -11,11 +11,13 @@ class MobileSearchTextfield extends StatefulWidget {
|
|||||||
this.onChanged,
|
this.onChanged,
|
||||||
required this.hintText,
|
required this.hintText,
|
||||||
required this.query,
|
required this.query,
|
||||||
|
required this.focusNode,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String hintText;
|
final String hintText;
|
||||||
final String query;
|
final String query;
|
||||||
final ValueChanged<String>? onChanged;
|
final ValueChanged<String>? onChanged;
|
||||||
|
final FocusNode focusNode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<MobileSearchTextfield> createState() => _MobileSearchTextfieldState();
|
State<MobileSearchTextfield> createState() => _MobileSearchTextfieldState();
|
||||||
@ -23,18 +25,15 @@ class MobileSearchTextfield extends StatefulWidget {
|
|||||||
|
|
||||||
class _MobileSearchTextfieldState extends State<MobileSearchTextfield> {
|
class _MobileSearchTextfieldState extends State<MobileSearchTextfield> {
|
||||||
late final TextEditingController controller;
|
late final TextEditingController controller;
|
||||||
late final FocusNode focusNode;
|
|
||||||
final ValueNotifier<bool> hasFocusValueNotifier = ValueNotifier(true);
|
final ValueNotifier<bool> hasFocusValueNotifier = ValueNotifier(true);
|
||||||
|
|
||||||
|
FocusNode get focusNode => widget.focusNode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
controller = TextEditingController(text: widget.query);
|
controller = TextEditingController(text: widget.query);
|
||||||
focusNode = FocusNode();
|
focusNode.addListener(onFocusChanged);
|
||||||
focusNode.addListener(() {
|
|
||||||
if (!mounted) return;
|
|
||||||
hasFocusValueNotifier.value = focusNode.hasFocus;
|
|
||||||
});
|
|
||||||
controller.addListener(() {
|
controller.addListener(() {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
widget.onChanged?.call(controller.text);
|
widget.onChanged?.call(controller.text);
|
||||||
@ -46,7 +45,7 @@ class _MobileSearchTextfieldState extends State<MobileSearchTextfield> {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
controller.dispose();
|
controller.dispose();
|
||||||
focusNode.dispose();
|
focusNode.removeListener(onFocusChanged);
|
||||||
hasFocusValueNotifier.dispose();
|
hasFocusValueNotifier.dispose();
|
||||||
bottomNavigationBarItemType.removeListener(onBackOrLeave);
|
bottomNavigationBarItemType.removeListener(onBackOrLeave);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
@ -157,11 +156,17 @@ class _MobileSearchTextfieldState extends State<MobileSearchTextfield> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onFocusChanged() {
|
||||||
|
if (!mounted) return;
|
||||||
|
hasFocusValueNotifier.value = focusNode.hasFocus;
|
||||||
|
}
|
||||||
|
|
||||||
void onBackOrLeave() {
|
void onBackOrLeave() {
|
||||||
final label = bottomNavigationBarItemType.value;
|
final label = bottomNavigationBarItemType.value;
|
||||||
if (label == BottomNavigationBarItemType.search.label) {
|
if (label == BottomNavigationBarItemType.search.label) {
|
||||||
focusNode.requestFocus();
|
focusNode.requestFocus();
|
||||||
} else {
|
} else {
|
||||||
|
focusNode.unfocus();
|
||||||
controller.clear();
|
controller.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,11 @@ class LinkStyle {
|
|||||||
BuildContext context, {
|
BuildContext context, {
|
||||||
bool showErrorBorder = false,
|
bool showErrorBorder = false,
|
||||||
EdgeInsets? contentPadding,
|
EdgeInsets? contentPadding,
|
||||||
|
double? radius,
|
||||||
}) {
|
}) {
|
||||||
final theme = AppFlowyTheme.of(context);
|
final theme = AppFlowyTheme.of(context);
|
||||||
final border = OutlineInputBorder(
|
final border = OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
borderRadius: BorderRadius.all(Radius.circular(radius ?? 8.0)),
|
||||||
borderSide: BorderSide(color: borderColor(context)),
|
borderSide: BorderSide(color: borderColor(context)),
|
||||||
);
|
);
|
||||||
final enableBorder = border.copyWith(
|
final enableBorder = border.copyWith(
|
||||||
|
@ -5,7 +5,11 @@ import 'package:appflowy_backend/protobuf/flowy-search/result.pb.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
extension GetIcon on ResultIconPB {
|
extension GetIcon on ResultIconPB {
|
||||||
Widget? getIcon({double size = 18.0, double lineHeight = 1.0}) {
|
Widget? getIcon({
|
||||||
|
double size = 18.0,
|
||||||
|
double lineHeight = 1.0,
|
||||||
|
Color? iconColor,
|
||||||
|
}) {
|
||||||
final iconValue = value, iconType = ty;
|
final iconValue = value, iconType = ty;
|
||||||
if (iconType == ResultIconTypePB.Emoji) {
|
if (iconType == ResultIconTypePB.Emoji) {
|
||||||
return iconValue.isNotEmpty
|
return iconValue.isNotEmpty
|
||||||
@ -17,7 +21,11 @@ extension GetIcon on ResultIconPB {
|
|||||||
: null;
|
: null;
|
||||||
} else if (ty == ResultIconTypePB.Icon) {
|
} else if (ty == ResultIconTypePB.Icon) {
|
||||||
if (_resultIconValueTypes.contains(iconValue)) {
|
if (_resultIconValueTypes.contains(iconValue)) {
|
||||||
return FlowySvg(getViewSvg(), size: Size.square(size));
|
return FlowySvg(
|
||||||
|
getViewSvg(),
|
||||||
|
size: Size.square(size),
|
||||||
|
color: iconColor,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return RawEmojiIconWidget(
|
return RawEmojiIconWidget(
|
||||||
emoji: EmojiIconData(iconType.toFlowyIconType(), iconValue),
|
emoji: EmojiIconData(iconType.toFlowyIconType(), iconValue),
|
||||||
|
@ -2347,8 +2347,8 @@
|
|||||||
"searchOrAskAI": "Search or ask AI",
|
"searchOrAskAI": "Search or ask AI",
|
||||||
"askAIAnything": "Ask AI anything",
|
"askAIAnything": "Ask AI anything",
|
||||||
"askAIFor": "Ask AI",
|
"askAIFor": "Ask AI",
|
||||||
"noResultForSearching": "No result for \"{}\"",
|
"noResultForSearching": "No matches found",
|
||||||
"noResultForSearchingHint": "Some results may be in your deleted pages",
|
"noResultForSearchingHint": "Try different questions or keywords.\n Some pages may be in the Trash.",
|
||||||
"bestMatch": "Best match",
|
"bestMatch": "Best match",
|
||||||
"placeholder": {
|
"placeholder": {
|
||||||
"actions": "Search actions..."
|
"actions": "Search actions..."
|
||||||
|
Loading…
x
Reference in New Issue
Block a user