Merge branch 'main' into redesign_search_tab
This commit is contained in:
commit
b10edfacdd
7 changed files with 77 additions and 51 deletions
2
lib/generated/intl/messages_zh.dart
generated
2
lib/generated/intl/messages_zh.dart
generated
|
@ -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":
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Reference in a new issue