Przeglądaj źródła

Merge branch 'main' into redesign_search_tab

ashilkn 1 rok temu
rodzic
commit
b10edfacdd

+ 1 - 1
lib/generated/intl/messages_zh.dart

@@ -666,7 +666,7 @@ class MessageLookup extends MessageLookupByLibrary {
             MessageLookupByLibrary.simpleMessage("项目显示永久删除前剩余的天数"),
         "itemsWillBeRemovedFromAlbum":
             MessageLookupByLibrary.simpleMessage("所选项目将从此相册中移除"),
-        "joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"),
+        "joinDiscord": MessageLookupByLibrary.simpleMessage("加入 Discord"),
         "keepPhotos": MessageLookupByLibrary.simpleMessage("保留照片"),
         "kiloMeterUnit": MessageLookupByLibrary.simpleMessage("公里"),
         "kindlyHelpUsWithThisInformation":

+ 17 - 7
lib/services/semantic_search/semantic_search_service.dart

@@ -19,6 +19,7 @@ import "package:photos/services/semantic_search/frameworks/ggml.dart";
 import "package:photos/services/semantic_search/frameworks/ml_framework.dart";
 import 'package:photos/services/semantic_search/frameworks/onnx/onnx.dart';
 import "package:photos/utils/debouncer.dart";
+import "package:photos/utils/device_info.dart";
 import "package:photos/utils/local_settings.dart";
 import "package:photos/utils/thumbnail_util.dart";
 
@@ -33,7 +34,6 @@ class SemanticSearchService {
   static const kEmbeddingLength = 512;
   static const kScoreThreshold = 0.23;
   static const kShouldPushEmbeddings = true;
-  static const kCurrentModel = Model.onnxClip;
   static const kDebounceDuration = Duration(milliseconds: 4000);
 
   final _logger = Logger("SemanticSearchService");
@@ -42,6 +42,7 @@ class SemanticSearchService {
   final _embeddingLoaderDebouncer =
       Debouncer(kDebounceDuration, executionInterval: kDebounceDuration);
 
+  late Model _currentModel;
   late MLFramework _mlFramework;
   bool _hasInitialized = false;
   bool _isComputingEmbeddings = false;
@@ -76,7 +77,8 @@ class SemanticSearchService {
     _hasInitialized = true;
     final shouldDownloadOverMobileData =
         Configuration.instance.shouldBackupOverMobileData();
-    _mlFramework = kCurrentModel == Model.onnxClip
+    _currentModel = await _getCurrentModel();
+    _mlFramework = _currentModel == Model.onnxClip
         ? ONNX(shouldDownloadOverMobileData)
         : GGML(shouldDownloadOverMobileData);
     await EmbeddingsDB.instance.init();
@@ -122,7 +124,7 @@ class SemanticSearchService {
       return;
     }
     _isSyncing = true;
-    await EmbeddingStore.instance.pullEmbeddings(kCurrentModel);
+    await EmbeddingStore.instance.pullEmbeddings(_currentModel);
     await _backFill();
     _isSyncing = false;
   }
@@ -171,14 +173,14 @@ class SemanticSearchService {
   }
 
   Future<void> clearIndexes() async {
-    await EmbeddingStore.instance.clearEmbeddings(kCurrentModel);
-    _logger.info("Indexes cleared for $kCurrentModel");
+    await EmbeddingStore.instance.clearEmbeddings(_currentModel);
+    _logger.info("Indexes cleared for $_currentModel");
   }
 
   Future<void> _loadEmbeddings() async {
     _logger.info("Pulling cached embeddings");
     final startTime = DateTime.now();
-    _cachedEmbeddings = await EmbeddingsDB.instance.getAll(kCurrentModel);
+    _cachedEmbeddings = await EmbeddingsDB.instance.getAll(_currentModel);
     final endTime = DateTime.now();
     _logger.info(
       "Loading ${_cachedEmbeddings.length} took: ${(endTime.millisecondsSinceEpoch - startTime.millisecondsSinceEpoch)}ms",
@@ -312,7 +314,7 @@ class SemanticSearchService {
 
       final embedding = Embedding(
         fileID: file.uploadedFileID!,
-        model: kCurrentModel,
+        model: _currentModel,
         embedding: result,
       );
       await EmbeddingStore.instance.storeEmbedding(
@@ -359,6 +361,14 @@ class SemanticSearchService {
     );
     return queryResults;
   }
+
+  Future<Model> _getCurrentModel() async {
+    if (await isGrapheneOS()) {
+      return Model.ggmlClip;
+    } else {
+      return Model.onnxClip;
+    }
+  }
 }
 
 List<QueryResult> computeBulkScore(Map args) {

+ 19 - 10
lib/services/update_service.dart

@@ -73,30 +73,39 @@ class UpdateService {
     return _latestVersion;
   }
 
-  Future<void> showUpdateNotification() async {
-    if (!isIndependent()) {
-      return;
-    }
+  Future<bool> shouldShowUpdateNoification() async {
     final shouldUpdate = await this.shouldUpdate();
+
     final lastNotificationShownTime =
         _prefs.getInt(kUpdateAvailableShownTimeKey) ?? 0;
     final now = DateTime.now().microsecondsSinceEpoch;
-    final hasBeen3DaysSinceLastNotification =
-        (now - lastNotificationShownTime) > (3 * microSecondsInDay);
-    if (shouldUpdate &&
-        hasBeen3DaysSinceLastNotification &&
-        _latestVersion!.shouldNotify) {
+    final hasBeenThresholdDaysSinceLastNotification =
+        (now - lastNotificationShownTime) >
+            ((_latestVersion!.shouldNotify ? 1 : 3) * microSecondsInDay);
+
+    return shouldUpdate && hasBeenThresholdDaysSinceLastNotification;
+  }
+
+  Future<void> showUpdateNotification() async {
+    if (await shouldShowUpdateNoification()) {
       // ignore: unawaited_futures
       NotificationService.instance.showNotification(
         "Update available",
         "Click to install our best version yet",
       );
-      await _prefs.setInt(kUpdateAvailableShownTimeKey, now);
+      await resetUpdateAvailableShownTime();
     } else {
       _logger.info("Debouncing notification");
     }
   }
 
+  Future<void> resetUpdateAvailableShownTime() {
+    return _prefs.setInt(
+      kUpdateAvailableShownTimeKey,
+      DateTime.now().microsecondsSinceEpoch,
+    );
+  }
+
   Future<LatestVersionInfo> _getLatestVersionInfo() async {
     final response = await NetworkClient.instance
         .getDio()

+ 24 - 27
lib/ui/settings/app_update_dialog.dart

@@ -1,12 +1,13 @@
 import 'package:flutter/material.dart';
 import 'package:logging/logging.dart';
-// import 'package:open_file/open_file.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/network/network.dart';
 import 'package:photos/ente_theme_data.dart';
 import "package:photos/generated/l10n.dart";
 import 'package:photos/services/update_service.dart';
 import 'package:photos/theme/ente_theme.dart';
+import "package:photos/ui/components/buttons/button_widget.dart";
+import "package:photos/ui/components/models/button_type.dart";
 import 'package:url_launcher/url_launcher_string.dart';
 
 class AppUpdateDialog extends StatefulWidget {
@@ -63,32 +64,28 @@ class _AppUpdateDialogState extends State<AppUpdateDialog> {
           children: changelog,
         ),
         const Padding(padding: EdgeInsets.all(8)),
-        SizedBox(
-          width: double.infinity,
-          height: 56,
-          child: OutlinedButton(
-            style: Theme.of(context).outlinedButtonTheme.style!.copyWith(
-              textStyle: MaterialStateProperty.resolveWith<TextStyle>(
-                (Set<MaterialState> states) {
-                  return enteTextTheme.bodyBold;
-                },
-              ),
-            ),
-            onPressed: () async {
-              Navigator.pop(context);
-              // ignore: unawaited_futures
-              showDialog(
-                context: context,
-                builder: (BuildContext context) {
-                  return ApkDownloaderDialog(widget.latestVersionInfo);
-                },
-                barrierDismissible: false,
-              );
-            },
-            child: Text(
-              S.of(context).update,
-            ),
-          ),
+        ButtonWidget(
+          buttonType: ButtonType.primary,
+          labelText: S.of(context).update,
+          onTap: () async {
+            Navigator.pop(context);
+            // ignore: unawaited_futures
+            showDialog(
+              context: context,
+              builder: (BuildContext context) {
+                return ApkDownloaderDialog(widget.latestVersionInfo);
+              },
+              barrierDismissible: false,
+            );
+          },
+        ),
+        const SizedBox(height: 6),
+        ButtonWidget(
+          buttonType: ButtonType.secondary,
+          labelText: S.of(context).cancel,
+          onTap: () async {
+            Navigator.of(context).pop();
+          },
         ),
         const Padding(padding: EdgeInsets.all(8)),
         Center(

+ 7 - 5
lib/ui/tabs/home_widget.dart

@@ -194,9 +194,9 @@ class _HomeWidgetState extends State<HomeWidget> {
       },
     );
     _initDeepLinks();
-    UpdateService.instance.shouldUpdate().then((shouldUpdate) {
-      if (shouldUpdate) {
-        Future.delayed(Duration.zero, () {
+    UpdateService.instance.shouldShowUpdateNoification().then((value) {
+      Future.delayed(Duration.zero, () {
+        if (value) {
           showDialog(
             context: context,
             builder: (BuildContext context) {
@@ -206,9 +206,11 @@ class _HomeWidgetState extends State<HomeWidget> {
             },
             barrierColor: Colors.black.withOpacity(0.85),
           );
-        });
-      }
+          UpdateService.instance.resetUpdateAvailableShownTime();
+        }
+      });
     });
+
     // For sharing images coming from outside the app
     _initMediaShareSubscription();
     WidgetsBinding.instance.addPostFrameCallback(

+ 8 - 0
lib/utils/device_info.dart

@@ -42,6 +42,14 @@ Future<bool> isLowSpecDevice() async {
   return false;
 }
 
+Future<bool> isGrapheneOS() async {
+  if (Platform.isAndroid) {
+    final androidInfo = await deviceInfoPlugin.androidInfo;
+    return androidInfo.host.toLowerCase() == "grapheneos";
+  }
+  return false;
+}
+
 Future<bool> isAndroidSDKVersionLowerThan(int inputSDK) async {
   if (Platform.isAndroid) {
     final AndroidDeviceInfo androidInfo = await deviceInfoPlugin.androidInfo;

+ 1 - 1
pubspec.lock

@@ -1390,7 +1390,7 @@ packages:
     description:
       path: "."
       ref: HEAD
-      resolved-ref: "5f26aef45ed9f5e563c26f90c1e21b3339ed906d"
+      resolved-ref: "1318dce97f3aae5ec9bdf7491d5eff0ad6beb378"
       url: "https://github.com/ente-io/onnxruntime.git"
     source: git
     version: "1.1.0"