Browse Source

Merge branch 'main' into onnx

Vishnu Mohandas 1 năm trước cách đây
mục cha
commit
2daebda377

+ 3 - 0
lib/events/clear_and_unfocus_search_bar_event.dart

@@ -0,0 +1,3 @@
+import 'package:photos/events/event.dart';
+
+class ClearAndUnfocusSearchBar extends Event {}

+ 12 - 5
lib/l10n/intl_zh.arb

@@ -406,6 +406,13 @@
   },
   "photoGridSize": "照片网格大小",
   "manageDeviceStorage": "管理设备存储",
+  "machineLearning": "机器学习",
+  "magicSearch": "魔法搜索",
+  "magicSearchDescription": "请使用我们的桌面应用程序来为您库中的待处理项目建立索引。",
+  "status": "状态",
+  "indexedItems": "已索引项目",
+  "pendingItems": "待处理项目",
+  "clearIndexes": "清空索引",
   "selectFoldersForBackup": "选择要备份的文件夹",
   "selectedFoldersWillBeEncryptedAndBackedUp": "所选文件夹将被加密和备份",
   "unselectAll": "取消全部选择",
@@ -1173,10 +1180,10 @@
   "signOutOtherBody": "如果你认为有人可能知道你的密码,你可以强制所有使用你账户的其他设备退出登录。",
   "signOutOtherDevices": "登出其他设备",
   "doNotSignOut": "不要退登",
-  "editLocation": "Edit location",
-  "selectALocation": "Select a location",
-  "selectALocationFirst": "Select a location first",
-  "changeLocationOfSelectedItems": "Change location of selected items?",
-  "editsToLocationWillOnlyBeSeenWithinEnte": "Edits to location will only be seen within Ente",
+  "editLocation": "编辑位置",
+  "selectALocation": "选择一个位置",
+  "selectALocationFirst": "首先选择一个位置",
+  "changeLocationOfSelectedItems": "确定要更改所选项目的位置吗?",
+  "editsToLocationWillOnlyBeSeenWithinEnte": "对位置的编辑只能在 Ente 内看到",
   "cleanUncategorized": "清除未分类的"
 }

+ 2 - 2
lib/ui/components/title_bar_widget.dart

@@ -60,7 +60,7 @@ class TitleBarWidget extends StatelessWidget {
             ? null
             : leading ??
                 IconButtonWidget(
-                  icon: Icons.arrow_back_outlined,
+                  icon: Icons.adaptive.arrow_back_outlined,
                   iconButtonType: IconButtonType.primary,
                   onTap: () {
                     Navigator.pop(context);
@@ -100,7 +100,7 @@ class TitleBarWidget extends StatelessWidget {
             ? null
             : leading ??
                 IconButtonWidget(
-                  icon: Icons.arrow_back_outlined,
+                  icon: Icons.adaptive.arrow_back_outlined,
                   iconButtonType: IconButtonType.primary,
                   onTap: () {
                     Navigator.pop(context);

+ 74 - 60
lib/ui/search_tab.dart

@@ -1,5 +1,6 @@
 import "package:fade_indexed_stack/fade_indexed_stack.dart";
 import "package:flutter/material.dart";
+import "package:flutter_animate/flutter_animate.dart";
 import "package:photos/core/constants.dart";
 import "package:photos/models/search/search_result.dart";
 import "package:photos/models/search/search_types.dart";
@@ -40,18 +41,15 @@ class _SearchTabState extends State<SearchTab> {
 
   @override
   Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.only(top: 8),
-      child: AllSectionsExamplesProvider(
-        child: FadeIndexedStack(
-          duration: const Duration(milliseconds: 150),
-          index: index,
-          children: [
-            const AllSearchSections(),
-            SearchSuggestionsWidget(_searchResults),
-            const NoResultWidget(),
-          ],
-        ),
+    return AllSectionsExamplesProvider(
+      child: FadeIndexedStack(
+        duration: const Duration(milliseconds: 150),
+        index: index,
+        children: [
+          const AllSearchSections(),
+          SearchSuggestionsWidget(_searchResults),
+          const NoResultWidget(),
+        ],
       ),
     );
   }
@@ -71,58 +69,74 @@ class _AllSearchSectionsState extends State<AllSearchSections> {
     // remove face and content sectionType
     searchTypes.remove(SectionType.face);
     searchTypes.remove(SectionType.content);
-    return Stack(
-      children: [
-        FutureBuilder(
-          future: InheritedAllSectionsExamples.of(context)
-              .allSectionsExamplesFuture,
-          builder: (context, snapshot) {
-            if (snapshot.hasData) {
-              if (snapshot.data!.every((element) => element.isEmpty)) {
+    return Padding(
+      padding: const EdgeInsets.only(top: 8),
+      child: Stack(
+        children: [
+          FutureBuilder(
+            future: InheritedAllSectionsExamples.of(context)
+                .allSectionsExamplesFuture,
+            builder: (context, snapshot) {
+              if (snapshot.hasData && snapshot.data!.isNotEmpty) {
+                if (snapshot.data!.every((element) => element.isEmpty)) {
+                  return const Padding(
+                    padding: EdgeInsets.only(bottom: 72),
+                    child: SearchTabEmptyState(),
+                  );
+                }
+                return ListView.builder(
+                  padding: const EdgeInsets.only(bottom: 180),
+                  physics: const BouncingScrollPhysics(),
+                  itemCount: searchTypes.length,
+                  itemBuilder: (context, index) {
+                    return SearchSection(
+                      sectionType: searchTypes[index],
+                      examples: snapshot.data!.elementAt(index),
+                      limit: searchSectionLimit,
+                    );
+                  },
+                )
+                    .animate(
+                      delay: const Duration(milliseconds: 150),
+                    )
+                    .slide(
+                      begin: const Offset(0, -0.015),
+                      end: const Offset(0, 0),
+                      duration: const Duration(milliseconds: 300),
+                      curve: Curves.easeOut,
+                    )
+                    .fadeIn(
+                      duration: const Duration(milliseconds: 150),
+                      curve: Curves.easeOut,
+                    );
+              } else if (snapshot.hasError) {
+                //Errors are handled and this else if condition will be false always
+                //is the understanding.
                 return const Padding(
                   padding: EdgeInsets.only(bottom: 72),
-                  child: SearchTabEmptyState(),
+                  child: EnteLoadingWidget(),
+                );
+              } else {
+                return const Padding(
+                  padding: EdgeInsets.only(bottom: 72),
+                  child: EnteLoadingWidget(),
                 );
               }
-              return ListView.builder(
-                padding: const EdgeInsets.only(bottom: 180),
-                physics: const BouncingScrollPhysics(),
-                itemCount: searchTypes.length,
-                itemBuilder: (context, index) {
-                  return SearchSection(
-                    sectionType: searchTypes[index],
-                    examples: snapshot.data!.elementAt(index),
-                    limit: searchSectionLimit,
-                  );
-                },
-              );
-            } else if (snapshot.hasError) {
-              //Errors are handled and this else if condition will be false always
-              //is the understanding.
-              return const Padding(
-                padding: EdgeInsets.only(bottom: 72),
-                child: EnteLoadingWidget(),
-              );
-            } else {
-              return const Padding(
-                padding: EdgeInsets.only(bottom: 72),
-                child: EnteLoadingWidget(),
-              );
-            }
-          },
-        ),
-        ValueListenableBuilder(
-          valueListenable:
-              InheritedAllSectionsExamples.of(context).isDebouncingNotifier,
-          builder: (context, value, _) {
-            return value
-                ? const EnteLoadingWidget(
-                    alignment: Alignment.topRight,
-                  )
-                : const SizedBox.shrink();
-          },
-        ),
-      ],
+            },
+          ),
+          ValueListenableBuilder(
+            valueListenable:
+                InheritedAllSectionsExamples.of(context).isDebouncingNotifier,
+            builder: (context, value, _) {
+              return value
+                  ? const EnteLoadingWidget(
+                      alignment: Alignment.topRight,
+                    )
+                  : const SizedBox.shrink();
+            },
+          ),
+        ],
+      ),
     );
   }
 }

+ 0 - 2
lib/ui/viewer/search/result/go_to_map_widget.dart

@@ -1,5 +1,3 @@
-import "dart:async";
-
 import "package:flutter/material.dart";
 import "package:photos/generated/l10n.dart";
 import "package:photos/services/search_service.dart";

+ 45 - 34
lib/ui/viewer/search/result/no_result_widget.dart

@@ -1,4 +1,6 @@
 import 'package:flutter/material.dart';
+import "package:photos/core/event_bus.dart";
+import "package:photos/events/clear_and_unfocus_search_bar_event.dart";
 import "package:photos/generated/l10n.dart";
 import "package:photos/models/search/search_types.dart";
 import "package:photos/states/all_sections_examples_state.dart";
@@ -71,42 +73,51 @@ class _NoResultWidgetState extends State<NoResultWidget> {
         );
       },
     );
-    return Padding(
-      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 32),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          Column(
-            crossAxisAlignment: CrossAxisAlignment.start,
-            children: [
-              Text(
-                S.of(context).noResultsFound,
-                style: textTheme.largeBold,
+    return Scaffold(
+      appBar: AppBar(
+        leading: BackButton(
+          onPressed: () {
+            Bus.instance.fire(ClearAndUnfocusSearchBar());
+          },
+        ),
+      ),
+      body: Padding(
+        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
+        child: Column(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            Column(
+              crossAxisAlignment: CrossAxisAlignment.start,
+              children: [
+                Text(
+                  S.of(context).noResultsFound,
+                  style: textTheme.largeBold,
+                ),
+                const SizedBox(height: 6),
+                searchTypeToQuerySuggestion.isNotEmpty
+                    ? Text(
+                        S.of(context).modifyYourQueryOrTrySearchingFor,
+                        style: textTheme.smallMuted,
+                      )
+                    : const SizedBox.shrink(),
+              ],
+            ),
+            const SizedBox(height: 20),
+            Padding(
+              padding: const EdgeInsets.symmetric(horizontal: 4),
+              child: ListView.separated(
+                itemBuilder: (context, index) {
+                  return searchTypeAndSuggestion[index];
+                },
+                separatorBuilder: (context, index) {
+                  return const SizedBox(height: 12);
+                },
+                itemCount: searchTypeToQuerySuggestion.length,
+                shrinkWrap: true,
               ),
-              const SizedBox(height: 6),
-              searchTypeToQuerySuggestion.isNotEmpty
-                  ? Text(
-                      S.of(context).modifyYourQueryOrTrySearchingFor,
-                      style: textTheme.smallMuted,
-                    )
-                  : const SizedBox.shrink(),
-            ],
-          ),
-          const SizedBox(height: 20),
-          Padding(
-            padding: const EdgeInsets.symmetric(horizontal: 4),
-            child: ListView.separated(
-              itemBuilder: (context, index) {
-                return searchTypeAndSuggestion[index];
-              },
-              separatorBuilder: (context, index) {
-                return const SizedBox(height: 12);
-              },
-              itemCount: searchTypeToQuerySuggestion.length,
-              shrinkWrap: true,
             ),
-          ),
-        ],
+          ],
+        ),
       ),
     );
   }

+ 3 - 5
lib/ui/viewer/search/search_suffix_icon_widget.dart

@@ -1,6 +1,7 @@
 import 'package:flutter/material.dart';
+import "package:photos/core/event_bus.dart";
+import "package:photos/events/clear_and_unfocus_search_bar_event.dart";
 import "package:photos/theme/ente_theme.dart";
-import 'package:photos/ui/viewer/search/search_widget.dart';
 
 class SearchSuffixIcon extends StatefulWidget {
   final bool shouldShowSpinner;
@@ -35,10 +36,7 @@ class _SearchSuffixIconState extends State<SearchSuffixIcon>
               splashRadius: 1,
               visualDensity: const VisualDensity(horizontal: -1, vertical: -1),
               onPressed: () {
-                final searchWidgetState =
-                    context.findAncestorStateOfType<SearchWidgetState>()!;
-                searchWidgetState.textController.clear();
-                searchWidgetState.focusNode.unfocus();
+                Bus.instance.fire(ClearAndUnfocusSearchBar());
               },
               icon: Icon(
                 Icons.close,

+ 63 - 52
lib/ui/viewer/search/search_suggestions.dart

@@ -1,5 +1,7 @@
 import 'package:flutter/material.dart';
 import 'package:logging/logging.dart';
+import "package:photos/core/event_bus.dart";
+import "package:photos/events/clear_and_unfocus_search_bar_event.dart";
 import "package:photos/generated/l10n.dart";
 import 'package:photos/models/search/album_search_result.dart';
 import 'package:photos/models/search/generic_search_result.dart';
@@ -23,62 +25,71 @@ class SearchSuggestionsWidget extends StatelessWidget {
     late final String title;
     final resultsCount = results.length;
     title = S.of(context).searchResultCount(resultsCount);
-    return Padding(
-      padding: const EdgeInsets.fromLTRB(12, 32, 12, 0),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          Text(
-            title,
-            style: getEnteTextTheme(context).largeBold,
-          ),
-          const SizedBox(height: 20),
-          Expanded(
-            child: Padding(
-              padding: const EdgeInsets.symmetric(horizontal: 4),
-              child: ListView.separated(
-                itemBuilder: (context, index) {
-                  final result = results[index];
-                  if (result is AlbumSearchResult) {
-                    final AlbumSearchResult albumSearchResult = result;
-                    return SearchResultWidget(
-                      result,
-                      resultCount: CollectionsService.instance.getFileCount(
-                        albumSearchResult.collectionWithThumbnail.collection,
-                      ),
-                      onResultTap: () => routeToPage(
-                        context,
-                        CollectionPage(
-                          albumSearchResult.collectionWithThumbnail,
-                          tagPrefix: result.heroTag(),
+    return Scaffold(
+      appBar: AppBar(
+        leading: BackButton(
+          onPressed: () {
+            Bus.instance.fire(ClearAndUnfocusSearchBar());
+          },
+        ),
+      ),
+      body: Padding(
+        padding: const EdgeInsets.fromLTRB(12, 0, 12, 0),
+        child: Column(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            Text(
+              title,
+              style: getEnteTextTheme(context).largeBold,
+            ),
+            const SizedBox(height: 20),
+            Expanded(
+              child: Padding(
+                padding: const EdgeInsets.symmetric(horizontal: 4),
+                child: ListView.separated(
+                  itemBuilder: (context, index) {
+                    final result = results[index];
+                    if (result is AlbumSearchResult) {
+                      final AlbumSearchResult albumSearchResult = result;
+                      return SearchResultWidget(
+                        result,
+                        resultCount: CollectionsService.instance.getFileCount(
+                          albumSearchResult.collectionWithThumbnail.collection,
+                        ),
+                        onResultTap: () => routeToPage(
+                          context,
+                          CollectionPage(
+                            albumSearchResult.collectionWithThumbnail,
+                            tagPrefix: result.heroTag(),
+                          ),
                         ),
-                      ),
-                    );
-                  } else if (result is GenericSearchResult) {
-                    return SearchResultWidget(
-                      result,
-                      onResultTap: result.onResultTap != null
-                          ? () => result.onResultTap!(context)
-                          : null,
-                    );
-                  } else {
-                    Logger('SearchSuggestionsWidget')
-                        .info("Invalid/Unsupported value");
-                    return const SizedBox.shrink();
-                  }
-                },
-                padding: EdgeInsets.only(
-                  bottom: (MediaQuery.sizeOf(context).height / 2) + 50,
+                      );
+                    } else if (result is GenericSearchResult) {
+                      return SearchResultWidget(
+                        result,
+                        onResultTap: result.onResultTap != null
+                            ? () => result.onResultTap!(context)
+                            : null,
+                      );
+                    } else {
+                      Logger('SearchSuggestionsWidget')
+                          .info("Invalid/Unsupported value");
+                      return const SizedBox.shrink();
+                    }
+                  },
+                  padding: EdgeInsets.only(
+                    bottom: (MediaQuery.sizeOf(context).height / 2) + 50,
+                  ),
+                  separatorBuilder: (context, index) {
+                    return const SizedBox(height: 12);
+                  },
+                  itemCount: results.length,
+                  physics: const BouncingScrollPhysics(),
                 ),
-                separatorBuilder: (context, index) {
-                  return const SizedBox(height: 12);
-                },
-                itemCount: results.length,
-                physics: const BouncingScrollPhysics(),
               ),
             ),
-          ),
-        ],
+          ],
+        ),
       ),
     );
   }

+ 10 - 0
lib/ui/viewer/search/search_widget.dart

@@ -4,6 +4,7 @@ import "package:flutter/material.dart";
 import "package:flutter/scheduler.dart";
 import "package:logging/logging.dart";
 import "package:photos/core/event_bus.dart";
+import "package:photos/events/clear_and_unfocus_search_bar_event.dart";
 import "package:photos/events/tab_changed_event.dart";
 import "package:photos/models/search/search_result.dart";
 import "package:photos/services/search_service.dart";
@@ -33,6 +34,8 @@ class SearchWidgetState extends State<SearchWidget> {
   double _distanceOfWidgetFromBottom = 0;
   GlobalKey widgetKey = GlobalKey();
   TextEditingController textController = TextEditingController();
+  late final StreamSubscription<ClearAndUnfocusSearchBar>
+      _clearAndUnfocusSearchBar;
 
   @override
   void initState() {
@@ -62,6 +65,12 @@ class SearchWidgetState extends State<SearchWidget> {
       textController.addListener(textControllerListener);
     });
     textController.text = query;
+
+    _clearAndUnfocusSearchBar =
+        Bus.instance.on<ClearAndUnfocusSearchBar>().listen((event) {
+      textController.clear();
+      focusNode.unfocus();
+    });
   }
 
   @override
@@ -81,6 +90,7 @@ class SearchWidgetState extends State<SearchWidget> {
     _tabDoubleTapEvent?.cancel();
     textController.removeListener(textControllerListener);
     textController.dispose();
+    _clearAndUnfocusSearchBar.cancel();
     super.dispose();
   }