Merge remote-tracking branch 'origin/master' into share_to_ente

This commit is contained in:
Neeraj Gupta 2021-07-22 13:16:22 +05:30
commit 77c2489714
28 changed files with 301 additions and 203 deletions

View file

@ -10,7 +10,7 @@ class ThumbnailLruCache {
static Uint8List get(File photo, [int size]) {
return _map.get(photo.generatedID.toString() +
"_" +
(size != null ? size.toString() : THUMBNAIL_LARGE_SIZE.toString()));
(size != null ? size.toString() : kThumbnailLargeSize.toString()));
}
static void put(
@ -21,7 +21,7 @@ class ThumbnailLruCache {
_map.put(
photo.generatedID.toString() +
"_" +
(size != null ? size.toString() : THUMBNAIL_LARGE_SIZE.toString()),
(size != null ? size.toString() : kThumbnailLargeSize.toString()),
imageData);
}
}

View file

@ -46,6 +46,8 @@ class Configuration {
static const tokenKey = "token";
static const encryptedTokenKey = "encrypted_token";
static const userIDKey = "user_id";
static const hasMigratedSecureStorageToFirstUnlockKey =
"has_migrated_secure_storage_to_first_unlock";
final kTempFolderDeletionTimeBuffer = Duration(days: 1).inMicroseconds;
@ -61,12 +63,15 @@ class Configuration {
String _thumbnailCacheDirectory;
String _volatilePassword;
final _secureStorageOptionsIOS =
IOSOptions(accessibility: IOSAccessibility.first_unlock_this_device);
Future<void> init() async {
_preferences = await SharedPreferences.getInstance();
_secureStorage = FlutterSecureStorage();
_documentsDirectory = (await getApplicationDocumentsDirectory()).path;
_tempDirectory = _documentsDirectory + "/temp/";
final tempDirectory = new io.Directory(_tempDirectory);
final tempDirectory = io.Directory(_tempDirectory);
try {
final currentTime = DateTime.now().microsecondsSinceEpoch;
if (tempDirectory.existsSync() &&
@ -86,10 +91,17 @@ class Configuration {
(await getTemporaryDirectory()).path + "/thumbnail-cache";
io.Directory(_thumbnailCacheDirectory).createSync(recursive: true);
if (!_preferences.containsKey(tokenKey)) {
await _secureStorage.deleteAll();
await _secureStorage.deleteAll(iOptions: _secureStorageOptionsIOS);
} else {
_key = await _secureStorage.read(key: keyKey);
_secretKey = await _secureStorage.read(key: secretKeyKey);
_key = await _secureStorage.read(
key: keyKey,
iOptions: _secureStorageOptionsIOS,
);
_secretKey = await _secureStorage.read(
key: secretKeyKey,
iOptions: _secureStorageOptionsIOS,
);
await _migrateSecurityStorageToFirstUnlock();
}
}
@ -103,7 +115,7 @@ class Configuration {
}
}
await _preferences.clear();
await _secureStorage.deleteAll();
await _secureStorage.deleteAll(iOptions: _secureStorageOptionsIOS);
_key = null;
_cachedToken = null;
_secretKey = null;
@ -197,7 +209,7 @@ class Configuration {
attributes.memLimit,
attributes.opsLimit,
);
var key;
Uint8List key;
try {
key = CryptoUtil.decryptSync(Sodium.base642bin(attributes.encryptedKey),
kek, Sodium.base642bin(attributes.keyDecryptionNonce));
@ -241,7 +253,7 @@ class Configuration {
Future<void> recover(String recoveryKey) async {
final keyAttributes = getKeyAttributes();
var masterKey;
Uint8List masterKey;
try {
masterKey = await CryptoUtil.decrypt(
Sodium.base642bin(keyAttributes.masterKeyEncryptedWithRecoveryKey),
@ -249,7 +261,7 @@ class Configuration {
Sodium.base642bin(keyAttributes.masterKeyDecryptionNonce));
} catch (e) {
_logger.severe(e);
throw e;
rethrow;
}
await setKey(Sodium.bin2base64(masterKey));
}
@ -262,9 +274,7 @@ class Configuration {
}
String getToken() {
if (_cachedToken == null) {
_cachedToken = _preferences.getString(tokenKey);
}
_cachedToken ??= _preferences.getString(tokenKey);
return _cachedToken;
}
@ -309,7 +319,7 @@ class Configuration {
if (_preferences.containsKey(foldersToBackUpKey)) {
return _preferences.getStringList(foldersToBackUpKey).toSet();
} else {
return Set<String>();
return <String>{};
}
}
@ -342,8 +352,7 @@ class Configuration {
}
Future<void> setKeyAttributes(KeyAttributes attributes) async {
await _preferences.setString(
keyAttributesKey, attributes == null ? null : attributes.toJson());
await _preferences.setString(keyAttributesKey, attributes?.toJson());
}
KeyAttributes getKeyAttributes() {
@ -358,18 +367,32 @@ class Configuration {
Future<void> setKey(String key) async {
_key = key;
if (key == null) {
await _secureStorage.delete(key: keyKey);
await _secureStorage.delete(
key: keyKey,
iOptions: _secureStorageOptionsIOS,
);
} else {
await _secureStorage.write(key: keyKey, value: key);
await _secureStorage.write(
key: keyKey,
value: key,
iOptions: _secureStorageOptionsIOS,
);
}
}
Future<void> setSecretKey(String secretKey) async {
_secretKey = secretKey;
if (secretKey == null) {
await _secureStorage.delete(key: secretKeyKey);
await _secureStorage.delete(
key: secretKeyKey,
iOptions: _secureStorageOptionsIOS,
);
} else {
await _secureStorage.write(key: secretKeyKey, value: secretKey);
await _secureStorage.write(
key: secretKeyKey,
value: secretKey,
iOptions: _secureStorageOptionsIOS,
);
}
}
@ -477,4 +500,25 @@ class Configuration {
bool hasSkippedBackupFolderSelection() {
return _preferences.getBool(keyHasSkippedBackupFolderSelection) ?? false;
}
Future<void> _migrateSecurityStorageToFirstUnlock() async {
final hasMigratedSecureStorageToFirstUnlock =
_preferences.getBool(hasMigratedSecureStorageToFirstUnlockKey) ?? false;
if (!hasMigratedSecureStorageToFirstUnlock &&
_key != null &&
_secretKey != null) {
await _secureStorage.write(
key: keyKey,
value: _key,
iOptions: _secureStorageOptionsIOS,
);
await _secureStorage.write(
key: secretKeyKey,
value: _secretKey,
iOptions: _secureStorageOptionsIOS,
);
await _preferences.setBool(
hasMigratedSecureStorageToFirstUnlockKey, true);
}
}
}

View file

@ -1,12 +1,13 @@
const int THUMBNAIL_SMALL_SIZE = 256;
const int THUMBNAIL_QUALITY = 50;
const int THUMBNAIL_LARGE_SIZE = 512;
const int COMPRESSED_THUMBNAIL_RESOLUTION = 1080;
const int THUMBNAIL_DATA_LIMIT = 100 * 1024;
const String SENTRY_DSN =
const int kThumbnailSmallSize = 256;
const int kThumbnailQuality = 50;
const int kThumbnailLargeSize = 512;
const int kCompressedThumbnailResolution = 1080;
const int kThumbnailDataLimit = 100 * 1024;
const String kSentryDSN =
"https://93b8ea6f54f442dc8408ebccdff6fe7a@errors.ente.io/2";
const String SENTRY_DEBUG_DSN =
const String kSentryDebugDSN =
"https://b31c8af8384a4ce980509b8f592a67eb@errors.ente.io/3";
const String ROADMAP_URL = "https://roadmap.ente.io";
const int MICRO_SECONDS_IN_DAY = 86400000000;
const int ANDROID_11_SDK_INT = 30;
const String kRoadmapURL = "https://roadmap.ente.io";
const int kMicroSecondsInDay = 86400000000;
const int kAndroid11SDKINT = 30;
const int kGalleryLoadStartTime = -8000000000000000; // Wednesday, March 6, 1748

View file

@ -39,14 +39,14 @@ class CollectionsDB {
CollectionsDB._privateConstructor();
static final CollectionsDB instance = CollectionsDB._privateConstructor();
static Database _database;
static Future<Database> _dbFuture;
Future<Database> get database async {
if (_database != null) return _database;
_database = await _initDatabase();
return _database;
_dbFuture ??= _initDatabase();
return _dbFuture;
}
_initDatabase() async {
Future<Database> _initDatabase() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, _databaseName);
return await openDatabaseWithMigration(path, dbConfig);

View file

@ -46,28 +46,34 @@ class FilesDB {
static final columnThumbnailDecryptionHeader = 'thumbnail_decryption_header';
static final columnMetadataDecryptionHeader = 'metadata_decryption_header';
static final intitialScript = [...createTable(table), ...addIndex()];
static final migrationScripts = [...alterDeviceFolderToAllowNULL()];
static final initializationScript = [...createTable(table)];
static final migrationScripts = [
...alterDeviceFolderToAllowNULL(),
...alterTimestampColumnTypes(),
...addIndices(),
];
final dbConfig = MigrationConfig(
initializationScript: intitialScript, migrationScripts: migrationScripts);
initializationScript: initializationScript,
migrationScripts: migrationScripts);
// make this a singleton class
FilesDB._privateConstructor();
static final FilesDB instance = FilesDB._privateConstructor();
// only have a single app-wide reference to the database
static Database _database;
static Future<Database> _dbFuture;
Future<Database> get database async {
if (_database != null) return _database;
// lazily instantiate the db the first time it is accessed
_database = await _initDatabase();
return _database;
_dbFuture ??= _initDatabase();
return _dbFuture;
}
// this opens the database (and creates it if it doesn't exist)
_initDatabase() async {
Future<Database> _initDatabase() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, _databaseName);
_logger.info("DB path " + path);
return await openDatabaseWithMigration(path, dbConfig);
}
@ -101,13 +107,19 @@ class FilesDB {
];
}
static List<String> addIndex() {
static List<String> addIndices() {
return [
'''
CREATE INDEX collection_id_index ON $table($columnCollectionID);
CREATE INDEX device_folder_index ON $table($columnDeviceFolder);
CREATE INDEX creation_time_index ON $table($columnCreationTime);
CREATE INDEX updation_time_index ON $table($columnUpdationTime);
CREATE INDEX IF NOT EXISTS collection_id_index ON $table($columnCollectionID);
''',
'''
CREATE INDEX IF NOT EXISTS device_folder_index ON $table($columnDeviceFolder);
''',
'''
CREATE INDEX IF NOT EXISTS creation_time_index ON $table($columnCreationTime);
''',
'''
CREATE INDEX IF NOT EXISTS updation_time_index ON $table($columnUpdationTime);
'''
];
}
@ -128,6 +140,67 @@ class FilesDB {
];
}
static List<String> alterTimestampColumnTypes() {
return [
'''
DROP TABLE IF EXISTS $tempTable;
''',
'''
CREATE TABLE $tempTable (
$columnGeneratedID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
$columnLocalID TEXT,
$columnUploadedFileID INTEGER DEFAULT -1,
$columnOwnerID INTEGER,
$columnCollectionID INTEGER DEFAULT -1,
$columnTitle TEXT NOT NULL,
$columnDeviceFolder TEXT,
$columnLatitude REAL,
$columnLongitude REAL,
$columnFileType INTEGER,
$columnModificationTime INTEGER NOT NULL,
$columnEncryptedKey TEXT,
$columnKeyDecryptionNonce TEXT,
$columnFileDecryptionHeader TEXT,
$columnThumbnailDecryptionHeader TEXT,
$columnMetadataDecryptionHeader TEXT,
$columnCreationTime INTEGER NOT NULL,
$columnUpdationTime INTEGER,
UNIQUE($columnLocalID, $columnUploadedFileID, $columnCollectionID)
);
''',
'''
INSERT INTO $tempTable
SELECT
$columnGeneratedID,
$columnLocalID,
$columnUploadedFileID,
$columnOwnerID,
$columnCollectionID,
$columnTitle,
$columnDeviceFolder,
$columnLatitude,
$columnLongitude,
$columnFileType,
CAST($columnModificationTime AS INTEGER),
$columnEncryptedKey,
$columnKeyDecryptionNonce,
$columnFileDecryptionHeader,
$columnThumbnailDecryptionHeader,
$columnMetadataDecryptionHeader,
CAST($columnCreationTime AS INTEGER),
CAST($columnUpdationTime AS INTEGER)
FROM $table;
''',
'''
DROP TABLE $table;
''',
'''
ALTER TABLE $tempTable
RENAME TO $table;
''',
];
}
Future<void> clearTable() async {
final db = await instance.database;
await db.delete(table);
@ -208,7 +281,7 @@ class FilesDB {
collectionID,
],
);
final ids = Set<int>();
final ids = <int>{};
for (final result in results) {
ids.add(result[columnUploadedFileID]);
}
@ -223,8 +296,8 @@ class FilesDB {
where:
'$columnLocalID IS NOT NULL AND ($columnUploadedFileID IS NOT NULL AND $columnUploadedFileID IS NOT -1)',
);
final localIDs = Set<String>();
final uploadedIDs = Set<int>();
final localIDs = <String>{};
final uploadedIDs = <int>{};
for (final result in results) {
localIDs.add(result[columnLocalID]);
uploadedIDs.add(result[columnUploadedFileID]);
@ -239,7 +312,7 @@ class FilesDB {
final results = await db.query(
table,
where:
'$columnCreationTime >= ? AND $columnCreationTime <= ? AND $columnIsDeleted = 0 AND ($columnCollectionID IS NOT NULL AND $columnCollectionID IS NOT -1)',
'$columnCreationTime >= ? AND $columnCreationTime <= ? AND ($columnCollectionID IS NOT NULL AND $columnCollectionID IS NOT -1)',
whereArgs: [startTime, endTime],
orderBy:
'$columnCreationTime ' + order + ', $columnModificationTime ' + order,
@ -256,7 +329,7 @@ class FilesDB {
final results = await db.query(
table,
where:
'$columnCreationTime >= ? AND $columnCreationTime <= ? AND $columnIsDeleted = 0 AND ($columnLocalID IS NOT NULL OR ($columnCollectionID IS NOT NULL AND $columnCollectionID IS NOT -1))',
'$columnCreationTime >= ? AND $columnCreationTime <= ? AND ($columnLocalID IS NOT NULL OR ($columnCollectionID IS NOT NULL AND $columnCollectionID IS NOT -1))',
whereArgs: [startTime, endTime],
orderBy:
'$columnCreationTime ' + order + ', $columnModificationTime ' + order,
@ -279,13 +352,13 @@ class FilesDB {
final results = await db.query(
table,
where:
'$columnCreationTime >= ? AND $columnCreationTime <= ? AND $columnIsDeleted = 0 AND (($columnLocalID IS NOT NULL AND $columnDeviceFolder IN ($inParam)) OR ($columnCollectionID IS NOT NULL AND $columnCollectionID IS NOT -1))',
'$columnCreationTime >= ? AND $columnCreationTime <= ? AND (($columnLocalID IS NOT NULL AND $columnDeviceFolder IN ($inParam)) OR ($columnCollectionID IS NOT NULL AND $columnCollectionID IS NOT -1))',
whereArgs: [startTime, endTime],
orderBy:
'$columnCreationTime ' + order + ', $columnModificationTime ' + order,
limit: limit,
);
final uploadedFileIDs = Set<int>();
final uploadedFileIDs = <int>{};
final files = _convertToFiles(results);
final List<File> deduplicatedFiles = [];
for (final file in files) {
@ -307,7 +380,7 @@ class FilesDB {
final results = await db.query(
table,
where:
'$columnCollectionID = ? AND $columnCreationTime >= ? AND $columnCreationTime <= ? AND $columnIsDeleted = 0',
'$columnCollectionID = ? AND $columnCreationTime >= ? AND $columnCreationTime <= ?',
whereArgs: [collectionID, startTime, endTime],
orderBy:
'$columnCreationTime ' + order + ', $columnModificationTime ' + order,
@ -325,11 +398,11 @@ class FilesDB {
final results = await db.query(
table,
where:
'$columnDeviceFolder = ? AND $columnCreationTime >= ? AND $columnCreationTime <= ? AND $columnLocalID IS NOT NULL AND $columnIsDeleted = 0',
'$columnDeviceFolder = ? AND $columnCreationTime >= ? AND $columnCreationTime <= ? AND $columnLocalID IS NOT NULL',
whereArgs: [path, startTime, endTime],
orderBy:
'$columnCreationTime ' + order + ', $columnModificationTime ' + order,
groupBy: '$columnLocalID',
groupBy: columnLocalID,
limit: limit,
);
final files = _convertToFiles(results);
@ -340,8 +413,7 @@ class FilesDB {
final db = await instance.database;
final results = await db.query(
table,
where:
'$columnLocalID IS NOT NULL AND $columnFileType = 1 AND $columnIsDeleted = 0',
where: '$columnLocalID IS NOT NULL AND $columnFileType = 1',
orderBy: '$columnCreationTime DESC',
);
return _convertToFiles(results);
@ -351,11 +423,10 @@ class FilesDB {
final db = await instance.database;
final results = await db.query(
table,
where:
'$columnLocalID IS NOT NULL AND $columnDeviceFolder = ? AND $columnIsDeleted = 0',
where: '$columnLocalID IS NOT NULL AND $columnDeviceFolder = ?',
whereArgs: [path],
orderBy: '$columnCreationTime DESC',
groupBy: '$columnLocalID',
groupBy: columnLocalID,
);
return _convertToFiles(results);
}
@ -376,28 +447,12 @@ class FilesDB {
}
final results = await db.query(
table,
where: whereClause + " AND $columnIsDeleted = 0",
where: whereClause,
orderBy: '$columnCreationTime ASC',
);
return _convertToFiles(results);
}
Future<List<int>> getDeletedFileIDs() async {
final db = await instance.database;
final rows = await db.query(
table,
columns: [columnUploadedFileID],
distinct: true,
where: '$columnIsDeleted = 1',
orderBy: '$columnCreationTime DESC',
);
final result = List<int>();
for (final row in rows) {
result.add(row[columnUploadedFileID]);
}
return result;
}
Future<List<File>> getFilesToBeUploadedWithinFolders(
Set<String> folders) async {
if (folders.isEmpty) {
@ -414,7 +469,7 @@ class FilesDB {
where:
'($columnUploadedFileID IS NULL OR $columnUploadedFileID IS -1) AND $columnDeviceFolder IN ($inParam)',
orderBy: '$columnCreationTime DESC',
groupBy: '$columnLocalID',
groupBy: columnLocalID,
);
return _convertToFiles(results);
}
@ -426,7 +481,7 @@ class FilesDB {
where:
'($columnUploadedFileID IS NULL OR $columnUploadedFileID IS -1) AND $columnLocalID IS NOT NULL',
orderBy: '$columnCreationTime DESC',
groupBy: '$columnLocalID',
groupBy: columnLocalID,
);
return _convertToFiles(results);
}
@ -438,7 +493,7 @@ class FilesDB {
where:
'($columnCollectionID IS NOT NULL AND $columnCollectionID IS NOT -1) AND ($columnUploadedFileID IS NULL OR $columnUploadedFileID IS -1)',
orderBy: '$columnCreationTime DESC',
groupBy: '$columnLocalID',
groupBy: columnLocalID,
);
return _convertToFiles(results);
}
@ -449,11 +504,11 @@ class FilesDB {
table,
columns: [columnUploadedFileID],
where:
'($columnLocalID IS NOT NULL AND ($columnUploadedFileID IS NOT NULL AND $columnUploadedFileID IS NOT -1) AND $columnUpdationTime IS NULL AND $columnIsDeleted = 0)',
'($columnLocalID IS NOT NULL AND ($columnUploadedFileID IS NOT NULL AND $columnUploadedFileID IS NOT -1) AND $columnUpdationTime IS NULL)',
orderBy: '$columnCreationTime DESC',
distinct: true,
);
final uploadedFileIDs = List<int>();
final uploadedFileIDs = <int>[];
for (final row in rows) {
uploadedFileIDs.add(row[columnUploadedFileID]);
}
@ -484,7 +539,7 @@ class FilesDB {
distinct: true,
where: '$columnLocalID IS NOT NULL',
);
final result = Set<String>();
final result = <String>{};
for (final row in rows) {
result.add(row[columnLocalID]);
}
@ -497,7 +552,7 @@ class FilesDB {
table,
columns: [columnUploadedFileID],
where:
'($columnLocalID IS NOT NULL AND ($columnUploadedFileID IS NOT NULL AND $columnUploadedFileID IS NOT -1) AND $columnUpdationTime IS NOT NULL AND $columnIsDeleted = 0)',
'($columnLocalID IS NOT NULL AND ($columnUploadedFileID IS NOT NULL AND $columnUploadedFileID IS NOT -1) AND $columnUpdationTime IS NOT NULL)',
distinct: true,
);
return rows.length;
@ -666,7 +721,7 @@ class FilesDB {
''');
final files = _convertToFiles(rows);
// TODO: Do this de-duplication within the SQL Query
final folderMap = Map<String, File>();
final folderMap = <String, File>{};
for (final file in files) {
if (folderMap.containsKey(file.deviceFolder)) {
if (folderMap[file.deviceFolder].updationTime < file.updationTime) {
@ -695,7 +750,7 @@ class FilesDB {
''');
final files = _convertToFiles(rows);
// TODO: Do this de-duplication within the SQL Query
final collectionMap = Map<int, File>();
final collectionMap = <int, File>{};
for (final file in files) {
if (collectionMap.containsKey(file.collectionID)) {
if (collectionMap[file.collectionID].updationTime < file.updationTime) {
@ -711,7 +766,7 @@ class FilesDB {
final db = await instance.database;
final rows = await db.query(
table,
where: '$columnCollectionID = ? AND $columnIsDeleted = 0',
where: '$columnCollectionID = ?',
whereArgs: [collectionID],
orderBy: '$columnUpdationTime DESC',
limit: 1,
@ -731,7 +786,7 @@ class FilesDB {
WHERE $columnLocalID IS NOT NULL
GROUP BY $columnDeviceFolder
''');
final result = Map<String, int>();
final result = <String, int>{};
for (final row in rows) {
result[row[columnDeviceFolder]] = row["count"];
}
@ -759,7 +814,7 @@ class FilesDB {
}
Map<String, dynamic> _getRowForFile(File file) {
final row = new Map<String, dynamic>();
final row = <String, dynamic>{};
if (file.generatedID != null) {
row[columnGeneratedID] = file.generatedID;
}
@ -795,7 +850,7 @@ class FilesDB {
}
Map<String, dynamic> _getRowForFileWithoutCollection(File file) {
final row = new Map<String, dynamic>();
final row = <String, dynamic>{};
row[columnLocalID] = file.localID;
row[columnUploadedFileID] = file.uploadedFileID ?? -1;
row[columnOwnerID] = file.ownerID;
@ -839,11 +894,9 @@ class FilesDB {
file.location = Location(row[columnLatitude], row[columnLongitude]);
}
file.fileType = getFileType(row[columnFileType]);
file.creationTime = int.parse(row[columnCreationTime]);
file.modificationTime = int.parse(row[columnModificationTime]);
file.updationTime = row[columnUpdationTime] == null
? -1
: int.parse(row[columnUpdationTime]);
file.creationTime = row[columnCreationTime];
file.modificationTime = row[columnModificationTime];
file.updationTime = row[columnUpdationTime] ?? -1;
file.encryptedKey = row[columnEncryptedKey];
file.keyDecryptionNonce = row[columnKeyDecryptionNonce];
file.fileDecryptionHeader = row[columnFileDecryptionHeader];

View file

@ -2,9 +2,9 @@ import 'dart:async';
import 'dart:io';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:photos/models/memory.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
class MemoriesDB {
static final _databaseName = "ente.memories.db";
@ -18,14 +18,13 @@ class MemoriesDB {
MemoriesDB._privateConstructor();
static final MemoriesDB instance = MemoriesDB._privateConstructor();
static Database _database;
static Future<Database> _dbFuture;
Future<Database> get database async {
if (_database != null) return _database;
_database = await _initDatabase();
return _database;
_dbFuture ??= _initDatabase();
return _dbFuture;
}
_initDatabase() async {
Future<Database> _initDatabase() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, _databaseName);
return await openDatabase(

View file

@ -2,9 +2,9 @@ import 'dart:async';
import 'dart:io';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:photos/models/public_key.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
class PublicKeysDB {
static final _databaseName = "ente.public_keys.db";
@ -18,14 +18,14 @@ class PublicKeysDB {
PublicKeysDB._privateConstructor();
static final PublicKeysDB instance = PublicKeysDB._privateConstructor();
static Database _database;
static Future<Database> _dbFuture;
Future<Database> get database async {
if (_database != null) return _database;
_database = await _initDatabase();
return _database;
_dbFuture ??= _initDatabase();
return _dbFuture;
}
_initDatabase() async {
Future<Database> _initDatabase() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, _databaseName);
return await openDatabase(

View file

@ -2,8 +2,8 @@ import 'dart:async';
import 'dart:io';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
class UploadLocksDB {
static const _databaseName = "ente.upload_locks.db";
@ -17,14 +17,13 @@ class UploadLocksDB {
UploadLocksDB._privateConstructor();
static final UploadLocksDB instance = UploadLocksDB._privateConstructor();
static Database _database;
static Future<Database> _dbFuture;
Future<Database> get database async {
if (_database != null) return _database;
_database = await _initDatabase();
return _database;
_dbFuture ??= _initDatabase();
return _dbFuture;
}
_initDatabase() async {
Future<Database> _initDatabase() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, _databaseName);
return await openDatabase(

View file

@ -5,9 +5,10 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:in_app_purchase/in_app_purchase.dart';
import 'package:logging/logging.dart';
import 'package:path_provider/path_provider.dart';
import 'package:photos/core/constants.dart';
import 'package:photos/core/configuration.dart';
import 'package:photos/core/constants.dart';
import 'package:photos/core/network.dart';
import 'package:photos/db/upload_locks_db.dart';
import 'package:photos/services/billing_service.dart';
@ -25,7 +26,6 @@ import 'package:photos/utils/crypto_util.dart';
import 'package:photos/utils/file_uploader.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:super_logging/super_logging.dart';
import 'package:logging/logging.dart';
final _logger = Logger("main");
@ -166,7 +166,7 @@ Future _runWithLogs(Function() function, {String prefix = ""}) async {
body: function,
logDirPath: (await getTemporaryDirectory()).path + "/logs",
maxLogFiles: 5,
sentryDsn: kDebugMode ? SENTRY_DEBUG_DSN : SENTRY_DSN,
sentryDsn: kDebugMode ? kSentryDebugDSN : kSentryDSN,
enableInDebugMode: true,
prefix: prefix,
));

View file

@ -134,10 +134,16 @@ class File {
return localID == null && uploadedFileID != null;
}
bool isCachedInAppSandbox() {
return localID != null && localID.startsWith("ente-upload-cache");
}
bool hasLocation() {
return location != null &&
(location.longitude != 0 || location.latitude != 0);
}
@override
String toString() {
return '''File(generatedId: $generatedID, uploadedFileId: $uploadedFileID,

View file

@ -35,9 +35,9 @@ class CollectionsService {
SharedPreferences _prefs;
Future<List<File>> _cachedLatestFiles;
final _dio = Network.instance.getDio();
final _localCollections = Map<String, Collection>();
final _collectionIDToCollections = Map<int, Collection>();
final _cachedKeys = Map<int, Uint8List>();
final _localCollections = <String, Collection>{};
final _collectionIDToCollections = <int, Collection>{};
final _cachedKeys = <int, Uint8List>{};
CollectionsService._privateConstructor() {
_db = CollectionsDB.instance;
@ -72,7 +72,7 @@ class CollectionsService {
// Might not have synced the collection fully
final fetchedCollections =
await _fetchCollections(lastCollectionUpdationTime ?? 0);
final updatedCollections = List<Collection>();
final updatedCollections = <Collection>[];
int maxUpdationTime = lastCollectionUpdationTime;
for (final collection in fetchedCollections) {
if (collection.isDeleted) {
@ -100,7 +100,7 @@ class CollectionsService {
return collections;
}
Future<void> clearCache() {
void clearCache() {
_localCollections.clear();
_collectionIDToCollections.clear();
_cachedKeys.clear();
@ -108,7 +108,7 @@ class CollectionsService {
Future<List<Collection>> getCollectionsToBeSynced() async {
final collections = await _db.getAllCollections();
final updatedCollections = List<Collection>();
final updatedCollections = <Collection>[];
for (final c in collections) {
if (c.updationTime > getCollectionSyncTime(c.id)) {
updatedCollections.add(c);
@ -118,18 +118,13 @@ class CollectionsService {
}
int getCollectionSyncTime(int collectionID) {
var syncTime =
_prefs.getInt(_collectionSyncTimeKeyPrefix + collectionID.toString());
if (syncTime == null) {
syncTime = 0;
}
return syncTime;
return _prefs
.getInt(_collectionSyncTimeKeyPrefix + collectionID.toString()) ??
0;
}
Future<List<File>> getLatestCollectionFiles() {
if (_cachedLatestFiles == null) {
_cachedLatestFiles = _filesDB.getLatestCollectionFiles();
}
_cachedLatestFiles ??= _filesDB.getLatestCollectionFiles();
return _cachedLatestFiles;
}
@ -161,7 +156,7 @@ class CollectionsService {
)
.then((response) {
_logger.info(response.toString());
final sharees = List<User>();
final sharees = <User>[];
for (final user in response.data["sharees"]) {
sharees.add(User.fromMap(user));
}
@ -187,7 +182,7 @@ class CollectionsService {
if (e.response.statusCode == 402) {
throw SharingNotPermittedForFreeAccountsError();
}
throw e;
rethrow;
}
RemoteSyncService.instance.sync(silently: true);
}
@ -209,7 +204,7 @@ class CollectionsService {
_db.insert([_collectionIDToCollections[collectionID]]);
} catch (e) {
_logger.severe(e);
throw e;
rethrow;
}
RemoteSyncService.instance.sync(silently: true);
}
@ -257,7 +252,7 @@ class CollectionsService {
if (e is DioError && e.response?.statusCode == 401) {
throw UnauthorizedError();
}
throw e;
rethrow;
}
}
@ -313,7 +308,7 @@ class CollectionsService {
}
Future<void> addToCollection(int collectionID, List<File> files) {
final params = Map<String, dynamic>();
final params = <String, dynamic>{};
params["collectionID"] = collectionID;
for (final file in files) {
final key = decryptFileKey(file);
@ -344,11 +339,11 @@ class CollectionsService {
}
Future<void> removeFromCollection(int collectionID, List<File> files) async {
final params = Map<String, dynamic>();
final params = <String, dynamic>{};
params["collectionID"] = collectionID;
for (final file in files) {
if (params["fileIDs"] == null) {
params["fileIDs"] = List<int>();
params["fileIDs"] = <int>[];
}
params["fileIDs"].add(file.uploadedFileID);
}
@ -401,7 +396,7 @@ class CollectionsService {
Collection _getCollectionWithDecryptedName(Collection collection) {
if (collection.encryptedName != null &&
collection.encryptedName.isNotEmpty) {
var name;
String name;
try {
final result = CryptoUtil.decryptSync(
Sodium.base642bin(collection.encryptedName),
@ -429,7 +424,7 @@ class CollectionsService {
if (attempt < kMaximumWriteAttempts) {
return _updateDB(collections, attempt: attempt++);
} else {
throw e;
rethrow;
}
}
}

View file

@ -27,7 +27,7 @@ class MemoriesService extends ChangeNotifier {
_cachedMemories = null;
});
await _memoriesDB.clearMemoriesSeenBeforeTime(
DateTime.now().microsecondsSinceEpoch - (7 * MICRO_SECONDS_IN_DAY));
DateTime.now().microsecondsSinceEpoch - (7 * kMicroSecondsInDay));
}
void clearCache() {

View file

@ -79,7 +79,7 @@ class RemoteSyncService {
Future<bool> _uploadDiff() async {
final foldersToBackUp = Configuration.instance.getPathsToBackUp();
var filesToBeUploaded;
List<File> filesToBeUploaded;
if (LocalSyncService.instance.hasGrantedLimitedPermissions() &&
foldersToBackUp.isEmpty) {
filesToBeUploaded = await _db.getAllLocalFiles();
@ -149,7 +149,7 @@ class RemoteSyncService {
} on UserCancelledUploadError {
// Do nothing
} catch (e) {
throw e;
rethrow;
}
return _completedUploads > 0;
}
@ -223,7 +223,7 @@ class RemoteSyncService {
}
}
await _db.insertMultiple(toBeInserted);
if (toBeInserted.length > 0) {
if (toBeInserted.isNotEmpty) {
await _collectionsService.setCollectionSyncTime(
collectionID, toBeInserted[toBeInserted.length - 1].updationTime);
}

View file

@ -231,7 +231,7 @@ class SyncService {
final lastNotificationShownTime =
_prefs.getInt(kLastStorageLimitExceededNotificationPushTime) ?? 0;
final now = DateTime.now().microsecondsSinceEpoch;
if ((now - lastNotificationShownTime) > MICRO_SECONDS_IN_DAY) {
if ((now - lastNotificationShownTime) > kMicroSecondsInDay) {
await _prefs.setInt(kLastStorageLimitExceededNotificationPushTime, now);
NotificationService.instance.showNotification(
"storage limit exceeded", "sorry, we had to pause your backups");

View file

@ -51,7 +51,7 @@ class UpdateService {
_prefs.getInt(kUpdateAvailableShownTimeKey) ?? 0;
final now = DateTime.now().microsecondsSinceEpoch;
final hasBeen3DaysSinceLastNotification =
(now - lastNotificationShownTime) > (3 * MICRO_SECONDS_IN_DAY);
(now - lastNotificationShownTime) > (3 * kMicroSecondsInDay);
if (shouldUpdate &&
hasBeen3DaysSinceLastNotification &&
_latestVersion.shouldNotify) {

View file

@ -22,9 +22,9 @@ class BlurredFileBackdrop extends StatelessWidget {
key: Key("memory_backdrop" + file.tag()),
),
BackdropFilter(
filter: new ImageFilter.blur(sigmaX: 64.0, sigmaY: 64.0),
child: new Container(
decoration: new BoxDecoration(color: Colors.white.withOpacity(0.0)),
filter: ImageFilter.blur(sigmaX: 64.0, sigmaY: 64.0),
child: Container(
decoration: BoxDecoration(color: Colors.white.withOpacity(0.0)),
),
),
]),

View file

@ -3,6 +3,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:logging/logging.dart';
import 'package:photos/core/constants.dart';
import 'package:photos/models/file.dart';
import 'package:photos/models/file_type.dart';
import 'package:photos/ui/fading_app_bar.dart';
@ -208,7 +209,7 @@ class _DetailPageState extends State<DetailPage> {
}
if (_selectedIndex == _files.length - 1 && !_hasLoadedTillEnd) {
final result = await widget.config.asyncLoader(
0, _files[_selectedIndex].creationTime - 1,
kGalleryLoadStartTime, _files[_selectedIndex].creationTime - 1,
limit: kLoadLimit);
setState(() {
if (!result.hasMore) {

View file

@ -3,6 +3,7 @@ import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:photos/core/constants.dart';
import 'package:photos/core/event_bus.dart';
import 'package:photos/events/event.dart';
import 'package:photos/events/files_updated_event.dart';
@ -100,8 +101,9 @@ class _GalleryState extends State<Gallery> {
Future<FileLoadResult> _loadFiles({int limit}) async {
_logger.info("Loading files");
final startTime = DateTime.now().microsecondsSinceEpoch;
final result = await widget
.asyncLoader(0, DateTime.now().microsecondsSinceEpoch, limit: limit);
final result = await widget.asyncLoader(
kGalleryLoadStartTime, DateTime.now().microsecondsSinceEpoch,
limit: limit);
final endTime = DateTime.now().microsecondsSinceEpoch;
final duration = Duration(microseconds: endTime - startTime);
_logger.info("Time taken to load " +

View file

@ -99,7 +99,7 @@ class _LazyLoadingGalleryState extends State<LazyLoadingGallery> {
DateTime(galleryDate.year, galleryDate.month, galleryDate.day);
final result = await widget.asyncLoader(
dayStartTime.microsecondsSinceEpoch,
dayStartTime.microsecondsSinceEpoch + MICRO_SECONDS_IN_DAY - 1);
dayStartTime.microsecondsSinceEpoch + kMicroSecondsInDay - 1);
if (result.files.isEmpty) {
// All files on this day were deleted, let gallery trigger the reload
} else {

View file

@ -319,8 +319,7 @@ class _ImageEditorPageState extends State<ImageEditorPage> {
newFile.creationTime = widget.originalFile.creationTime;
newFile.collectionID = widget.originalFile.collectionID;
newFile.location = widget.originalFile.location;
if (newFile.location == null ||
(newFile.location.latitude == 0 && newFile.location.longitude == 0)) {
if (!newFile.hasLocation() && widget.originalFile.localID != null) {
final latLong =
await (await widget.originalFile.getAsset()).latlngAsync();
newFile.location = Location(latLong.latitude, latLong.longitude);

View file

@ -72,7 +72,7 @@ class SupportSectionWidget extends StatelessWidget {
final isLoggedIn = Configuration.instance.getToken() != null;
final url = isLoggedIn
? endpoint + "?token=" + Configuration.instance.getToken()
: ROADMAP_URL;
: kRoadmapURL;
return WebPage("roadmap", url);
},
),

View file

@ -1,12 +1,12 @@
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:photos/core/cache/thumbnail_cache.dart';
import 'package:photos/core/constants.dart';
import 'package:photos/core/errors.dart';
import 'package:photos/core/event_bus.dart';
import 'package:photos/db/files_db.dart';
import 'package:photos/events/local_photos_updated_event.dart';
import 'package:photos/models/file.dart';
import 'package:logging/logging.dart';
import 'package:photos/core/constants.dart';
import 'package:photos/models/file_type.dart';
import 'package:photos/ui/common_elements.dart';
import 'package:photos/utils/thumbnail_util.dart';
@ -152,7 +152,7 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
!_isLoadingThumbnail) {
_isLoadingThumbnail = true;
final cachedSmallThumbnail =
ThumbnailLruCache.get(widget.file, THUMBNAIL_SMALL_SIZE);
ThumbnailLruCache.get(widget.file, kThumbnailSmallSize);
if (cachedSmallThumbnail != null) {
_imageProvider = Image.memory(cachedSmallThumbnail).image;
_hasLoadedThumbnail = true;
@ -185,11 +185,12 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
}
return;
}
if (thumbData != null && mounted) {
final imageProvider = Image.memory(thumbData).image;
_cacheAndRender(imageProvider);
}
ThumbnailLruCache.put(widget.file, thumbData, THUMBNAIL_SMALL_SIZE);
ThumbnailLruCache.put(widget.file, thumbData, kThumbnailSmallSize);
}).catchError((e) {
_logger.warning("Could not load image: ", e);
_encounteredErrorLoadingThumbnail = true;

View file

@ -2,15 +2,15 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:logging/logging.dart';
import 'package:photo_view/photo_view.dart';
import 'package:photos/core/cache/image_cache.dart';
import 'package:photos/core/cache/thumbnail_cache.dart';
import 'package:photos/core/constants.dart';
import 'package:photos/core/event_bus.dart';
import 'package:photos/db/files_db.dart';
import 'package:photos/events/local_photos_updated_event.dart';
import 'package:photos/models/file.dart';
import 'package:photos/ui/loading_widget.dart';
import 'package:photo_view/photo_view.dart';
import 'package:photos/core/constants.dart';
import 'package:photos/utils/file_util.dart';
import 'package:photos/utils/thumbnail_util.dart';
@ -119,7 +119,7 @@ class _ZoomableImageState extends State<ZoomableImage>
!_loadedLargeThumbnail &&
!_loadedFinalImage) {
final cachedThumbnail =
ThumbnailLruCache.get(_photo, THUMBNAIL_SMALL_SIZE);
ThumbnailLruCache.get(_photo, kThumbnailSmallSize);
if (cachedThumbnail != null) {
_imageProvider = Image.memory(cachedThumbnail).image;
_loadedSmallThumbnail = true;
@ -131,7 +131,7 @@ class _ZoomableImageState extends State<ZoomableImage>
!_loadedFinalImage) {
_loadingLargeThumbnail = true;
final cachedThumbnail =
ThumbnailLruCache.get(_photo, THUMBNAIL_LARGE_SIZE);
ThumbnailLruCache.get(_photo, kThumbnailLargeSize);
if (cachedThumbnail != null) {
_onLargeThumbnailLoaded(Image.memory(cachedThumbnail).image, context);
} else {
@ -141,14 +141,14 @@ class _ZoomableImageState extends State<ZoomableImage>
return;
}
asset
.thumbDataWithSize(THUMBNAIL_LARGE_SIZE, THUMBNAIL_LARGE_SIZE)
.thumbDataWithSize(kThumbnailLargeSize, kThumbnailLargeSize)
.then((data) {
if (data == null) {
// Deleted file
return;
}
_onLargeThumbnailLoaded(Image.memory(data).image, context);
ThumbnailLruCache.put(_photo, data, THUMBNAIL_LARGE_SIZE);
ThumbnailLruCache.put(_photo, data, kThumbnailLargeSize);
});
});
}

View file

@ -1,6 +1,6 @@
import 'dart:io' as io;
import 'dart:typed_data';
import 'dart:io' as io;
import 'package:computer/computer.dart';
import 'package:flutter_sodium/flutter_sodium.dart';
import 'package:logging/logging.dart';
@ -109,15 +109,15 @@ void chachaDecryptFile(Map<String, dynamic> args) {
}
Uint8List chachaDecryptData(Map<String, dynamic> args) {
final pullState =
Sodium.cryptoSecretstreamXchacha20poly1305InitPull(args["header"], args["key"]);
final pullResult =
Sodium.cryptoSecretstreamXchacha20poly1305Pull(pullState, args["source"], null);
final pullState = Sodium.cryptoSecretstreamXchacha20poly1305InitPull(
args["header"], args["key"]);
final pullResult = Sodium.cryptoSecretstreamXchacha20poly1305Pull(
pullState, args["source"], null);
return pullResult.m;
}
class CryptoUtil {
static Computer _computer = Computer();
static final Computer _computer = Computer();
static init() {
_computer.turnOn(workersCount: 4);
@ -127,7 +127,7 @@ class CryptoUtil {
static EncryptionResult encryptSync(Uint8List source, Uint8List key) {
final nonce = Sodium.randombytesBuf(Sodium.cryptoSecretboxNoncebytes);
final args = Map<String, dynamic>();
final args = <String, dynamic>{};
args["source"] = source;
args["nonce"] = nonce;
args["key"] = key;
@ -141,7 +141,7 @@ class CryptoUtil {
Uint8List key,
Uint8List nonce,
) async {
final args = Map<String, dynamic>();
final args = <String, dynamic>{};
args["cipher"] = cipher;
args["nonce"] = nonce;
args["key"] = key;
@ -153,7 +153,7 @@ class CryptoUtil {
Uint8List key,
Uint8List nonce,
) {
final args = Map<String, dynamic>();
final args = <String, dynamic>{};
args["cipher"] = cipher;
args["nonce"] = nonce;
args["key"] = key;
@ -162,7 +162,7 @@ class CryptoUtil {
static Future<EncryptionResult> encryptChaCha(
Uint8List source, Uint8List key) async {
final args = Map<String, dynamic>();
final args = <String, dynamic>{};
args["source"] = source;
args["key"] = key;
return _computer.compute(chachaEncryptData, param: args);
@ -170,7 +170,7 @@ class CryptoUtil {
static Future<Uint8List> decryptChaCha(
Uint8List source, Uint8List key, Uint8List header) async {
final args = Map<String, dynamic>();
final args = <String, dynamic>{};
args["source"] = source;
args["key"] = key;
args["header"] = header;
@ -182,7 +182,7 @@ class CryptoUtil {
String destinationFilePath, {
Uint8List key,
}) {
final args = Map<String, dynamic>();
final args = <String, dynamic>{};
args["sourceFilePath"] = sourceFilePath;
args["destinationFilePath"] = destinationFilePath;
args["key"] = key;
@ -195,7 +195,7 @@ class CryptoUtil {
Uint8List header,
Uint8List key,
) {
final args = Map<String, dynamic>();
final args = <String, dynamic>{};
args["sourceFilePath"] = sourceFilePath;
args["destinationFilePath"] = destinationFilePath;
args["header"] = header;

View file

@ -147,7 +147,7 @@ Future<bool> deleteLocalFiles(
final List<String> deletedIDs = [];
if (Platform.isAndroid) {
final androidInfo = await DeviceInfoPlugin().androidInfo;
if (androidInfo.version.sdkInt < ANDROID_11_SDK_INT) {
if (androidInfo.version.sdkInt < kAndroid11SDKINT) {
deletedIDs.addAll(await _deleteLocalFilesInBatches(context, localIDs));
} else {
deletedIDs.addAll(await _deleteLocalFilesInOneShot(context, localIDs));

View file

@ -1,14 +1,13 @@
import 'dart:async';
import 'dart:io' as io;
import 'dart:typed_data';
import 'package:logging/logging.dart';
import 'package:photo_manager/photo_manager.dart';
import 'package:photos/core/constants.dart';
import 'package:photos/core/errors.dart';
import 'package:photos/models/location.dart';
import 'package:photos/models/file.dart' as ente;
import 'package:photos/models/location.dart';
import 'file_util.dart';
@ -63,12 +62,12 @@ Future<MediaUploadData> _getMediaUploadDataFromAssetFile(ente.File file) async {
throw InvalidFileError();
}
thumbnailData = await asset.thumbDataWithSize(
THUMBNAIL_SMALL_SIZE,
THUMBNAIL_SMALL_SIZE,
quality: THUMBNAIL_QUALITY,
kThumbnailSmallSize,
kThumbnailSmallSize,
quality: kThumbnailQuality,
);
int compressionAttempts = 0;
while (thumbnailData.length > THUMBNAIL_DATA_LIMIT &&
while (thumbnailData.length > kThumbnailDataLimit &&
compressionAttempts < kMaximumThumbnailCompressionAttempts) {
_logger.info("Thumbnail size " + thumbnailData.length.toString());
thumbnailData = await compressThumbnail(thumbnailData);
@ -115,7 +114,7 @@ Future<Uint8List> getThumbnailFromInAppCacheFile(ente.File file) async {
var localPath = file.localID.replaceAll(RegExp(r'ente-upload-cache:'), '');
var thumbnailData = io.File(localPath).readAsBytesSync();
int compressionAttempts = 0;
while (thumbnailData.length > THUMBNAIL_DATA_LIMIT &&
while (thumbnailData.length > kThumbnailDataLimit &&
compressionAttempts < kMaximumThumbnailCompressionAttempts) {
_logger.info("Thumbnail size " + thumbnailData.length.toString());
thumbnailData = await compressThumbnail(thumbnailData);

View file

@ -2,12 +2,12 @@ import 'dart:async';
import 'dart:io' as io;
import 'dart:typed_data';
import 'package:flutter_sodium/flutter_sodium.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart';
import 'package:dio/dio.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:flutter_sodium/flutter_sodium.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart';
import 'package:photos/core/cache/image_cache.dart';
import 'package:photos/core/cache/thumbnail_cache.dart';
import 'package:photos/core/cache/video_cache_manager.dart';
@ -175,8 +175,8 @@ Uint8List decryptFileKey(ente.File file) {
Future<Uint8List> compressThumbnail(Uint8List thumbnail) {
return FlutterImageCompress.compressWithList(
thumbnail,
minHeight: COMPRESSED_THUMBNAIL_RESOLUTION,
minWidth: COMPRESSED_THUMBNAIL_RESOLUTION,
minHeight: kCompressedThumbnailResolution,
minWidth: kCompressedThumbnailResolution,
quality: 25,
);
}

View file

@ -1,6 +1,6 @@
import 'dart:async';
import 'dart:collection';
import 'dart:io' as io;
import 'dart:typed_data';
import 'package:dio/dio.dart';
@ -16,7 +16,6 @@ import 'package:photos/utils/crypto_util.dart';
import 'package:photos/utils/file_util.dart';
import 'dart:io' as io;
import 'file_uploader_util.dart';
final _logger = Logger("ThumbnailUtil");
@ -60,7 +59,7 @@ Future<Uint8List> getThumbnailFromServer(File file) async {
}
Future<Uint8List> getThumbnailFromLocal(File file) async {
if (ThumbnailLruCache.get(file, THUMBNAIL_SMALL_SIZE) != null) {
if (ThumbnailLruCache.get(file, kThumbnailSmallSize) != null) {
return ThumbnailLruCache.get(file);
}
final cachedThumbnail = getCachedThumbnail(file);
@ -73,7 +72,7 @@ Future<Uint8List> getThumbnailFromLocal(File file) async {
return getThumbnailFromInAppCacheFile(file)
.then((data) {
if (data != null) {
ThumbnailLruCache.put(file, data, THUMBNAIL_SMALL_SIZE);
ThumbnailLruCache.put(file, data, kThumbnailSmallSize);
}
return data;
});
@ -83,10 +82,10 @@ Future<Uint8List> getThumbnailFromLocal(File file) async {
return null;
}
return asset
.thumbDataWithSize(THUMBNAIL_SMALL_SIZE, THUMBNAIL_SMALL_SIZE,
quality: THUMBNAIL_QUALITY)
.thumbDataWithSize(kThumbnailSmallSize, kThumbnailSmallSize,
quality: kThumbnailQuality)
.then((data) {
ThumbnailLruCache.put(file, data, THUMBNAIL_SMALL_SIZE);
ThumbnailLruCache.put(file, data, kThumbnailSmallSize);
return data;
});
});
@ -146,7 +145,7 @@ Future<void> _downloadAndDecryptThumbnail(FileDownloadItem item) async {
Sodium.base642bin(file.thumbnailDecryptionHeader),
);
final thumbnailSize = data.length;
if (thumbnailSize > THUMBNAIL_DATA_LIMIT) {
if (thumbnailSize > kThumbnailDataLimit) {
data = await compressThumbnail(data);
}
ThumbnailLruCache.put(item.file, data);