Merge remote-tracking branch 'origin/main' into migrate_files_db_to_sqlite_async

This commit is contained in:
laurenspriem 2024-05-24 18:23:32 +05:30
commit 7a6fa1cd80
33 changed files with 199 additions and 51 deletions

View file

@ -35,10 +35,10 @@ import 'package:photos/services/sync_service.dart';
import 'package:photos/utils/crypto_util.dart'; import 'package:photos/utils/crypto_util.dart';
import 'package:photos/utils/file_uploader.dart'; import 'package:photos/utils/file_uploader.dart';
import 'package:photos/utils/validator_util.dart'; import 'package:photos/utils/validator_util.dart';
import "package:photos/utils/wakelock_util.dart";
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import "package:tuple/tuple.dart"; import "package:tuple/tuple.dart";
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
class Configuration { class Configuration {
Configuration._privateConstructor(); Configuration._privateConstructor();
@ -585,7 +585,7 @@ class Configuration {
Future<void> setShouldKeepDeviceAwake(bool value) async { Future<void> setShouldKeepDeviceAwake(bool value) async {
await _preferences.setBool(keyShouldKeepDeviceAwake, value); await _preferences.setBool(keyShouldKeepDeviceAwake, value);
await WakelockPlus.toggle(enable: value); await EnteWakeLock.toggle(enable: value);
} }
Future<void> setShouldBackupVideos(bool value) async { Future<void> setShouldBackupVideos(bool value) async {

View file

@ -668,22 +668,39 @@ class FaceMLDataDB {
return maps.first['count'] as int; return maps.first['count'] as int;
} }
Future<int> getClusteredFileCount() async { Future<int> getClusteredOrFacelessFileCount() async {
final db = await instance.asyncDB; final db = await instance.asyncDB;
final List<Map<String, dynamic>> maps = await db.getAll( final List<Map<String, dynamic>> clustered = await db.getAll(
'SELECT $fcFaceId FROM $faceClustersTable', 'SELECT $fcFaceId FROM $faceClustersTable',
); );
final Set<int> fileIDs = {}; final Set<int> clusteredFileIDs = {};
for (final map in maps) { for (final map in clustered) {
final int fileID = getFileIdFromFaceId(map[fcFaceId] as String); final int fileID = getFileIdFromFaceId(map[fcFaceId] as String);
fileIDs.add(fileID); clusteredFileIDs.add(fileID);
} }
return fileIDs.length;
final List<Map<String, dynamic>> badFacesFiles = await db.getAll(
'SELECT DISTINCT $fileIDColumn FROM $facesTable WHERE $faceScore <= $kMinimumQualityFaceScore OR $faceBlur <= $kLaplacianHardThreshold',
);
final Set<int> badFileIDs = {};
for (final map in badFacesFiles) {
badFileIDs.add(map[fileIDColumn] as int);
}
final List<Map<String, dynamic>> goodFacesFiles = await db.getAll(
'SELECT DISTINCT $fileIDColumn FROM $facesTable WHERE $faceScore > $kMinimumQualityFaceScore AND $faceBlur > $kLaplacianHardThreshold',
);
final Set<int> goodFileIDs = {};
for (final map in goodFacesFiles) {
goodFileIDs.add(map[fileIDColumn] as int);
}
final trulyFacelessFiles = badFileIDs.difference(goodFileIDs);
return clusteredFileIDs.length + trulyFacelessFiles.length;
} }
Future<double> getClusteredToIndexableFilesRatio() async { Future<double> getClusteredToIndexableFilesRatio() async {
final int indexableFiles = (await getIndexableFileIDs()).length; final int indexableFiles = (await getIndexableFileIDs()).length;
final int clusteredFiles = await getClusteredFileCount(); final int clusteredFiles = await getClusteredOrFacelessFileCount();
return clusteredFiles / indexableFiles; return clusteredFiles / indexableFiles;
} }

View file

@ -54,6 +54,8 @@ class MessageLookup extends MessageLookupByLibrary {
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."), "Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
"fileTypes": MessageLookupByLibrary.simpleMessage("File types"), "fileTypes": MessageLookupByLibrary.simpleMessage("File types"),
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"), "foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
"Indexing is paused, will automatically resume when device is ready"),
"joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"), "joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"),
"locations": MessageLookupByLibrary.simpleMessage("Locations"), "locations": MessageLookupByLibrary.simpleMessage("Locations"),
"longPressAnEmailToVerifyEndToEndEncryption": "longPressAnEmailToVerifyEndToEndEncryption":

View file

@ -819,6 +819,8 @@ class MessageLookup extends MessageLookupByLibrary {
"Falscher Wiederherstellungs-Schlüssel"), "Falscher Wiederherstellungs-Schlüssel"),
"indexedItems": "indexedItems":
MessageLookupByLibrary.simpleMessage("Indizierte Elemente"), MessageLookupByLibrary.simpleMessage("Indizierte Elemente"),
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
"Indexing is paused, will automatically resume when device is ready"),
"insecureDevice": "insecureDevice":
MessageLookupByLibrary.simpleMessage("Unsicheres Gerät"), MessageLookupByLibrary.simpleMessage("Unsicheres Gerät"),
"installManually": "installManually":

View file

@ -813,6 +813,8 @@ class MessageLookup extends MessageLookupByLibrary {
"incorrectRecoveryKeyTitle": "incorrectRecoveryKeyTitle":
MessageLookupByLibrary.simpleMessage("Incorrect recovery key"), MessageLookupByLibrary.simpleMessage("Incorrect recovery key"),
"indexedItems": MessageLookupByLibrary.simpleMessage("Indexed items"), "indexedItems": MessageLookupByLibrary.simpleMessage("Indexed items"),
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
"Indexing is paused, will automatically resume when device is ready"),
"insecureDevice": "insecureDevice":
MessageLookupByLibrary.simpleMessage("Insecure device"), MessageLookupByLibrary.simpleMessage("Insecure device"),
"installManually": "installManually":

View file

@ -699,6 +699,8 @@ class MessageLookup extends MessageLookupByLibrary {
"La clave de recuperación introducida es incorrecta"), "La clave de recuperación introducida es incorrecta"),
"incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage( "incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage(
"Clave de recuperación incorrecta"), "Clave de recuperación incorrecta"),
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
"Indexing is paused, will automatically resume when device is ready"),
"insecureDevice": "insecureDevice":
MessageLookupByLibrary.simpleMessage("Dispositivo inseguro"), MessageLookupByLibrary.simpleMessage("Dispositivo inseguro"),
"installManually": "installManually":

View file

@ -804,6 +804,8 @@ class MessageLookup extends MessageLookupByLibrary {
"La clé de secours que vous avez entrée est incorrecte"), "La clé de secours que vous avez entrée est incorrecte"),
"incorrectRecoveryKeyTitle": "incorrectRecoveryKeyTitle":
MessageLookupByLibrary.simpleMessage("Clé de secours non valide"), MessageLookupByLibrary.simpleMessage("Clé de secours non valide"),
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
"Indexing is paused, will automatically resume when device is ready"),
"insecureDevice": "insecureDevice":
MessageLookupByLibrary.simpleMessage("Appareil non sécurisé"), MessageLookupByLibrary.simpleMessage("Appareil non sécurisé"),
"installManually": "installManually":

View file

@ -773,6 +773,8 @@ class MessageLookup extends MessageLookupByLibrary {
"Il codice che hai inserito non è corretto"), "Il codice che hai inserito non è corretto"),
"incorrectRecoveryKeyTitle": "incorrectRecoveryKeyTitle":
MessageLookupByLibrary.simpleMessage("Chiave di recupero errata"), MessageLookupByLibrary.simpleMessage("Chiave di recupero errata"),
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
"Indexing is paused, will automatically resume when device is ready"),
"insecureDevice": "insecureDevice":
MessageLookupByLibrary.simpleMessage("Dispositivo non sicuro"), MessageLookupByLibrary.simpleMessage("Dispositivo non sicuro"),
"installManually": "installManually":

View file

@ -54,6 +54,8 @@ class MessageLookup extends MessageLookupByLibrary {
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."), "Please note that this will result in a higher bandwidth and battery usage until all items are indexed."),
"fileTypes": MessageLookupByLibrary.simpleMessage("File types"), "fileTypes": MessageLookupByLibrary.simpleMessage("File types"),
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"), "foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
"Indexing is paused, will automatically resume when device is ready"),
"joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"), "joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"),
"locations": MessageLookupByLibrary.simpleMessage("Locations"), "locations": MessageLookupByLibrary.simpleMessage("Locations"),
"longPressAnEmailToVerifyEndToEndEncryption": "longPressAnEmailToVerifyEndToEndEncryption":

View file

@ -840,6 +840,8 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Onjuiste herstelsleutel"), MessageLookupByLibrary.simpleMessage("Onjuiste herstelsleutel"),
"indexedItems": "indexedItems":
MessageLookupByLibrary.simpleMessage("Geïndexeerde bestanden"), MessageLookupByLibrary.simpleMessage("Geïndexeerde bestanden"),
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
"Indexing is paused, will automatically resume when device is ready"),
"insecureDevice": "insecureDevice":
MessageLookupByLibrary.simpleMessage("Onveilig apparaat"), MessageLookupByLibrary.simpleMessage("Onveilig apparaat"),
"installManually": "installManually":

View file

@ -72,6 +72,8 @@ class MessageLookup extends MessageLookupByLibrary {
"feedback": MessageLookupByLibrary.simpleMessage("Tilbakemelding"), "feedback": MessageLookupByLibrary.simpleMessage("Tilbakemelding"),
"fileTypes": MessageLookupByLibrary.simpleMessage("File types"), "fileTypes": MessageLookupByLibrary.simpleMessage("File types"),
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"), "foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"),
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
"Indexing is paused, will automatically resume when device is ready"),
"invalidEmailAddress": "invalidEmailAddress":
MessageLookupByLibrary.simpleMessage("Ugyldig e-postadresse"), MessageLookupByLibrary.simpleMessage("Ugyldig e-postadresse"),
"joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"), "joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"),

View file

@ -131,6 +131,8 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Kod jest nieprawidłowy"), MessageLookupByLibrary.simpleMessage("Kod jest nieprawidłowy"),
"incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage( "incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage(
"Nieprawidłowy klucz odzyskiwania"), "Nieprawidłowy klucz odzyskiwania"),
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
"Indexing is paused, will automatically resume when device is ready"),
"invalidEmailAddress": "invalidEmailAddress":
MessageLookupByLibrary.simpleMessage("Nieprawidłowy adres e-mail"), MessageLookupByLibrary.simpleMessage("Nieprawidłowy adres e-mail"),
"joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"), "joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"),

View file

@ -98,7 +98,7 @@ class MessageLookup extends MessageLookupByLibrary {
"${storageAmountInGB} GB cada vez que alguém se inscrever para um plano pago e aplica o seu código"; "${storageAmountInGB} GB cada vez que alguém se inscrever para um plano pago e aplica o seu código";
static String m25(freeAmount, storageUnit) => static String m25(freeAmount, storageUnit) =>
"${freeAmount} ${storageUnit} grátis"; "${freeAmount} ${storageUnit} livre";
static String m26(endDate) => "Teste gratuito acaba em ${endDate}"; static String m26(endDate) => "Teste gratuito acaba em ${endDate}";
@ -225,6 +225,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Eu entendo que se eu perder minha senha, posso perder meus dados, já que meus dados são <underline>criptografados de ponta a ponta</underline>."), "Eu entendo que se eu perder minha senha, posso perder meus dados, já que meus dados são <underline>criptografados de ponta a ponta</underline>."),
"activeSessions": "activeSessions":
MessageLookupByLibrary.simpleMessage("Sessões ativas"), MessageLookupByLibrary.simpleMessage("Sessões ativas"),
"addAName": MessageLookupByLibrary.simpleMessage("Adicione um nome"),
"addANewEmail": "addANewEmail":
MessageLookupByLibrary.simpleMessage("Adicionar um novo email"), MessageLookupByLibrary.simpleMessage("Adicionar um novo email"),
"addCollaborator": "addCollaborator":
@ -446,7 +447,7 @@ class MessageLookup extends MessageLookupByLibrary {
"clubByFileName": MessageLookupByLibrary.simpleMessage( "clubByFileName": MessageLookupByLibrary.simpleMessage(
"Agrupar pelo nome de arquivo"), "Agrupar pelo nome de arquivo"),
"clusteringProgress": "clusteringProgress":
MessageLookupByLibrary.simpleMessage("Clustering progress"), MessageLookupByLibrary.simpleMessage("Progresso de agrupamento"),
"codeAppliedPageTitle": "codeAppliedPageTitle":
MessageLookupByLibrary.simpleMessage("Código aplicado"), MessageLookupByLibrary.simpleMessage("Código aplicado"),
"codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage( "codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
@ -692,6 +693,8 @@ class MessageLookup extends MessageLookupByLibrary {
"enterPassword": MessageLookupByLibrary.simpleMessage("Digite a senha"), "enterPassword": MessageLookupByLibrary.simpleMessage("Digite a senha"),
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage( "enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
"Insira a senha para criptografar seus dados"), "Insira a senha para criptografar seus dados"),
"enterPersonName":
MessageLookupByLibrary.simpleMessage("Inserir nome da pessoa"),
"enterReferralCode": MessageLookupByLibrary.simpleMessage( "enterReferralCode": MessageLookupByLibrary.simpleMessage(
"Insira o código de referência"), "Insira o código de referência"),
"enterThe6digitCodeFromnyourAuthenticatorApp": "enterThe6digitCodeFromnyourAuthenticatorApp":
@ -717,9 +720,9 @@ class MessageLookup extends MessageLookupByLibrary {
"exportYourData": "exportYourData":
MessageLookupByLibrary.simpleMessage("Exportar seus dados"), MessageLookupByLibrary.simpleMessage("Exportar seus dados"),
"faceRecognition": "faceRecognition":
MessageLookupByLibrary.simpleMessage("Face recognition"), MessageLookupByLibrary.simpleMessage("Reconhecimento facial"),
"faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage( "faceRecognitionIndexingDescription": MessageLookupByLibrary.simpleMessage(
"Please note that this will result in a higher bandwidth and battery usage until all items are indexed."), "Por favor, note que isso resultará em uma largura de banda maior e uso de bateria até que todos os itens sejam indexados."),
"faces": MessageLookupByLibrary.simpleMessage("Rostos"), "faces": MessageLookupByLibrary.simpleMessage("Rostos"),
"failedToApplyCode": "failedToApplyCode":
MessageLookupByLibrary.simpleMessage("Falha ao aplicar o código"), MessageLookupByLibrary.simpleMessage("Falha ao aplicar o código"),
@ -761,12 +764,15 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Arquivos excluídos"), MessageLookupByLibrary.simpleMessage("Arquivos excluídos"),
"filesSavedToGallery": "filesSavedToGallery":
MessageLookupByLibrary.simpleMessage("Arquivos salvos na galeria"), MessageLookupByLibrary.simpleMessage("Arquivos salvos na galeria"),
"findPeopleByName": MessageLookupByLibrary.simpleMessage(
"Encontre pessoas rapidamente por nome"),
"flip": MessageLookupByLibrary.simpleMessage("Inverter"), "flip": MessageLookupByLibrary.simpleMessage("Inverter"),
"forYourMemories": "forYourMemories":
MessageLookupByLibrary.simpleMessage("para suas memórias"), MessageLookupByLibrary.simpleMessage("para suas memórias"),
"forgotPassword": "forgotPassword":
MessageLookupByLibrary.simpleMessage("Esqueceu sua senha"), MessageLookupByLibrary.simpleMessage("Esqueceu sua senha"),
"foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"), "foundFaces":
MessageLookupByLibrary.simpleMessage("Rostos encontrados"),
"freeStorageClaimed": MessageLookupByLibrary.simpleMessage( "freeStorageClaimed": MessageLookupByLibrary.simpleMessage(
"Armazenamento gratuito reivindicado"), "Armazenamento gratuito reivindicado"),
"freeStorageOnReferralSuccess": m24, "freeStorageOnReferralSuccess": m24,
@ -830,6 +836,8 @@ class MessageLookup extends MessageLookupByLibrary {
"incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage( "incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage(
"Chave de recuperação incorreta"), "Chave de recuperação incorreta"),
"indexedItems": MessageLookupByLibrary.simpleMessage("Itens indexados"), "indexedItems": MessageLookupByLibrary.simpleMessage("Itens indexados"),
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
"Indexing is paused, will automatically resume when device is ready"),
"insecureDevice": "insecureDevice":
MessageLookupByLibrary.simpleMessage("Dispositivo não seguro"), MessageLookupByLibrary.simpleMessage("Dispositivo não seguro"),
"installManually": "installManually":
@ -1064,6 +1072,7 @@ class MessageLookup extends MessageLookupByLibrary {
"pendingItems": MessageLookupByLibrary.simpleMessage("Itens pendentes"), "pendingItems": MessageLookupByLibrary.simpleMessage("Itens pendentes"),
"pendingSync": "pendingSync":
MessageLookupByLibrary.simpleMessage("Sincronização pendente"), MessageLookupByLibrary.simpleMessage("Sincronização pendente"),
"people": MessageLookupByLibrary.simpleMessage("Pessoas"),
"peopleUsingYourCode": "peopleUsingYourCode":
MessageLookupByLibrary.simpleMessage("Pessoas que usam seu código"), MessageLookupByLibrary.simpleMessage("Pessoas que usam seu código"),
"permDeleteWarning": MessageLookupByLibrary.simpleMessage( "permDeleteWarning": MessageLookupByLibrary.simpleMessage(
@ -1197,6 +1206,8 @@ class MessageLookup extends MessageLookupByLibrary {
"removeParticipant": "removeParticipant":
MessageLookupByLibrary.simpleMessage("Remover participante"), MessageLookupByLibrary.simpleMessage("Remover participante"),
"removeParticipantBody": m43, "removeParticipantBody": m43,
"removePersonLabel":
MessageLookupByLibrary.simpleMessage("Remover etiqueta da pessoa"),
"removePublicLink": "removePublicLink":
MessageLookupByLibrary.simpleMessage("Remover link público"), MessageLookupByLibrary.simpleMessage("Remover link público"),
"removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage(
@ -1260,7 +1271,7 @@ class MessageLookup extends MessageLookupByLibrary {
"searchDatesEmptySection": MessageLookupByLibrary.simpleMessage( "searchDatesEmptySection": MessageLookupByLibrary.simpleMessage(
"Pesquisar por data, mês ou ano"), "Pesquisar por data, mês ou ano"),
"searchFaceEmptySection": MessageLookupByLibrary.simpleMessage( "searchFaceEmptySection": MessageLookupByLibrary.simpleMessage(
"Encontre todas as fotos de uma pessoa"), "Pessoas serão exibidas aqui uma vez que a indexação é feita"),
"searchFileTypesAndNamesEmptySection": "searchFileTypesAndNamesEmptySection":
MessageLookupByLibrary.simpleMessage("Tipos de arquivo e nomes"), MessageLookupByLibrary.simpleMessage("Tipos de arquivo e nomes"),
"searchHint1": MessageLookupByLibrary.simpleMessage( "searchHint1": MessageLookupByLibrary.simpleMessage(

View file

@ -686,6 +686,8 @@ class MessageLookup extends MessageLookupByLibrary {
"incorrectRecoveryKeyTitle": "incorrectRecoveryKeyTitle":
MessageLookupByLibrary.simpleMessage("不正确的恢复密钥"), MessageLookupByLibrary.simpleMessage("不正确的恢复密钥"),
"indexedItems": MessageLookupByLibrary.simpleMessage("已索引项目"), "indexedItems": MessageLookupByLibrary.simpleMessage("已索引项目"),
"indexingIsPaused": MessageLookupByLibrary.simpleMessage(
"Indexing is paused, will automatically resume when device is ready"),
"insecureDevice": MessageLookupByLibrary.simpleMessage("设备不安全"), "insecureDevice": MessageLookupByLibrary.simpleMessage("设备不安全"),
"installManually": MessageLookupByLibrary.simpleMessage("手动安装"), "installManually": MessageLookupByLibrary.simpleMessage("手动安装"),
"invalidEmailAddress": "invalidEmailAddress":

View file

@ -8793,6 +8793,16 @@ class S {
args: [], args: [],
); );
} }
/// `Indexing is paused, will automatically resume when device is ready`
String get indexingIsPaused {
return Intl.message(
'Indexing is paused, will automatically resume when device is ready',
name: 'indexingIsPaused',
desc: '',
args: [],
);
}
} }
class AppLocalizationDelegate extends LocalizationsDelegate<S> { class AppLocalizationDelegate extends LocalizationsDelegate<S> {

View file

@ -24,5 +24,6 @@
"faceRecognition": "Face recognition", "faceRecognition": "Face recognition",
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.", "faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
"foundFaces": "Found faces", "foundFaces": "Found faces",
"clusteringProgress": "Clustering progress" "clusteringProgress": "Clustering progress",
"indexingIsPaused": "Indexing is paused, will automatically resume when device is ready"
} }

View file

@ -1212,5 +1212,6 @@
"faceRecognition": "Face recognition", "faceRecognition": "Face recognition",
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.", "faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
"foundFaces": "Found faces", "foundFaces": "Found faces",
"clusteringProgress": "Clustering progress" "clusteringProgress": "Clustering progress",
"indexingIsPaused": "Indexing is paused, will automatically resume when device is ready"
} }

View file

@ -1235,5 +1235,6 @@
"faceRecognition": "Face recognition", "faceRecognition": "Face recognition",
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.", "faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
"foundFaces": "Found faces", "foundFaces": "Found faces",
"clusteringProgress": "Clustering progress" "clusteringProgress": "Clustering progress",
"indexingIsPaused": "Indexing is paused, will automatically resume when device is ready"
} }

View file

@ -986,5 +986,6 @@
"faceRecognition": "Face recognition", "faceRecognition": "Face recognition",
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.", "faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
"foundFaces": "Found faces", "foundFaces": "Found faces",
"clusteringProgress": "Clustering progress" "clusteringProgress": "Clustering progress",
"indexingIsPaused": "Indexing is paused, will automatically resume when device is ready"
} }

View file

@ -1167,5 +1167,6 @@
"faceRecognition": "Face recognition", "faceRecognition": "Face recognition",
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.", "faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
"foundFaces": "Found faces", "foundFaces": "Found faces",
"clusteringProgress": "Clustering progress" "clusteringProgress": "Clustering progress",
"indexingIsPaused": "Indexing is paused, will automatically resume when device is ready"
} }

View file

@ -1129,5 +1129,6 @@
"faceRecognition": "Face recognition", "faceRecognition": "Face recognition",
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.", "faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
"foundFaces": "Found faces", "foundFaces": "Found faces",
"clusteringProgress": "Clustering progress" "clusteringProgress": "Clustering progress",
"indexingIsPaused": "Indexing is paused, will automatically resume when device is ready"
} }

View file

@ -24,5 +24,6 @@
"faceRecognition": "Face recognition", "faceRecognition": "Face recognition",
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.", "faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
"foundFaces": "Found faces", "foundFaces": "Found faces",
"clusteringProgress": "Clustering progress" "clusteringProgress": "Clustering progress",
"indexingIsPaused": "Indexing is paused, will automatically resume when device is ready"
} }

View file

@ -1230,5 +1230,6 @@
"faceRecognition": "Face recognition", "faceRecognition": "Face recognition",
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.", "faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
"foundFaces": "Found faces", "foundFaces": "Found faces",
"clusteringProgress": "Clustering progress" "clusteringProgress": "Clustering progress",
"indexingIsPaused": "Indexing is paused, will automatically resume when device is ready"
} }

View file

@ -38,5 +38,6 @@
"faceRecognition": "Face recognition", "faceRecognition": "Face recognition",
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.", "faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
"foundFaces": "Found faces", "foundFaces": "Found faces",
"clusteringProgress": "Clustering progress" "clusteringProgress": "Clustering progress",
"indexingIsPaused": "Indexing is paused, will automatically resume when device is ready"
} }

View file

@ -125,5 +125,6 @@
"faceRecognition": "Face recognition", "faceRecognition": "Face recognition",
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.", "faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
"foundFaces": "Found faces", "foundFaces": "Found faces",
"clusteringProgress": "Clustering progress" "clusteringProgress": "Clustering progress",
"indexingIsPaused": "Indexing is paused, will automatically resume when device is ready"
} }

View file

@ -1235,5 +1235,6 @@
"faceRecognition": "Reconhecimento facial", "faceRecognition": "Reconhecimento facial",
"faceRecognitionIndexingDescription": "Por favor, note que isso resultará em uma largura de banda maior e uso de bateria até que todos os itens sejam indexados.", "faceRecognitionIndexingDescription": "Por favor, note que isso resultará em uma largura de banda maior e uso de bateria até que todos os itens sejam indexados.",
"foundFaces": "Rostos encontrados", "foundFaces": "Rostos encontrados",
"clusteringProgress": "Progresso de agrupamento" "clusteringProgress": "Progresso de agrupamento",
"indexingIsPaused": "Indexing is paused, will automatically resume when device is ready"
} }

View file

@ -1230,5 +1230,6 @@
"faceRecognition": "Face recognition", "faceRecognition": "Face recognition",
"faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.", "faceRecognitionIndexingDescription": "Please note that this will result in a higher bandwidth and battery usage until all items are indexed.",
"foundFaces": "Found faces", "foundFaces": "Found faces",
"clusteringProgress": "Clustering progress" "clusteringProgress": "Clustering progress",
"indexingIsPaused": "Indexing is paused, will automatically resume when device is ready"
} }

View file

@ -8,6 +8,18 @@ class GeneralFaceMlException implements Exception {
String toString() => 'GeneralFaceMlException: $message'; String toString() => 'GeneralFaceMlException: $message';
} }
class ThumbnailRetrievalException implements Exception {
final String message;
final StackTrace stackTrace;
ThumbnailRetrievalException(this.message, this.stackTrace);
@override
String toString() {
return 'ThumbnailRetrievalException: $message\n$stackTrace';
}
}
class CouldNotRetrieveAnyFileData implements Exception {} class CouldNotRetrieveAnyFileData implements Exception {}
class CouldNotInitializeFaceDetector implements Exception {} class CouldNotInitializeFaceDetector implements Exception {}

View file

@ -9,6 +9,7 @@ import "dart:ui" show Image;
import "package:computer/computer.dart"; import "package:computer/computer.dart";
import "package:dart_ui_isolate/dart_ui_isolate.dart"; import "package:dart_ui_isolate/dart_ui_isolate.dart";
import "package:flutter/foundation.dart" show debugPrint, kDebugMode; import "package:flutter/foundation.dart" show debugPrint, kDebugMode;
import "package:flutter/services.dart";
import "package:logging/logging.dart"; import "package:logging/logging.dart";
import "package:onnxruntime/onnxruntime.dart"; import "package:onnxruntime/onnxruntime.dart";
import "package:package_info_plus/package_info_plus.dart"; import "package:package_info_plus/package_info_plus.dart";
@ -446,7 +447,8 @@ class FaceMlService {
if (LocalSettings.instance.remoteFetchEnabled) { if (LocalSettings.instance.remoteFetchEnabled) {
try { try {
final Set<int> fileIds = {}; // if there are duplicates here server returns 400 final Set<int> fileIds =
{}; // if there are duplicates here server returns 400
// Try to find embeddings on the remote server // Try to find embeddings on the remote server
for (final f in chunk) { for (final f in chunk) {
fileIds.add(f.uploadedFileID!); fileIds.add(f.uploadedFileID!);
@ -844,13 +846,22 @@ class FaceMlService {
} }
await FaceMLDataDB.instance.bulkInsertFaces(faces); await FaceMLDataDB.instance.bulkInsertFaces(faces);
return true; return true;
} on ThumbnailRetrievalException catch (e, s) {
_logger.severe(
'ThumbnailRetrievalException while processing image with ID ${enteFile.uploadedFileID}, storing empty face so indexing does not get stuck',
e,
s,
);
await FaceMLDataDB.instance
.bulkInsertFaces([Face.empty(enteFile.uploadedFileID!, error: true)]);
return true;
} catch (e, s) { } catch (e, s) {
_logger.severe( _logger.severe(
"Failed to analyze using FaceML for image with ID: ${enteFile.uploadedFileID}", "Failed to analyze using FaceML for image with ID: ${enteFile.uploadedFileID}",
e, e,
s, s,
); );
return true; return false;
} }
} }
@ -1004,7 +1015,12 @@ class FaceMlService {
final stopwatch = Stopwatch()..start(); final stopwatch = Stopwatch()..start();
File? file; File? file;
if (enteFile.fileType == FileType.video) { if (enteFile.fileType == FileType.video) {
try {
file = await getThumbnailForUploadedFile(enteFile); file = await getThumbnailForUploadedFile(enteFile);
} on PlatformException catch (e, s) {
_logger.severe("Could not get thumbnail for $enteFile due to PlatformException", e, s);
throw ThumbnailRetrievalException(e.toString(), s);
}
} else { } else {
file = await getFile(enteFile, isOrigin: true); file = await getFile(enteFile, isOrigin: true);
// TODO: This is returning null for Pragadees for all files, so something is wrong here! // TODO: This is returning null for Pragadees for all files, so something is wrong here!

View file

@ -28,6 +28,8 @@ class MachineLearningController {
bool _canRunML = false; bool _canRunML = false;
late Timer _userInteractionTimer; late Timer _userInteractionTimer;
bool get isDeviceHealthy => _isDeviceHealthy;
void init() { void init() {
if (Platform.isAndroid) { if (Platform.isAndroid) {
_startInteractionTimer(); _startInteractionTimer();

View file

@ -11,6 +11,7 @@ import "package:photos/generated/l10n.dart";
import "package:photos/models/ml/ml_versions.dart"; import "package:photos/models/ml/ml_versions.dart";
import "package:photos/service_locator.dart"; import "package:photos/service_locator.dart";
import "package:photos/services/machine_learning/face_ml/face_ml_service.dart"; import "package:photos/services/machine_learning/face_ml/face_ml_service.dart";
import "package:photos/services/machine_learning/machine_learning_controller.dart";
import 'package:photos/services/machine_learning/semantic_search/frameworks/ml_framework.dart'; import 'package:photos/services/machine_learning/semantic_search/frameworks/ml_framework.dart';
import 'package:photos/services/machine_learning/semantic_search/semantic_search_service.dart'; import 'package:photos/services/machine_learning/semantic_search/semantic_search_service.dart';
import "package:photos/services/remote_assets_service.dart"; import "package:photos/services/remote_assets_service.dart";
@ -27,6 +28,7 @@ import "package:photos/ui/components/toggle_switch_widget.dart";
import "package:photos/utils/data_util.dart"; import "package:photos/utils/data_util.dart";
import "package:photos/utils/local_settings.dart"; import "package:photos/utils/local_settings.dart";
import "package:photos/utils/ml_util.dart"; import "package:photos/utils/ml_util.dart";
import "package:photos/utils/wakelock_util.dart";
final _logger = Logger("MachineLearningSettingsPage"); final _logger = Logger("MachineLearningSettingsPage");
@ -41,6 +43,7 @@ class MachineLearningSettingsPage extends StatefulWidget {
class _MachineLearningSettingsPageState class _MachineLearningSettingsPageState
extends State<MachineLearningSettingsPage> { extends State<MachineLearningSettingsPage> {
late InitializationState _state; late InitializationState _state;
final EnteWakeLock _wakeLock = EnteWakeLock();
late StreamSubscription<MLFrameworkInitializationUpdateEvent> late StreamSubscription<MLFrameworkInitializationUpdateEvent>
_eventSubscription; _eventSubscription;
@ -54,6 +57,7 @@ class _MachineLearningSettingsPageState
setState(() {}); setState(() {});
}); });
_fetchState(); _fetchState();
_wakeLock.enable();
} }
void _fetchState() { void _fetchState() {
@ -64,6 +68,7 @@ class _MachineLearningSettingsPageState
void dispose() { void dispose() {
super.dispose(); super.dispose();
_eventSubscription.cancel(); _eventSubscription.cancel();
_wakeLock.disable();
} }
@override @override
@ -439,16 +444,24 @@ class FaceRecognitionStatusWidgetState
}); });
} }
Future<(int, int, double)> getIndexStatus() async { Future<(int, int, double, bool)> getIndexStatus() async {
try { try {
final indexedFiles = await FaceMLDataDB.instance final indexedFiles = await FaceMLDataDB.instance
.getIndexedFileCount(minimumMlVersion: faceMlVersion); .getIndexedFileCount(minimumMlVersion: faceMlVersion);
final indexableFiles = (await getIndexableFileIDs()).length; final indexableFiles = (await getIndexableFileIDs()).length;
final showIndexedFiles = min(indexedFiles, indexableFiles); final showIndexedFiles = min(indexedFiles, indexableFiles);
final pendingFiles = max(indexableFiles - indexedFiles, 0); final pendingFiles = max(indexableFiles - indexedFiles, 0);
final clusteringDoneRatio = await FaceMLDataDB.instance.getClusteredToIndexableFilesRatio(); final clusteringDoneRatio =
await FaceMLDataDB.instance.getClusteredToIndexableFilesRatio();
final bool deviceIsHealthy =
MachineLearningController.instance.isDeviceHealthy;
return (showIndexedFiles, pendingFiles, clusteringDoneRatio); return (
showIndexedFiles,
pendingFiles,
clusteringDoneRatio,
deviceIsHealthy
);
} catch (e, s) { } catch (e, s) {
_logger.severe('Error getting face recognition status', e, s); _logger.severe('Error getting face recognition status', e, s);
rethrow; rethrow;
@ -480,6 +493,14 @@ class FaceRecognitionStatusWidgetState
final double clusteringDoneRatio = snapshot.data!.$3; final double clusteringDoneRatio = snapshot.data!.$3;
final double clusteringPercentage = final double clusteringPercentage =
(clusteringDoneRatio * 100).clamp(0, 100); (clusteringDoneRatio * 100).clamp(0, 100);
final bool isDeviceHealthy = snapshot.data!.$4;
if (!isDeviceHealthy &&
(pendingFiles > 0 || clusteringPercentage < 99)) {
return MenuSectionDescriptionWidget(
content: S.of(context).indexingIsPaused,
);
}
return Column( return Column(
children: [ children: [

View file

@ -17,9 +17,9 @@ import 'package:photos/ui/viewer/file/video_controls.dart';
import "package:photos/utils/dialog_util.dart"; import "package:photos/utils/dialog_util.dart";
import 'package:photos/utils/file_util.dart'; import 'package:photos/utils/file_util.dart';
import 'package:photos/utils/toast_util.dart'; import 'package:photos/utils/toast_util.dart';
import "package:photos/utils/wakelock_util.dart";
import 'package:video_player/video_player.dart'; import 'package:video_player/video_player.dart';
import 'package:visibility_detector/visibility_detector.dart'; import 'package:visibility_detector/visibility_detector.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
class VideoWidget extends StatefulWidget { class VideoWidget extends StatefulWidget {
final EnteFile file; final EnteFile file;
@ -45,7 +45,7 @@ class _VideoWidgetState extends State<VideoWidget> {
ChewieController? _chewieController; ChewieController? _chewieController;
final _progressNotifier = ValueNotifier<double?>(null); final _progressNotifier = ValueNotifier<double?>(null);
bool _isPlaying = false; bool _isPlaying = false;
bool _wakeLockEnabledHere = false; final EnteWakeLock _wakeLock = EnteWakeLock();
@override @override
void initState() { void initState() {
@ -126,13 +126,7 @@ class _VideoWidgetState extends State<VideoWidget> {
_chewieController?.dispose(); _chewieController?.dispose();
_progressNotifier.dispose(); _progressNotifier.dispose();
if (_wakeLockEnabledHere) { _wakeLock.dispose();
unawaited(
WakelockPlus.enabled.then((isEnabled) {
isEnabled ? WakelockPlus.disable() : null;
}),
);
}
super.dispose(); super.dispose();
} }
@ -257,17 +251,10 @@ class _VideoWidgetState extends State<VideoWidget> {
Future<void> _keepScreenAliveOnPlaying(bool isPlaying) async { Future<void> _keepScreenAliveOnPlaying(bool isPlaying) async {
if (isPlaying) { if (isPlaying) {
return WakelockPlus.enabled.then((value) { _wakeLock.enable();
if (value == false) {
WakelockPlus.enable();
//wakeLockEnabledHere will not be set to true if wakeLock is already enabled from settings on iOS.
//We shouldn't disable when video is not playing if it was enabled manually by the user from ente settings by user.
_wakeLockEnabledHere = true;
}
});
} }
if (_wakeLockEnabledHere && !isPlaying) { if (!isPlaying) {
return WakelockPlus.disable(); _wakeLock.disable();
} }
} }

View file

@ -0,0 +1,38 @@
import "dart:async" show unawaited;
import "package:wakelock_plus/wakelock_plus.dart";
class EnteWakeLock {
bool _wakeLockEnabledHere = false;
void enable() {
WakelockPlus.enabled.then((value) {
if (value == false) {
WakelockPlus.enable();
//wakeLockEnabledHere will not be set to true if wakeLock is already enabled from settings on iOS.
//We shouldn't disable when video is not playing if it was enabled manually by the user from ente settings by user.
_wakeLockEnabledHere = true;
}
});
}
void disable() {
if (_wakeLockEnabledHere) {
WakelockPlus.disable();
}
}
void dispose() {
if (_wakeLockEnabledHere) {
unawaited(
WakelockPlus.enabled.then((isEnabled) {
isEnabled ? WakelockPlus.disable() : null;
}),
);
}
}
static Future<void> toggle({required bool enable}) async {
await WakelockPlus.toggle(enable: enable);
}
}