Merge branch 'master' into reupload_hash_check
This commit is contained in:
commit
792dd67ade
87 changed files with 253 additions and 250 deletions
|
@ -15,6 +15,7 @@ linter:
|
||||||
- prefer_const_constructors_in_immutables
|
- prefer_const_constructors_in_immutables
|
||||||
- prefer_const_declarations
|
- prefer_const_declarations
|
||||||
- prefer_const_literals_to_create_immutables
|
- prefer_const_literals_to_create_immutables
|
||||||
|
- prefer_final_locals
|
||||||
- require_trailing_commas
|
- require_trailing_commas
|
||||||
- sized_box_for_whitespace
|
- sized_box_for_whitespace
|
||||||
- use_full_hex_values_for_flutter_colors
|
- use_full_hex_values_for_flutter_colors
|
||||||
|
|
6
lib/core/cache/lru_map.dart
vendored
6
lib/core/cache/lru_map.dart
vendored
|
@ -10,7 +10,7 @@ class LRUMap<K, V> {
|
||||||
LRUMap(this._maxSize, [this._handler]);
|
LRUMap(this._maxSize, [this._handler]);
|
||||||
|
|
||||||
V get(K key) {
|
V get(K key) {
|
||||||
V value = _map.remove(key);
|
final V value = _map.remove(key);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
_map[key] = value;
|
_map[key] = value;
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ class LRUMap<K, V> {
|
||||||
_map.remove(key);
|
_map.remove(key);
|
||||||
_map[key] = value;
|
_map[key] = value;
|
||||||
if (_map.length > _maxSize) {
|
if (_map.length > _maxSize) {
|
||||||
K evictedKey = _map.keys.first;
|
final K evictedKey = _map.keys.first;
|
||||||
V evictedValue = _map.remove(evictedKey);
|
final V evictedValue = _map.remove(evictedKey);
|
||||||
if (_handler != null) {
|
if (_handler != null) {
|
||||||
_handler(evictedKey, evictedValue);
|
_handler(evictedKey, evictedValue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ class Configuration {
|
||||||
_logger.warning(e);
|
_logger.warning(e);
|
||||||
}
|
}
|
||||||
tempDirectory.createSync(recursive: true);
|
tempDirectory.createSync(recursive: true);
|
||||||
var tempDirectoryPath = (await getTemporaryDirectory()).path;
|
final tempDirectoryPath = (await getTemporaryDirectory()).path;
|
||||||
_thumbnailCacheDirectory = tempDirectoryPath + "/thumbnail-cache";
|
_thumbnailCacheDirectory = tempDirectoryPath + "/thumbnail-cache";
|
||||||
io.Directory(_thumbnailCacheDirectory).createSync(recursive: true);
|
io.Directory(_thumbnailCacheDirectory).createSync(recursive: true);
|
||||||
_sharedTempMediaDirectory = tempDirectoryPath + "/ente-shared-media";
|
_sharedTempMediaDirectory = tempDirectoryPath + "/ente-shared-media";
|
||||||
|
|
|
@ -23,7 +23,7 @@ extension SuperString on String {
|
||||||
var start = 0;
|
var start = 0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
var stop = start + chunkSize;
|
final stop = start + chunkSize;
|
||||||
if (stop > length) break;
|
if (stop > length) break;
|
||||||
yield substring(start, stop);
|
yield substring(start, stop);
|
||||||
start = stop;
|
start = stop;
|
||||||
|
@ -37,7 +37,7 @@ extension SuperString on String {
|
||||||
|
|
||||||
extension SuperLogRecord on LogRecord {
|
extension SuperLogRecord on LogRecord {
|
||||||
String toPrettyString([String extraLines]) {
|
String toPrettyString([String extraLines]) {
|
||||||
var header = "[$loggerName] [$level] [$time]";
|
final header = "[$loggerName] [$level] [$time]";
|
||||||
|
|
||||||
var msg = "$header $message";
|
var msg = "$header $message";
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ class SuperLogging {
|
||||||
extraLines = null;
|
extraLines = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var str = config.prefix + " " + rec.toPrettyString(extraLines);
|
final str = config.prefix + " " + rec.toPrettyString(extraLines);
|
||||||
|
|
||||||
// write to stdout
|
// write to stdout
|
||||||
printLog(str);
|
printLog(str);
|
||||||
|
@ -316,21 +316,21 @@ class SuperLogging {
|
||||||
|
|
||||||
// choose [logDir]
|
// choose [logDir]
|
||||||
if (dirPath.isEmpty) {
|
if (dirPath.isEmpty) {
|
||||||
var root = await getExternalStorageDirectory();
|
final root = await getExternalStorageDirectory();
|
||||||
dirPath = '${root.path}/logs';
|
dirPath = '${root.path}/logs';
|
||||||
}
|
}
|
||||||
|
|
||||||
// create [logDir]
|
// create [logDir]
|
||||||
var dir = Directory(dirPath);
|
final dir = Directory(dirPath);
|
||||||
await dir.create(recursive: true);
|
await dir.create(recursive: true);
|
||||||
|
|
||||||
var files = <File>[];
|
final files = <File>[];
|
||||||
var dates = <File, DateTime>{};
|
final dates = <File, DateTime>{};
|
||||||
|
|
||||||
// collect all log files with valid names
|
// collect all log files with valid names
|
||||||
await for (final file in dir.list()) {
|
await for (final file in dir.list()) {
|
||||||
try {
|
try {
|
||||||
var date = config.dateFmt.parse(basename(file.path));
|
final date = config.dateFmt.parse(basename(file.path));
|
||||||
dates[file as File] = date;
|
dates[file as File] = date;
|
||||||
files.add(file);
|
files.add(file);
|
||||||
} on FormatException {}
|
} on FormatException {}
|
||||||
|
@ -363,7 +363,7 @@ class SuperLogging {
|
||||||
static String appVersion;
|
static String appVersion;
|
||||||
|
|
||||||
static Future<String> getAppVersion() async {
|
static Future<String> getAppVersion() async {
|
||||||
var pkgInfo = await PackageInfo.fromPlatform();
|
final pkgInfo = await PackageInfo.fromPlatform();
|
||||||
return "${pkgInfo.version}+${pkgInfo.buildNumber}";
|
return "${pkgInfo.version}+${pkgInfo.buildNumber}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,7 +372,7 @@ class SuperLogging {
|
||||||
if (!Platform.isAndroid) {
|
if (!Platform.isAndroid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var pkgName = (await PackageInfo.fromPlatform()).packageName;
|
final pkgName = (await PackageInfo.fromPlatform()).packageName;
|
||||||
return pkgName.startsWith("io.ente.photos.fdroid");
|
return pkgName.startsWith("io.ente.photos.fdroid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,8 +60,8 @@ class CollectionsDB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Database> _initDatabase() async {
|
Future<Database> _initDatabase() async {
|
||||||
Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
final Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
||||||
String path = join(documentsDirectory.path, _databaseName);
|
final String path = join(documentsDirectory.path, _databaseName);
|
||||||
return await openDatabaseWithMigration(path, dbConfig);
|
return await openDatabaseWithMigration(path, dbConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ class CollectionsDB {
|
||||||
|
|
||||||
Future<List<dynamic>> insert(List<Collection> collections) async {
|
Future<List<dynamic>> insert(List<Collection> collections) async {
|
||||||
final db = await instance.database;
|
final db = await instance.database;
|
||||||
var batch = db.batch();
|
final batch = db.batch();
|
||||||
for (final collection in collections) {
|
for (final collection in collections) {
|
||||||
batch.insert(
|
batch.insert(
|
||||||
table,
|
table,
|
||||||
|
@ -202,7 +202,7 @@ class CollectionsDB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> _getRowForCollection(Collection collection) {
|
Map<String, dynamic> _getRowForCollection(Collection collection) {
|
||||||
var row = <String, dynamic>{};
|
final row = <String, dynamic>{};
|
||||||
row[columnID] = collection.id;
|
row[columnID] = collection.id;
|
||||||
row[columnOwner] = collection.owner.toJson();
|
row[columnOwner] = collection.owner.toJson();
|
||||||
row[columnEncryptedKey] = collection.encryptedKey;
|
row[columnEncryptedKey] = collection.encryptedKey;
|
||||||
|
@ -230,7 +230,7 @@ class CollectionsDB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection _convertToCollection(Map<String, dynamic> row) {
|
Collection _convertToCollection(Map<String, dynamic> row) {
|
||||||
Collection result = Collection(
|
final Collection result = Collection(
|
||||||
row[columnID],
|
row[columnID],
|
||||||
User.fromJson(row[columnOwner]),
|
User.fromJson(row[columnOwner]),
|
||||||
row[columnEncryptedKey],
|
row[columnEncryptedKey],
|
||||||
|
|
|
@ -64,8 +64,9 @@ class FileUpdationDB {
|
||||||
|
|
||||||
// this opens the database (and creates it if it doesn't exist)
|
// this opens the database (and creates it if it doesn't exist)
|
||||||
Future<Database> _initDatabase() async {
|
Future<Database> _initDatabase() async {
|
||||||
Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
final Directory documentsDirectory =
|
||||||
String path = join(documentsDirectory.path, _databaseName);
|
await getApplicationDocumentsDirectory();
|
||||||
|
final String path = join(documentsDirectory.path, _databaseName);
|
||||||
debugPrint("DB path " + path);
|
debugPrint("DB path " + path);
|
||||||
return await openDatabaseWithMigration(path, dbConfig);
|
return await openDatabaseWithMigration(path, dbConfig);
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,8 +96,8 @@ class FilesDB {
|
||||||
|
|
||||||
// this opens the database (and creates it if it doesn't exist)
|
// this opens the database (and creates it if it doesn't exist)
|
||||||
Future<Database> _initDatabase() async {
|
Future<Database> _initDatabase() async {
|
||||||
Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
final Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
||||||
String path = join(documentsDirectory.path, _databaseName);
|
final String path = join(documentsDirectory.path, _databaseName);
|
||||||
_logger.info("DB path " + path);
|
_logger.info("DB path " + path);
|
||||||
return await openDatabaseWithMigration(path, dbConfig);
|
return await openDatabaseWithMigration(path, dbConfig);
|
||||||
}
|
}
|
||||||
|
@ -426,7 +426,7 @@ class FilesDB {
|
||||||
limit: limit,
|
limit: limit,
|
||||||
);
|
);
|
||||||
final files = _convertToFiles(results);
|
final files = _convertToFiles(results);
|
||||||
List<File> deduplicatedFiles =
|
final List<File> deduplicatedFiles =
|
||||||
_deduplicatedAndFilterIgnoredFiles(files, ignoredCollectionIDs);
|
_deduplicatedAndFilterIgnoredFiles(files, ignoredCollectionIDs);
|
||||||
return FileLoadResult(deduplicatedFiles, files.length == limit);
|
return FileLoadResult(deduplicatedFiles, files.length == limit);
|
||||||
}
|
}
|
||||||
|
@ -452,7 +452,7 @@ class FilesDB {
|
||||||
limit: limit,
|
limit: limit,
|
||||||
);
|
);
|
||||||
final files = _convertToFiles(results);
|
final files = _convertToFiles(results);
|
||||||
List<File> deduplicatedFiles =
|
final List<File> deduplicatedFiles =
|
||||||
_deduplicatedAndFilterIgnoredFiles(files, ignoredCollectionIDs);
|
_deduplicatedAndFilterIgnoredFiles(files, ignoredCollectionIDs);
|
||||||
return FileLoadResult(deduplicatedFiles, files.length == limit);
|
return FileLoadResult(deduplicatedFiles, files.length == limit);
|
||||||
}
|
}
|
||||||
|
@ -484,7 +484,7 @@ class FilesDB {
|
||||||
limit: limit,
|
limit: limit,
|
||||||
);
|
);
|
||||||
final files = _convertToFiles(results);
|
final files = _convertToFiles(results);
|
||||||
List<File> deduplicatedFiles =
|
final List<File> deduplicatedFiles =
|
||||||
_deduplicatedAndFilterIgnoredFiles(files, ignoredCollectionIDs);
|
_deduplicatedAndFilterIgnoredFiles(files, ignoredCollectionIDs);
|
||||||
return FileLoadResult(deduplicatedFiles, files.length == limit);
|
return FileLoadResult(deduplicatedFiles, files.length == limit);
|
||||||
}
|
}
|
||||||
|
@ -675,7 +675,7 @@ class FilesDB {
|
||||||
orderBy: '$columnCreationTime DESC',
|
orderBy: '$columnCreationTime DESC',
|
||||||
groupBy: columnLocalID,
|
groupBy: columnLocalID,
|
||||||
);
|
);
|
||||||
var files = _convertToFiles(results);
|
final files = _convertToFiles(results);
|
||||||
// future-safe filter just to ensure that the query doesn't end up returning files
|
// future-safe filter just to ensure that the query doesn't end up returning files
|
||||||
// which should not be backed up
|
// which should not be backed up
|
||||||
files.removeWhere(
|
files.removeWhere(
|
||||||
|
@ -972,7 +972,7 @@ class FilesDB {
|
||||||
|
|
||||||
Future<int> collectionFileCount(int collectionID) async {
|
Future<int> collectionFileCount(int collectionID) async {
|
||||||
final db = await instance.database;
|
final db = await instance.database;
|
||||||
var count = Sqflite.firstIntValue(
|
final count = Sqflite.firstIntValue(
|
||||||
await db.rawQuery(
|
await db.rawQuery(
|
||||||
'SELECT COUNT(*) FROM $table where $columnCollectionID = $collectionID',
|
'SELECT COUNT(*) FROM $table where $columnCollectionID = $collectionID',
|
||||||
),
|
),
|
||||||
|
@ -982,7 +982,7 @@ class FilesDB {
|
||||||
|
|
||||||
Future<int> fileCountWithVisibility(int visibility, int ownerID) async {
|
Future<int> fileCountWithVisibility(int visibility, int ownerID) async {
|
||||||
final db = await instance.database;
|
final db = await instance.database;
|
||||||
var count = Sqflite.firstIntValue(
|
final count = Sqflite.firstIntValue(
|
||||||
await db.rawQuery(
|
await db.rawQuery(
|
||||||
'SELECT COUNT(*) FROM $table where $columnMMdVisibility = $visibility AND $columnOwnerID = $ownerID',
|
'SELECT COUNT(*) FROM $table where $columnMMdVisibility = $visibility AND $columnOwnerID = $ownerID',
|
||||||
),
|
),
|
||||||
|
@ -1171,9 +1171,9 @@ class FilesDB {
|
||||||
|
|
||||||
Future<List<File>> getAllFilesFromDB() async {
|
Future<List<File>> getAllFilesFromDB() async {
|
||||||
final db = await instance.database;
|
final db = await instance.database;
|
||||||
List<Map<String, dynamic>> result = await db.query(table);
|
final List<Map<String, dynamic>> result = await db.query(table);
|
||||||
List<File> files = _convertToFiles(result);
|
final List<File> files = _convertToFiles(result);
|
||||||
List<File> deduplicatedFiles =
|
final List<File> deduplicatedFiles =
|
||||||
_deduplicatedAndFilterIgnoredFiles(files, null);
|
_deduplicatedAndFilterIgnoredFiles(files, null);
|
||||||
return deduplicatedFiles;
|
return deduplicatedFiles;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,8 +52,8 @@ class IgnoredFilesDB {
|
||||||
|
|
||||||
// this opens the database (and creates it if it doesn't exist)
|
// this opens the database (and creates it if it doesn't exist)
|
||||||
Future<Database> _initDatabase() async {
|
Future<Database> _initDatabase() async {
|
||||||
Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
final Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
||||||
String path = join(documentsDirectory.path, _databaseName);
|
final String path = join(documentsDirectory.path, _databaseName);
|
||||||
return await openDatabase(
|
return await openDatabase(
|
||||||
path,
|
path,
|
||||||
version: _databaseVersion,
|
version: _databaseVersion,
|
||||||
|
|
|
@ -25,8 +25,8 @@ class MemoriesDB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Database> _initDatabase() async {
|
Future<Database> _initDatabase() async {
|
||||||
Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
final Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
||||||
String path = join(documentsDirectory.path, _databaseName);
|
final String path = join(documentsDirectory.path, _databaseName);
|
||||||
return await openDatabase(
|
return await openDatabase(
|
||||||
path,
|
path,
|
||||||
version: _databaseVersion,
|
version: _databaseVersion,
|
||||||
|
@ -74,7 +74,7 @@ class MemoriesDB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> _getRowForSeenMemory(Memory memory, int timestamp) {
|
Map<String, dynamic> _getRowForSeenMemory(Memory memory, int timestamp) {
|
||||||
var row = <String, dynamic>{};
|
final row = <String, dynamic>{};
|
||||||
row[columnFileID] = memory.file.generatedID;
|
row[columnFileID] = memory.file.generatedID;
|
||||||
row[columnSeenTime] = timestamp;
|
row[columnSeenTime] = timestamp;
|
||||||
return row;
|
return row;
|
||||||
|
|
|
@ -26,8 +26,8 @@ class PublicKeysDB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Database> _initDatabase() async {
|
Future<Database> _initDatabase() async {
|
||||||
Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
final Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
||||||
String path = join(documentsDirectory.path, _databaseName);
|
final String path = join(documentsDirectory.path, _databaseName);
|
||||||
return await openDatabase(
|
return await openDatabase(
|
||||||
path,
|
path,
|
||||||
version: _databaseVersion,
|
version: _databaseVersion,
|
||||||
|
@ -72,7 +72,7 @@ class PublicKeysDB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> _getRow(PublicKey key) {
|
Map<String, dynamic> _getRow(PublicKey key) {
|
||||||
var row = <String, dynamic>{};
|
final row = <String, dynamic>{};
|
||||||
row[columnEmail] = key.email;
|
row[columnEmail] = key.email;
|
||||||
row[columnPublicKey] = key.publicKey;
|
row[columnPublicKey] = key.publicKey;
|
||||||
return row;
|
return row;
|
||||||
|
|
|
@ -85,8 +85,8 @@ class TrashDB {
|
||||||
|
|
||||||
// this opens the database (and creates it if it doesn't exist)
|
// this opens the database (and creates it if it doesn't exist)
|
||||||
Future<Database> _initDatabase() async {
|
Future<Database> _initDatabase() async {
|
||||||
Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
final Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
||||||
String path = join(documentsDirectory.path, _databaseName);
|
final String path = join(documentsDirectory.path, _databaseName);
|
||||||
_logger.info("DB path " + path);
|
_logger.info("DB path " + path);
|
||||||
return await openDatabase(
|
return await openDatabase(
|
||||||
path,
|
path,
|
||||||
|
@ -103,7 +103,7 @@ class TrashDB {
|
||||||
// getRecentlyTrashedFile returns the file which was trashed recently
|
// getRecentlyTrashedFile returns the file which was trashed recently
|
||||||
Future<TrashFile> getRecentlyTrashedFile() async {
|
Future<TrashFile> getRecentlyTrashedFile() async {
|
||||||
final db = await instance.database;
|
final db = await instance.database;
|
||||||
var rows = await db.query(
|
final rows = await db.query(
|
||||||
tableName,
|
tableName,
|
||||||
orderBy: '$columnTrashDeleteBy DESC',
|
orderBy: '$columnTrashDeleteBy DESC',
|
||||||
limit: 1,
|
limit: 1,
|
||||||
|
@ -116,7 +116,7 @@ class TrashDB {
|
||||||
|
|
||||||
Future<int> count() async {
|
Future<int> count() async {
|
||||||
final db = await instance.database;
|
final db = await instance.database;
|
||||||
var count = Sqflite.firstIntValue(
|
final count = Sqflite.firstIntValue(
|
||||||
await db.rawQuery('SELECT COUNT(*) FROM $tableName'),
|
await db.rawQuery('SELECT COUNT(*) FROM $tableName'),
|
||||||
);
|
);
|
||||||
return count;
|
return count;
|
||||||
|
|
|
@ -24,8 +24,8 @@ class UploadLocksDB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Database> _initDatabase() async {
|
Future<Database> _initDatabase() async {
|
||||||
Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
final Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
||||||
String path = join(documentsDirectory.path, _databaseName);
|
final String path = join(documentsDirectory.path, _databaseName);
|
||||||
return await openDatabase(
|
return await openDatabase(
|
||||||
path,
|
path,
|
||||||
version: _databaseVersion,
|
version: _databaseVersion,
|
||||||
|
|
|
@ -231,8 +231,8 @@ Future<void> _killBGTask([String taskId]) async {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||||
bool isRunningInFG = await _isRunningInForeground(); // hb
|
final bool isRunningInFG = await _isRunningInForeground(); // hb
|
||||||
bool isInForeground = AppLifecycleService.instance.isForeground;
|
final bool isInForeground = AppLifecycleService.instance.isForeground;
|
||||||
if (_isProcessRunning) {
|
if (_isProcessRunning) {
|
||||||
_logger.info(
|
_logger.info(
|
||||||
"Background push received when app is alive and runningInFS: $isRunningInFG inForeground: $isInForeground",
|
"Background push received when app is alive and runningInFS: $isRunningInFG inForeground: $isInForeground",
|
||||||
|
@ -259,18 +259,18 @@ Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _logFGHeartBeatInfo() async {
|
Future<void> _logFGHeartBeatInfo() async {
|
||||||
bool isRunningInFG = await _isRunningInForeground();
|
final bool isRunningInFG = await _isRunningInForeground();
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
await prefs.reload();
|
await prefs.reload();
|
||||||
var lastFGTaskHeartBeatTime = prefs.getInt(kLastFGTaskHeartBeatTime) ?? 0;
|
final lastFGTaskHeartBeatTime = prefs.getInt(kLastFGTaskHeartBeatTime) ?? 0;
|
||||||
String lastRun = lastFGTaskHeartBeatTime == 0
|
final String lastRun = lastFGTaskHeartBeatTime == 0
|
||||||
? 'never'
|
? 'never'
|
||||||
: DateTime.fromMicrosecondsSinceEpoch(lastFGTaskHeartBeatTime).toString();
|
: DateTime.fromMicrosecondsSinceEpoch(lastFGTaskHeartBeatTime).toString();
|
||||||
_logger.info('isAlreaduunningFG: $isRunningInFG, last Beat: $lastRun');
|
_logger.info('isAlreaduunningFG: $isRunningInFG, last Beat: $lastRun');
|
||||||
}
|
}
|
||||||
|
|
||||||
void _scheduleSuicide(Duration duration, [String taskID]) {
|
void _scheduleSuicide(Duration duration, [String taskID]) {
|
||||||
var taskIDVal = taskID ?? 'no taskID';
|
final taskIDVal = taskID ?? 'no taskID';
|
||||||
_logger.warning("Schedule seppuku taskID: $taskIDVal");
|
_logger.warning("Schedule seppuku taskID: $taskIDVal");
|
||||||
Future.delayed(duration, () {
|
Future.delayed(duration, () {
|
||||||
_logger.warning("TLE, committing seppuku for taskID: $taskIDVal");
|
_logger.warning("TLE, committing seppuku for taskID: $taskIDVal");
|
||||||
|
|
|
@ -85,7 +85,7 @@ class Collection {
|
||||||
String mMdEncodedJson,
|
String mMdEncodedJson,
|
||||||
int mMdVersion,
|
int mMdVersion,
|
||||||
}) {
|
}) {
|
||||||
Collection result = Collection(
|
final Collection result = Collection(
|
||||||
id ?? this.id,
|
id ?? this.id,
|
||||||
owner ?? this.owner,
|
owner ?? this.owner,
|
||||||
encryptedKey ?? this.encryptedKey,
|
encryptedKey ?? this.encryptedKey,
|
||||||
|
|
|
@ -60,7 +60,7 @@ class File extends EnteFile {
|
||||||
File();
|
File();
|
||||||
|
|
||||||
static Future<File> fromAsset(String pathName, AssetEntity asset) async {
|
static Future<File> fromAsset(String pathName, AssetEntity asset) async {
|
||||||
File file = File();
|
final File file = File();
|
||||||
file.localID = asset.id;
|
file.localID = asset.id;
|
||||||
file.title = asset.title;
|
file.title = asset.title;
|
||||||
file.deviceFolder = pathName;
|
file.deviceFolder = pathName;
|
||||||
|
|
|
@ -9,7 +9,7 @@ class SelectedFiles extends ChangeNotifier {
|
||||||
// To handle the cases, where the file might have changed due to upload
|
// To handle the cases, where the file might have changed due to upload
|
||||||
// or any other update, using file.generatedID to track if this file was already
|
// or any other update, using file.generatedID to track if this file was already
|
||||||
// selected or not
|
// selected or not
|
||||||
File alreadySelected = files.firstWhere(
|
final File alreadySelected = files.firstWhere(
|
||||||
(element) => element.generatedID == file.generatedID,
|
(element) => element.generatedID == file.generatedID,
|
||||||
orElse: () => null,
|
orElse: () => null,
|
||||||
);
|
);
|
||||||
|
@ -24,7 +24,7 @@ class SelectedFiles extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFileSelected(File file) {
|
bool isFileSelected(File file) {
|
||||||
File alreadySelected = files.firstWhere(
|
final File alreadySelected = files.firstWhere(
|
||||||
(element) => element.generatedID == file.generatedID,
|
(element) => element.generatedID == file.generatedID,
|
||||||
orElse: () => null,
|
orElse: () => null,
|
||||||
);
|
);
|
||||||
|
@ -32,7 +32,7 @@ class SelectedFiles extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isPartOfLastSection(File file) {
|
bool isPartOfLastSection(File file) {
|
||||||
File alreadySelected = lastSelections.firstWhere(
|
final File alreadySelected = lastSelections.firstWhere(
|
||||||
(element) => element.generatedID == file.generatedID,
|
(element) => element.generatedID == file.generatedID,
|
||||||
orElse: () => null,
|
orElse: () => null,
|
||||||
);
|
);
|
||||||
|
|
|
@ -144,7 +144,7 @@ class Attributes {
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
var map = <String, dynamic>{};
|
final map = <String, dynamic>{};
|
||||||
map["isCancelled"] = isCancelled;
|
map["isCancelled"] = isCancelled;
|
||||||
map["customerID"] = customerID;
|
map["customerID"] = customerID;
|
||||||
return map;
|
return map;
|
||||||
|
|
|
@ -308,7 +308,7 @@ class CollectionsService {
|
||||||
// read the existing magic metadata and apply new updates to existing data
|
// read the existing magic metadata and apply new updates to existing data
|
||||||
// current update is simple replace. This will be enhanced in the future,
|
// current update is simple replace. This will be enhanced in the future,
|
||||||
// as required.
|
// as required.
|
||||||
Map<String, dynamic> jsonToUpdate =
|
final Map<String, dynamic> jsonToUpdate =
|
||||||
jsonDecode(collection.mMdEncodedJson ?? '{}');
|
jsonDecode(collection.mMdEncodedJson ?? '{}');
|
||||||
newMetadataUpdate.forEach((key, value) {
|
newMetadataUpdate.forEach((key, value) {
|
||||||
jsonToUpdate[key] = value;
|
jsonToUpdate[key] = value;
|
||||||
|
@ -325,7 +325,7 @@ class CollectionsService {
|
||||||
);
|
);
|
||||||
// for required field, the json validator on golang doesn't treat 0 as valid
|
// for required field, the json validator on golang doesn't treat 0 as valid
|
||||||
// value. Instead of changing version to ptr, decided to start version with 1.
|
// value. Instead of changing version to ptr, decided to start version with 1.
|
||||||
int currentVersion = max(collection.mMdVersion, 1);
|
final int currentVersion = max(collection.mMdVersion, 1);
|
||||||
final params = UpdateMagicMetadataRequest(
|
final params = UpdateMagicMetadataRequest(
|
||||||
id: collection.id,
|
id: collection.id,
|
||||||
magicMetadata: MetadataRequest(
|
magicMetadata: MetadataRequest(
|
||||||
|
|
|
@ -18,7 +18,7 @@ class DeduplicationService {
|
||||||
|
|
||||||
Future<List<DuplicateFiles>> getDuplicateFiles() async {
|
Future<List<DuplicateFiles>> getDuplicateFiles() async {
|
||||||
try {
|
try {
|
||||||
DuplicateFilesResponse dupes = await _fetchDuplicateFileIDs();
|
final DuplicateFilesResponse dupes = await _fetchDuplicateFileIDs();
|
||||||
final ids = <int>[];
|
final ids = <int>[];
|
||||||
for (final dupe in dupes.duplicates) {
|
for (final dupe in dupes.duplicates) {
|
||||||
ids.addAll(dupe.fileIDs);
|
ids.addAll(dupe.fileIDs);
|
||||||
|
|
|
@ -53,7 +53,7 @@ class FavoritesService {
|
||||||
|
|
||||||
Future<void> removeFromFavorites(File file) async {
|
Future<void> removeFromFavorites(File file) async {
|
||||||
final collectionID = await _getOrCreateFavoriteCollectionID();
|
final collectionID = await _getOrCreateFavoriteCollectionID();
|
||||||
var fileID = file.uploadedFileID;
|
final fileID = file.uploadedFileID;
|
||||||
if (fileID == null) {
|
if (fileID == null) {
|
||||||
// Do nothing, ignore
|
// Do nothing, ignore
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -94,7 +94,7 @@ class FeatureFlagService {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _isInternalUserOrDebugBuild() {
|
bool _isInternalUserOrDebugBuild() {
|
||||||
String email = Configuration.instance.getEmail();
|
final String email = Configuration.instance.getEmail();
|
||||||
return (email != null && email.endsWith("@ente.io")) || kDebugMode;
|
return (email != null && email.endsWith("@ente.io")) || kDebugMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ class FileMagicService {
|
||||||
FileMagicService._privateConstructor();
|
FileMagicService._privateConstructor();
|
||||||
|
|
||||||
Future<void> changeVisibility(List<File> files, int visibility) async {
|
Future<void> changeVisibility(List<File> files, int visibility) async {
|
||||||
Map<String, dynamic> update = {kMagicKeyVisibility: visibility};
|
final Map<String, dynamic> update = {kMagicKeyVisibility: visibility};
|
||||||
await _updateMagicData(files, update);
|
await _updateMagicData(files, update);
|
||||||
if (visibility == kVisibilityVisible) {
|
if (visibility == kVisibilityVisible) {
|
||||||
// Force reload home gallery to pull in the now unarchived files
|
// Force reload home gallery to pull in the now unarchived files
|
||||||
|
@ -62,7 +62,7 @@ class FileMagicService {
|
||||||
// read the existing magic metadata and apply new updates to existing data
|
// read the existing magic metadata and apply new updates to existing data
|
||||||
// current update is simple replace. This will be enhanced in the future,
|
// current update is simple replace. This will be enhanced in the future,
|
||||||
// as required.
|
// as required.
|
||||||
Map<String, dynamic> jsonToUpdate = jsonDecode(file.pubMmdEncodedJson);
|
final Map<String, dynamic> jsonToUpdate = jsonDecode(file.pubMmdEncodedJson);
|
||||||
newMetadataUpdate.forEach((key, value) {
|
newMetadataUpdate.forEach((key, value) {
|
||||||
jsonToUpdate[key] = value;
|
jsonToUpdate[key] = value;
|
||||||
});
|
});
|
||||||
|
@ -132,7 +132,7 @@ class FileMagicService {
|
||||||
// read the existing magic metadata and apply new updates to existing data
|
// read the existing magic metadata and apply new updates to existing data
|
||||||
// current update is simple replace. This will be enhanced in the future,
|
// current update is simple replace. This will be enhanced in the future,
|
||||||
// as required.
|
// as required.
|
||||||
Map<String, dynamic> jsonToUpdate = jsonDecode(file.mMdEncodedJson);
|
final Map<String, dynamic> jsonToUpdate = jsonDecode(file.mMdEncodedJson);
|
||||||
newMetadataUpdate.forEach((key, value) {
|
newMetadataUpdate.forEach((key, value) {
|
||||||
jsonToUpdate[key] = value;
|
jsonToUpdate[key] = value;
|
||||||
});
|
});
|
||||||
|
@ -224,7 +224,7 @@ class MetadataRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
var map = <String, dynamic>{};
|
final map = <String, dynamic>{};
|
||||||
map['version'] = version;
|
map['version'] = version;
|
||||||
map['count'] = count;
|
map['count'] = count;
|
||||||
map['data'] = data;
|
map['data'] = data;
|
||||||
|
|
|
@ -164,7 +164,7 @@ class LocalSyncService {
|
||||||
if (_prefs.containsKey(kEditedFileIDsKey)) {
|
if (_prefs.containsKey(kEditedFileIDsKey)) {
|
||||||
return _prefs.getStringList(kEditedFileIDsKey);
|
return _prefs.getStringList(kEditedFileIDsKey);
|
||||||
} else {
|
} else {
|
||||||
List<String> editedIDs = [];
|
final List<String> editedIDs = [];
|
||||||
return editedIDs;
|
return editedIDs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ class LocalSyncService {
|
||||||
if (_prefs.containsKey(kDownloadedFileIDsKey)) {
|
if (_prefs.containsKey(kDownloadedFileIDsKey)) {
|
||||||
return _prefs.getStringList(kDownloadedFileIDsKey);
|
return _prefs.getStringList(kDownloadedFileIDsKey);
|
||||||
} else {
|
} else {
|
||||||
List<String> downloadedIDs = [];
|
final List<String> downloadedIDs = [];
|
||||||
return downloadedIDs;
|
return downloadedIDs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ class LocalSyncService {
|
||||||
if (_prefs.containsKey(kInvalidFileIDsKey)) {
|
if (_prefs.containsKey(kInvalidFileIDsKey)) {
|
||||||
return _prefs.getStringList(kInvalidFileIDsKey);
|
return _prefs.getStringList(kInvalidFileIDsKey);
|
||||||
} else {
|
} else {
|
||||||
List<String> invalidIDs = [];
|
final List<String> invalidIDs = [];
|
||||||
return invalidIDs;
|
return invalidIDs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,7 +262,7 @@ class RemoteSyncService {
|
||||||
_logger.info(editedFiles.length.toString() + " files edited.");
|
_logger.info(editedFiles.length.toString() + " files edited.");
|
||||||
|
|
||||||
_completedUploads = 0;
|
_completedUploads = 0;
|
||||||
int toBeUploaded =
|
final int toBeUploaded =
|
||||||
filesToBeUploaded.length + updatedFileIDs.length + editedFiles.length;
|
filesToBeUploaded.length + updatedFileIDs.length + editedFiles.length;
|
||||||
|
|
||||||
if (toBeUploaded > 0) {
|
if (toBeUploaded > 0) {
|
||||||
|
@ -371,8 +371,8 @@ class RemoteSyncService {
|
||||||
localButUpdatedOnRemote = 0,
|
localButUpdatedOnRemote = 0,
|
||||||
localButAddedToNewCollectionOnRemote = 0;
|
localButAddedToNewCollectionOnRemote = 0;
|
||||||
bool hasAnyCreationTimeChanged = false;
|
bool hasAnyCreationTimeChanged = false;
|
||||||
List<File> toBeInserted = [];
|
final List<File> toBeInserted = [];
|
||||||
int userID = Configuration.instance.getUserID();
|
final int userID = Configuration.instance.getUserID();
|
||||||
for (File file in diff) {
|
for (File file in diff) {
|
||||||
final existingFiles = file.deviceFolder == null
|
final existingFiles = file.deviceFolder == null
|
||||||
? null
|
? null
|
||||||
|
@ -417,7 +417,7 @@ class RemoteSyncService {
|
||||||
} else {
|
} else {
|
||||||
file.localID = null;
|
file.localID = null;
|
||||||
}
|
}
|
||||||
bool wasUploadedOnAPreviousInstallation =
|
final bool wasUploadedOnAPreviousInstallation =
|
||||||
existingFiles.length == 1 && existingFiles[0].collectionID == null;
|
existingFiles.length == 1 && existingFiles[0].collectionID == null;
|
||||||
if (wasUploadedOnAPreviousInstallation) {
|
if (wasUploadedOnAPreviousInstallation) {
|
||||||
file.generatedID = existingFiles[0].generatedID;
|
file.generatedID = existingFiles[0].generatedID;
|
||||||
|
|
|
@ -806,7 +806,7 @@ class UserService {
|
||||||
|
|
||||||
Future<String> getPaymentToken() async {
|
Future<String> getPaymentToken() async {
|
||||||
try {
|
try {
|
||||||
var response = await _dio.get(
|
final response = await _dio.get(
|
||||||
"${_config.getHttpEndpoint()}/users/payment-token",
|
"${_config.getHttpEndpoint()}/users/payment-token",
|
||||||
options: Options(
|
options: Options(
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -827,7 +827,7 @@ class UserService {
|
||||||
|
|
||||||
Future<String> getFamiliesToken() async {
|
Future<String> getFamiliesToken() async {
|
||||||
try {
|
try {
|
||||||
var response = await _dio.get(
|
final response = await _dio.get(
|
||||||
"${_config.getHttpEndpoint()}/users/families-token",
|
"${_config.getHttpEndpoint()}/users/families-token",
|
||||||
options: Options(
|
options: Options(
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
@ -145,7 +145,7 @@ class DeleteAccountPage extends StatelessWidget {
|
||||||
DeleteChallengeResponse response,
|
DeleteChallengeResponse response,
|
||||||
) async {
|
) async {
|
||||||
AppLock.of(context).setEnabled(false);
|
AppLock.of(context).setEnabled(false);
|
||||||
String reason = "Please authenticate to initiate account deletion";
|
const String reason = "Please authenticate to initiate account deletion";
|
||||||
final result = await requestAuthentication(reason);
|
final result = await requestAuthentication(reason);
|
||||||
AppLock.of(context).setEnabled(
|
AppLock.of(context).setEnabled(
|
||||||
Configuration.instance.shouldShowLockScreen(),
|
Configuration.instance.shouldShowLockScreen(),
|
||||||
|
@ -177,7 +177,7 @@ class DeleteAccountPage extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _requestEmailForDeletion(BuildContext context) async {
|
Future<void> _requestEmailForDeletion(BuildContext context) async {
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
title: const Text(
|
title: const Text(
|
||||||
"Delete account",
|
"Delete account",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
|
|
@ -79,7 +79,7 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
|
||||||
_logger.severe("Password verification failed", e, s);
|
_logger.severe("Password verification failed", e, s);
|
||||||
await dialog.hide();
|
await dialog.hide();
|
||||||
|
|
||||||
var dialogUserChoice = await showChoiceDialog(
|
final dialogUserChoice = await showChoiceDialog(
|
||||||
context,
|
context,
|
||||||
"Incorrect password",
|
"Incorrect password",
|
||||||
"Please try again",
|
"Please try again",
|
||||||
|
|
|
@ -186,7 +186,7 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _saveOptions(BuildContext context, String recoveryKey) {
|
List<Widget> _saveOptions(BuildContext context, String recoveryKey) {
|
||||||
List<Widget> childrens = [];
|
final List<Widget> childrens = [];
|
||||||
if (!_hasTriedToSave) {
|
if (!_hasTriedToSave) {
|
||||||
childrens.add(
|
childrens.add(
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
|
|
|
@ -41,7 +41,7 @@ class _SessionsPageState extends State<SessionsPage> {
|
||||||
if (_sessions == null) {
|
if (_sessions == null) {
|
||||||
return const Center(child: EnteLoadingWidget());
|
return const Center(child: EnteLoadingWidget());
|
||||||
}
|
}
|
||||||
List<Widget> rows = [];
|
final List<Widget> rows = [];
|
||||||
rows.add(const Padding(padding: EdgeInsets.all(4)));
|
rows.add(const Padding(padding: EdgeInsets.all(4)));
|
||||||
for (final session in _sessions.sessions) {
|
for (final session in _sessions.sessions) {
|
||||||
rows.add(_getSessionWidget(session));
|
rows.add(_getSessionWidget(session));
|
||||||
|
@ -163,7 +163,7 @@ class _SessionsPageState extends State<SessionsPage> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
title: const Text("Terminate session?"),
|
title: const Text("Terminate session?"),
|
||||||
content: text,
|
content: text,
|
||||||
actions: [
|
actions: [
|
||||||
|
|
|
@ -116,7 +116,7 @@ class _TwoFactorSetupPageState extends State<TwoFactorSetupPage>
|
||||||
Divider(
|
Divider(
|
||||||
height: 1,
|
height: 1,
|
||||||
thickness: 1,
|
thickness: 1,
|
||||||
color: Theme.of(context).accentColor,
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
),
|
),
|
||||||
_getVerificationWidget(),
|
_getVerificationWidget(),
|
||||||
],
|
],
|
||||||
|
@ -126,7 +126,7 @@ class _TwoFactorSetupPageState extends State<TwoFactorSetupPage>
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _getSecretCode() {
|
Widget _getSecretCode() {
|
||||||
Color textColor = Theme.of(context).colorScheme.onSurface;
|
final Color textColor = Theme.of(context).colorScheme.onSurface;
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await Clipboard.setData(ClipboardData(text: widget.secretCode));
|
await Clipboard.setData(ClipboardData(text: widget.secretCode));
|
||||||
|
|
|
@ -19,11 +19,11 @@ class CollectionItem extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
const double horizontalPaddingOfGridRow = 16;
|
const double horizontalPaddingOfGridRow = 16;
|
||||||
const double crossAxisSpacingOfGrid = 9;
|
const double crossAxisSpacingOfGrid = 9;
|
||||||
Size size = MediaQuery.of(context).size;
|
final Size size = MediaQuery.of(context).size;
|
||||||
int albumsCountInOneRow = max(size.width ~/ 220.0, 2);
|
final int albumsCountInOneRow = max(size.width ~/ 220.0, 2);
|
||||||
double totalWhiteSpaceOfRow = (horizontalPaddingOfGridRow * 2) +
|
final double totalWhiteSpaceOfRow = (horizontalPaddingOfGridRow * 2) +
|
||||||
(albumsCountInOneRow - 1) * crossAxisSpacingOfGrid;
|
(albumsCountInOneRow - 1) * crossAxisSpacingOfGrid;
|
||||||
TextStyle albumTitleTextStyle =
|
final TextStyle albumTitleTextStyle =
|
||||||
Theme.of(context).textTheme.subtitle1.copyWith(fontSize: 14);
|
Theme.of(context).textTheme.subtitle1.copyWith(fontSize: 14);
|
||||||
final double sideOfThumbnail = (size.width / albumsCountInOneRow) -
|
final double sideOfThumbnail = (size.width / albumsCountInOneRow) -
|
||||||
(totalWhiteSpaceOfRow / albumsCountInOneRow);
|
(totalWhiteSpaceOfRow / albumsCountInOneRow);
|
||||||
|
|
|
@ -17,8 +17,8 @@ class RemoteCollectionsGridViewWidget extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
const double horizontalPaddingOfGridRow = 16;
|
const double horizontalPaddingOfGridRow = 16;
|
||||||
const double crossAxisSpacingOfGrid = 9;
|
const double crossAxisSpacingOfGrid = 9;
|
||||||
Size size = MediaQuery.of(context).size;
|
final Size size = MediaQuery.of(context).size;
|
||||||
int albumsCountInOneRow = max(size.width ~/ 220.0, 2);
|
final int albumsCountInOneRow = max(size.width ~/ 220.0, 2);
|
||||||
final double sideOfThumbnail = (size.width / albumsCountInOneRow) -
|
final double sideOfThumbnail = (size.width / albumsCountInOneRow) -
|
||||||
horizontalPaddingOfGridRow -
|
horizontalPaddingOfGridRow -
|
||||||
((crossAxisSpacingOfGrid / 2) * (albumsCountInOneRow - 1));
|
((crossAxisSpacingOfGrid / 2) * (albumsCountInOneRow - 1));
|
||||||
|
|
|
@ -19,7 +19,7 @@ Future<DialogUserChoice> showChoiceDialog<T>(
|
||||||
Color secondActionColor,
|
Color secondActionColor,
|
||||||
ActionType actionType = ActionType.confirm,
|
ActionType actionType = ActionType.confirm,
|
||||||
}) {
|
}) {
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
title: Text(
|
title: Text(
|
||||||
title,
|
title,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
|
|
@ -202,7 +202,7 @@ class _CreateCollectionPageState extends State<CreateCollectionPage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showNameAlbumDialog() async {
|
void _showNameAlbumDialog() async {
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
title: const Text("Album title"),
|
title: const Text("Album title"),
|
||||||
content: TextFormField(
|
content: TextFormField(
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
|
@ -284,7 +284,7 @@ class _CreateCollectionPageState extends State<CreateCollectionPage> {
|
||||||
final dialog = createProgressDialog(context, "Moving files to album...");
|
final dialog = createProgressDialog(context, "Moving files to album...");
|
||||||
await dialog.show();
|
await dialog.show();
|
||||||
try {
|
try {
|
||||||
int fromCollectionID = widget.selectedFiles.files?.first?.collectionID;
|
final int fromCollectionID = widget.selectedFiles.files?.first?.collectionID;
|
||||||
await CollectionsService.instance.move(
|
await CollectionsService.instance.move(
|
||||||
toCollectionID,
|
toCollectionID,
|
||||||
fromCollectionID,
|
fromCollectionID,
|
||||||
|
|
|
@ -94,7 +94,7 @@ class GrantPermissionsWidget extends StatelessWidget {
|
||||||
state == PermissionState.limited) {
|
state == PermissionState.limited) {
|
||||||
await SyncService.instance.onPermissionGranted(state);
|
await SyncService.instance.onPermissionGranted(state);
|
||||||
} else if (state == PermissionState.denied) {
|
} else if (state == PermissionState.denied) {
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
title: const Text("Please grant permissions"),
|
title: const Text("Please grant permissions"),
|
||||||
content: const Text(
|
content: const Text(
|
||||||
"ente can encrypt and preserve files only if you grant access to them",
|
"ente can encrypt and preserve files only if you grant access to them",
|
||||||
|
|
|
@ -123,7 +123,7 @@ class _HomeWidgetState extends State<HomeWidget> {
|
||||||
});
|
});
|
||||||
_triggerLogoutEvent =
|
_triggerLogoutEvent =
|
||||||
Bus.instance.on<TriggerLogoutEvent>().listen((event) async {
|
Bus.instance.on<TriggerLogoutEvent>().listen((event) async {
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
title: const Text("Session expired"),
|
title: const Text("Session expired"),
|
||||||
content: const Text("Please login again"),
|
content: const Text("Please login again"),
|
||||||
actions: [
|
actions: [
|
||||||
|
@ -344,7 +344,7 @@ class _HomeWidgetState extends State<HomeWidget> {
|
||||||
Future<bool> _initDeepLinks() async {
|
Future<bool> _initDeepLinks() async {
|
||||||
// Platform messages may fail, so we use a try/catch PlatformException.
|
// Platform messages may fail, so we use a try/catch PlatformException.
|
||||||
try {
|
try {
|
||||||
String initialLink = await getInitialLink();
|
final String initialLink = await getInitialLink();
|
||||||
// Parse the link and warn the user, if it is not correct,
|
// Parse the link and warn the user, if it is not correct,
|
||||||
// but keep in mind it could be `null`.
|
// but keep in mind it could be `null`.
|
||||||
if (initialLink != null) {
|
if (initialLink != null) {
|
||||||
|
@ -609,7 +609,7 @@ class _HomeBottomNavigationBarState extends State<HomeBottomNavigationBar> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
bool filesAreSelected = widget.selectedFiles.files.isNotEmpty;
|
final bool filesAreSelected = widget.selectedFiles.files.isNotEmpty;
|
||||||
return AnimatedContainer(
|
return AnimatedContainer(
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOut,
|
||||||
|
|
|
@ -175,7 +175,7 @@ class DraggableScrollbarState extends State<DraggableScrollbar>
|
||||||
if (isDragging && details.delta.dy != 0) {
|
if (isDragging && details.delta.dy != 0) {
|
||||||
thumbOffset += details.delta.dy;
|
thumbOffset += details.delta.dy;
|
||||||
thumbOffset = thumbOffset.clamp(thumbMin, thumbMax);
|
thumbOffset = thumbOffset.clamp(thumbMin, thumbMax);
|
||||||
double position = thumbOffset / (thumbMax - thumbMin);
|
final double position = thumbOffset / (thumbMax - thumbMin);
|
||||||
widget.onChange?.call(position);
|
widget.onChange?.call(position);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -97,7 +97,7 @@ class HugeListViewState<T> extends State<HugeListView<T>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _sendScroll() {
|
void _sendScroll() {
|
||||||
int current = _currentFirst();
|
final int current = _currentFirst();
|
||||||
widget.firstShown?.call(current);
|
widget.firstShown?.call(current);
|
||||||
scrollKey.currentState?.setPosition(current / widget.totalCount, current);
|
scrollKey.currentState?.setPosition(current / widget.totalCount, current);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ class _LazyLoadingGalleryState extends State<LazyLoadingGallery> {
|
||||||
|
|
||||||
_currentIndexSubscription =
|
_currentIndexSubscription =
|
||||||
widget.currentIndexStream.listen((currentIndex) {
|
widget.currentIndexStream.listen((currentIndex) {
|
||||||
bool shouldRender = (currentIndex - widget.index).abs() <
|
final bool shouldRender = (currentIndex - widget.index).abs() <
|
||||||
kNumberOfDaysToRenderBeforeAndAfter;
|
kNumberOfDaysToRenderBeforeAndAfter;
|
||||||
if (mounted && shouldRender != _shouldRender) {
|
if (mounted && shouldRender != _shouldRender) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
@ -163,7 +163,7 @@ class _LazyLoadingGalleryState extends State<LazyLoadingGallery> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _getGallery() {
|
Widget _getGallery() {
|
||||||
List<Widget> childGalleries = [];
|
final List<Widget> childGalleries = [];
|
||||||
for (int index = 0; index < _files.length; index += kSubGalleryItemLimit) {
|
for (int index = 0; index < _files.length; index += kSubGalleryItemLimit) {
|
||||||
childGalleries.add(
|
childGalleries.add(
|
||||||
LazyLoadingGridView(
|
LazyLoadingGridView(
|
||||||
|
|
|
@ -66,9 +66,9 @@ class MemoriesWidget extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _areMemoriesFromSameYear(Memory first, Memory second) {
|
bool _areMemoriesFromSameYear(Memory first, Memory second) {
|
||||||
var firstDate =
|
final firstDate =
|
||||||
DateTime.fromMicrosecondsSinceEpoch(first.file.creationTime);
|
DateTime.fromMicrosecondsSinceEpoch(first.file.creationTime);
|
||||||
var secondDate =
|
final secondDate =
|
||||||
DateTime.fromMicrosecondsSinceEpoch(second.file.creationTime);
|
DateTime.fromMicrosecondsSinceEpoch(second.file.creationTime);
|
||||||
return firstDate.year == secondDate.year;
|
return firstDate.year == secondDate.year;
|
||||||
}
|
}
|
||||||
|
|
|
@ -321,7 +321,7 @@ class _ButtonState extends State<Button> with TickerProviderStateMixin {
|
||||||
expandController.forward();
|
expandController.forward();
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget icon = widget.leading ??
|
final Widget icon = widget.leading ??
|
||||||
Icon(
|
Icon(
|
||||||
widget.icon,
|
widget.icon,
|
||||||
color: _expanded ? widget.iconColor : widget.iconActiveColor,
|
color: _expanded ? widget.iconColor : widget.iconActiveColor,
|
||||||
|
|
|
@ -77,7 +77,7 @@ class _PaymentWebPageState extends State<PaymentWebPage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
shouldOverrideUrlLoading: (controller, navigationAction) async {
|
shouldOverrideUrlLoading: (controller, navigationAction) async {
|
||||||
var loadingUri = navigationAction.request.url;
|
final loadingUri = navigationAction.request.url;
|
||||||
_logger.info("Loading url $loadingUri");
|
_logger.info("Loading url $loadingUri");
|
||||||
// handle the payment response
|
// handle the payment response
|
||||||
if (_isPaymentActionComplete(loadingUri)) {
|
if (_isPaymentActionComplete(loadingUri)) {
|
||||||
|
@ -130,7 +130,7 @@ class _PaymentWebPageState extends State<PaymentWebPage> {
|
||||||
'action': widget.actionType,
|
'action': widget.actionType,
|
||||||
'redirectURL': kWebPaymentRedirectUrl,
|
'redirectURL': kWebPaymentRedirectUrl,
|
||||||
};
|
};
|
||||||
var tryParse = Uri.tryParse(kWebPaymentBaseEndpoint);
|
final tryParse = Uri.tryParse(kWebPaymentBaseEndpoint);
|
||||||
if (kDebugMode && kWebPaymentBaseEndpoint.startsWith("http://")) {
|
if (kDebugMode && kWebPaymentBaseEndpoint.startsWith("http://")) {
|
||||||
return Uri.http(tryParse.authority, tryParse.path, queryParameters);
|
return Uri.http(tryParse.authority, tryParse.path, queryParameters);
|
||||||
} else {
|
} else {
|
||||||
|
@ -173,13 +173,13 @@ class _PaymentWebPageState extends State<PaymentWebPage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _handlePaymentResponse(Uri uri) async {
|
Future<void> _handlePaymentResponse(Uri uri) async {
|
||||||
var queryParams = uri.queryParameters;
|
final queryParams = uri.queryParameters;
|
||||||
var paymentStatus = uri.queryParameters['status'] ?? '';
|
final paymentStatus = uri.queryParameters['status'] ?? '';
|
||||||
_logger.fine('handle payment response with status $paymentStatus');
|
_logger.fine('handle payment response with status $paymentStatus');
|
||||||
if (paymentStatus == 'success') {
|
if (paymentStatus == 'success') {
|
||||||
await _handlePaymentSuccess(queryParams);
|
await _handlePaymentSuccess(queryParams);
|
||||||
} else if (paymentStatus == 'fail') {
|
} else if (paymentStatus == 'fail') {
|
||||||
var reason = queryParams['reason'] ?? '';
|
final reason = queryParams['reason'] ?? '';
|
||||||
await _handlePaymentFailure(reason);
|
await _handlePaymentFailure(reason);
|
||||||
} else {
|
} else {
|
||||||
// should never reach here
|
// should never reach here
|
||||||
|
@ -210,17 +210,17 @@ class _PaymentWebPageState extends State<PaymentWebPage> {
|
||||||
|
|
||||||
// return true if verifySubscription didn't throw any exceptions
|
// return true if verifySubscription didn't throw any exceptions
|
||||||
Future<void> _handlePaymentSuccess(Map<String, String> queryParams) async {
|
Future<void> _handlePaymentSuccess(Map<String, String> queryParams) async {
|
||||||
var checkoutSessionID = queryParams['session_id'] ?? '';
|
final checkoutSessionID = queryParams['session_id'] ?? '';
|
||||||
await _dialog.show();
|
await _dialog.show();
|
||||||
try {
|
try {
|
||||||
var response = await billingService.verifySubscription(
|
final response = await billingService.verifySubscription(
|
||||||
widget.planId,
|
widget.planId,
|
||||||
checkoutSessionID,
|
checkoutSessionID,
|
||||||
paymentProvider: kStripe,
|
paymentProvider: kStripe,
|
||||||
);
|
);
|
||||||
await _dialog.hide();
|
await _dialog.hide();
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
var content = widget.actionType == 'buy'
|
final content = widget.actionType == 'buy'
|
||||||
? 'Your purchase was successful'
|
? 'Your purchase was successful'
|
||||||
: 'Your subscription was updated successfully';
|
: 'Your subscription was updated successfully';
|
||||||
await _showExitPageDialog(title: 'Thank you', content: content);
|
await _showExitPageDialog(title: 'Thank you', content: content);
|
||||||
|
|
|
@ -307,7 +307,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
|
||||||
Future<void> _launchStripePortal() async {
|
Future<void> _launchStripePortal() async {
|
||||||
await _dialog.show();
|
await _dialog.show();
|
||||||
try {
|
try {
|
||||||
String url = await _billingService.getStripeCustomerPortalUrl();
|
final String url = await _billingService.getStripeCustomerPortalUrl();
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
|
@ -353,9 +353,9 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _stripeRenewOrCancelButton() {
|
Widget _stripeRenewOrCancelButton() {
|
||||||
bool isRenewCancelled =
|
final bool isRenewCancelled =
|
||||||
_currentSubscription.attributes?.isCancelled ?? false;
|
_currentSubscription.attributes?.isCancelled ?? false;
|
||||||
String title =
|
final String title =
|
||||||
isRenewCancelled ? "Renew subscription" : "Cancel subscription";
|
isRenewCancelled ? "Renew subscription" : "Cancel subscription";
|
||||||
return TextButton(
|
return TextButton(
|
||||||
child: Text(
|
child: Text(
|
||||||
|
@ -370,7 +370,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
bool confirmAction = false;
|
bool confirmAction = false;
|
||||||
if (isRenewCancelled) {
|
if (isRenewCancelled) {
|
||||||
var choice = await showChoiceDialog(
|
final choice = await showChoiceDialog(
|
||||||
context,
|
context,
|
||||||
title,
|
title,
|
||||||
"Are you sure you want to renew?",
|
"Are you sure you want to renew?",
|
||||||
|
@ -379,7 +379,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
|
||||||
);
|
);
|
||||||
confirmAction = choice == DialogUserChoice.secondChoice;
|
confirmAction = choice == DialogUserChoice.secondChoice;
|
||||||
} else {
|
} else {
|
||||||
var choice = await showChoiceDialog(
|
final choice = await showChoiceDialog(
|
||||||
context,
|
context,
|
||||||
title,
|
title,
|
||||||
'Are you sure you want to cancel?',
|
'Are you sure you want to cancel?',
|
||||||
|
@ -455,7 +455,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
|
||||||
String stripPurChaseAction = 'buy';
|
String stripPurChaseAction = 'buy';
|
||||||
if (_isStripeSubscriber && _hasActiveSubscription) {
|
if (_isStripeSubscriber && _hasActiveSubscription) {
|
||||||
// confirm if user wants to change plan or not
|
// confirm if user wants to change plan or not
|
||||||
var result = await showChoiceDialog(
|
final result = await showChoiceDialog(
|
||||||
context,
|
context,
|
||||||
"Confirm plan change",
|
"Confirm plan change",
|
||||||
"Are you sure you want to change your plan?",
|
"Are you sure you want to change your plan?",
|
||||||
|
|
|
@ -87,7 +87,7 @@ class ValidityWidget extends StatelessWidget {
|
||||||
if (currentSubscription == null) {
|
if (currentSubscription == null) {
|
||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
var endDate = getDateAndMonthAndYear(
|
final endDate = getDateAndMonthAndYear(
|
||||||
DateTime.fromMicrosecondsSinceEpoch(currentSubscription.expiryTime),
|
DateTime.fromMicrosecondsSinceEpoch(currentSubscription.expiryTime),
|
||||||
);
|
);
|
||||||
var message = "Renews on $endDate";
|
var message = "Renews on $endDate";
|
||||||
|
|
|
@ -16,13 +16,13 @@ class SubscriptionPlanWidget extends StatelessWidget {
|
||||||
final bool isActive;
|
final bool isActive;
|
||||||
|
|
||||||
String _displayPrice() {
|
String _displayPrice() {
|
||||||
var result = price + (period.isNotEmpty ? " / " + period : "");
|
final result = price + (period.isNotEmpty ? " / " + period : "");
|
||||||
return result.isNotEmpty ? result : "Trial plan";
|
return result.isNotEmpty ? result : "Trial plan";
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Color textColor = isActive ? Colors.white : Colors.black;
|
final Color textColor = isActive ? Colors.white : Colors.black;
|
||||||
return Container(
|
return Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
color: Theme.of(context).colorScheme.onPrimary,
|
color: Theme.of(context).colorScheme.onPrimary,
|
||||||
|
|
|
@ -40,7 +40,7 @@ class AccountSectionWidgetState extends State<AccountSectionWidget> {
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
AppLock.of(context).setEnabled(false);
|
AppLock.of(context).setEnabled(false);
|
||||||
String reason = "Please authenticate to view your recovery key";
|
const String reason = "Please authenticate to view your recovery key";
|
||||||
final result = await requestAuthentication(reason);
|
final result = await requestAuthentication(reason);
|
||||||
AppLock.of(context)
|
AppLock.of(context)
|
||||||
.setEnabled(Configuration.instance.shouldShowLockScreen());
|
.setEnabled(Configuration.instance.shouldShowLockScreen());
|
||||||
|
@ -76,7 +76,7 @@ class AccountSectionWidgetState extends State<AccountSectionWidget> {
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
AppLock.of(context).setEnabled(false);
|
AppLock.of(context).setEnabled(false);
|
||||||
String reason = "Please authenticate to change your email";
|
const String reason = "Please authenticate to change your email";
|
||||||
final result = await requestAuthentication(reason);
|
final result = await requestAuthentication(reason);
|
||||||
AppLock.of(context)
|
AppLock.of(context)
|
||||||
.setEnabled(Configuration.instance.shouldShowLockScreen());
|
.setEnabled(Configuration.instance.shouldShowLockScreen());
|
||||||
|
@ -103,7 +103,7 @@ class AccountSectionWidgetState extends State<AccountSectionWidget> {
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
AppLock.of(context).setEnabled(false);
|
AppLock.of(context).setEnabled(false);
|
||||||
String reason = "Please authenticate to change your password";
|
const String reason = "Please authenticate to change your password";
|
||||||
final result = await requestAuthentication(reason);
|
final result = await requestAuthentication(reason);
|
||||||
AppLock.of(context)
|
AppLock.of(context)
|
||||||
.setEnabled(Configuration.instance.shouldShowLockScreen());
|
.setEnabled(Configuration.instance.shouldShowLockScreen());
|
||||||
|
|
|
@ -153,7 +153,7 @@ class _ApkDownloaderDialogState extends State<ApkDownloaderDialog> {
|
||||||
OpenFile.open(_saveUrl);
|
OpenFile.open(_saveUrl);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Logger("ApkDownloader").severe(e);
|
Logger("ApkDownloader").severe(e);
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
title: const Text("Sorry"),
|
title: const Text("Sorry"),
|
||||||
content: const Text("The download could not be completed"),
|
content: const Text("The download could not be completed"),
|
||||||
actions: [
|
actions: [
|
||||||
|
|
|
@ -25,7 +25,7 @@ class _AppVersionWidgetState extends State<AppVersionWidget> {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
int now = DateTime.now().millisecondsSinceEpoch;
|
final int now = DateTime.now().millisecondsSinceEpoch;
|
||||||
if (now - (_lastTap ?? now) < kConsecutiveTapTimeWindowInMilliseconds) {
|
if (now - (_lastTap ?? now) < kConsecutiveTapTimeWindowInMilliseconds) {
|
||||||
_consecutiveTaps++;
|
_consecutiveTaps++;
|
||||||
if (_consecutiveTaps == kTapThresholdForInspector) {
|
if (_consecutiveTaps == kTapThresholdForInspector) {
|
||||||
|
|
|
@ -113,7 +113,7 @@ class BackupSectionWidgetState extends State<BackupSectionWidget> {
|
||||||
value: Configuration.instance.shouldKeepDeviceAwake(),
|
value: Configuration.instance.shouldKeepDeviceAwake(),
|
||||||
onChanged: (value) async {
|
onChanged: (value) async {
|
||||||
if (value) {
|
if (value) {
|
||||||
var choice = await showChoiceDialog(
|
final choice = await showChoiceDialog(
|
||||||
context,
|
context,
|
||||||
"Disable automatic screen lock when ente is running?",
|
"Disable automatic screen lock when ente is running?",
|
||||||
"This will ensure faster uploads by ensuring your device does not sleep when uploads are in progress.",
|
"This will ensure faster uploads by ensuring your device does not sleep when uploads are in progress.",
|
||||||
|
@ -158,7 +158,7 @@ class BackupSectionWidgetState extends State<BackupSectionWidget> {
|
||||||
"You've no files on this device that can be deleted",
|
"You've no files on this device that can be deleted",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
bool result = await routeToPage(context, FreeSpacePage(status));
|
final bool result = await routeToPage(context, FreeSpacePage(status));
|
||||||
if (result == true) {
|
if (result == true) {
|
||||||
_showSpaceFreedDialog(status);
|
_showSpaceFreedDialog(status);
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ class BackupSectionWidgetState extends State<BackupSectionWidget> {
|
||||||
"You've no duplicate files that can be cleared",
|
"You've no duplicate files that can be cleared",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
DeduplicationResult result =
|
final DeduplicationResult result =
|
||||||
await routeToPage(context, DeduplicatePage(duplicates));
|
await routeToPage(context, DeduplicatePage(duplicates));
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
_showDuplicateFilesDeletedDialog(result);
|
_showDuplicateFilesDeletedDialog(result);
|
||||||
|
@ -213,7 +213,7 @@ class BackupSectionWidgetState extends State<BackupSectionWidget> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showSpaceFreedDialog(BackupStatus status) {
|
void _showSpaceFreedDialog(BackupStatus status) {
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
title: const Text("Success"),
|
title: const Text("Success"),
|
||||||
content: Text(
|
content: Text(
|
||||||
"You have successfully freed up " + formatBytes(status.size) + "!",
|
"You have successfully freed up " + formatBytes(status.size) + "!",
|
||||||
|
@ -268,10 +268,10 @@ class BackupSectionWidgetState extends State<BackupSectionWidget> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showDuplicateFilesDeletedDialog(DeduplicationResult result) {
|
void _showDuplicateFilesDeletedDialog(DeduplicationResult result) {
|
||||||
String countText = result.count.toString() +
|
final String countText = result.count.toString() +
|
||||||
" duplicate file" +
|
" duplicate file" +
|
||||||
(result.count == 1 ? "" : "s");
|
(result.count == 1 ? "" : "s");
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
title: const Text("✨ Success"),
|
title: const Text("✨ Success"),
|
||||||
content: Text(
|
content: Text(
|
||||||
"You have cleaned up " +
|
"You have cleaned up " +
|
||||||
|
|
|
@ -53,7 +53,7 @@ class _DangerSectionWidgetState extends State<DangerSectionWidget> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onLogoutTapped() async {
|
Future<void> _onLogoutTapped() async {
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
title: const Text(
|
title: const Text(
|
||||||
"Logout",
|
"Logout",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
|
|
@ -48,7 +48,7 @@ class DebugSectionWidget extends StatelessWidget {
|
||||||
|
|
||||||
void _showKeyAttributesDialog(BuildContext context) {
|
void _showKeyAttributesDialog(BuildContext context) {
|
||||||
final keyAttributes = Configuration.instance.getKeyAttributes();
|
final keyAttributes = Configuration.instance.getKeyAttributes();
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
title: const Text("key attributes"),
|
title: const Text("key attributes"),
|
||||||
content: SingleChildScrollView(
|
content: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|
|
@ -83,7 +83,7 @@ class _SecuritySectionWidgetState extends State<SecuritySectionWidget> {
|
||||||
value: snapshot.data,
|
value: snapshot.data,
|
||||||
onChanged: (value) async {
|
onChanged: (value) async {
|
||||||
AppLock.of(context).setEnabled(false);
|
AppLock.of(context).setEnabled(false);
|
||||||
String reason =
|
const String reason =
|
||||||
"Please authenticate to configure two-factor authentication";
|
"Please authenticate to configure two-factor authentication";
|
||||||
final result = await requestAuthentication(reason);
|
final result = await requestAuthentication(reason);
|
||||||
AppLock.of(context).setEnabled(
|
AppLock.of(context).setEnabled(
|
||||||
|
@ -164,7 +164,7 @@ class _SecuritySectionWidgetState extends State<SecuritySectionWidget> {
|
||||||
value: _config.shouldHideFromRecents(),
|
value: _config.shouldHideFromRecents(),
|
||||||
onChanged: (value) async {
|
onChanged: (value) async {
|
||||||
if (value) {
|
if (value) {
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
title: const Text("Hide from recents?"),
|
title: const Text("Hide from recents?"),
|
||||||
content: SingleChildScrollView(
|
content: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
|
@ -278,7 +278,7 @@ class _SecuritySectionWidgetState extends State<SecuritySectionWidget> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _disableTwoFactor() {
|
void _disableTwoFactor() {
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
title: const Text("Disable two-factor"),
|
title: const Text("Disable two-factor"),
|
||||||
content: const Text(
|
content: const Text(
|
||||||
"Are you sure you want to disable two-factor authentication?",
|
"Are you sure you want to disable two-factor authentication?",
|
||||||
|
|
|
@ -22,7 +22,7 @@ class SocialSectionWidget extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _getSectionOptions(BuildContext context) {
|
Widget _getSectionOptions(BuildContext context) {
|
||||||
List<Widget> options = [
|
final List<Widget> options = [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
|
|
@ -112,9 +112,9 @@ class _SharedCollectionGalleryState extends State<SharedCollectionGallery>
|
||||||
Widget _getSharedCollectionsGallery(SharedCollections collections) {
|
Widget _getSharedCollectionsGallery(SharedCollections collections) {
|
||||||
const double horizontalPaddingOfGridRow = 16;
|
const double horizontalPaddingOfGridRow = 16;
|
||||||
const double crossAxisSpacingOfGrid = 9;
|
const double crossAxisSpacingOfGrid = 9;
|
||||||
Size size = MediaQuery.of(context).size;
|
final Size size = MediaQuery.of(context).size;
|
||||||
int albumsCountInOneRow = max(size.width ~/ 220.0, 2);
|
final int albumsCountInOneRow = max(size.width ~/ 220.0, 2);
|
||||||
double totalWhiteSpaceOfRow = (horizontalPaddingOfGridRow * 2) +
|
final double totalWhiteSpaceOfRow = (horizontalPaddingOfGridRow * 2) +
|
||||||
(albumsCountInOneRow - 1) * crossAxisSpacingOfGrid;
|
(albumsCountInOneRow - 1) * crossAxisSpacingOfGrid;
|
||||||
final double sideOfThumbnail = (size.width / albumsCountInOneRow) -
|
final double sideOfThumbnail = (size.width / albumsCountInOneRow) -
|
||||||
(totalWhiteSpaceOfRow / albumsCountInOneRow);
|
(totalWhiteSpaceOfRow / albumsCountInOneRow);
|
||||||
|
@ -363,11 +363,11 @@ class IncomingCollectionItem extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
const double horizontalPaddingOfGridRow = 16;
|
const double horizontalPaddingOfGridRow = 16;
|
||||||
const double crossAxisSpacingOfGrid = 9;
|
const double crossAxisSpacingOfGrid = 9;
|
||||||
TextStyle albumTitleTextStyle =
|
final TextStyle albumTitleTextStyle =
|
||||||
Theme.of(context).textTheme.subtitle1.copyWith(fontSize: 14);
|
Theme.of(context).textTheme.subtitle1.copyWith(fontSize: 14);
|
||||||
Size size = MediaQuery.of(context).size;
|
final Size size = MediaQuery.of(context).size;
|
||||||
int albumsCountInOneRow = max(size.width ~/ 220.0, 2);
|
final int albumsCountInOneRow = max(size.width ~/ 220.0, 2);
|
||||||
double totalWhiteSpaceOfRow = (horizontalPaddingOfGridRow * 2) +
|
final double totalWhiteSpaceOfRow = (horizontalPaddingOfGridRow * 2) +
|
||||||
(albumsCountInOneRow - 1) * crossAxisSpacingOfGrid;
|
(albumsCountInOneRow - 1) * crossAxisSpacingOfGrid;
|
||||||
final double sideOfThumbnail = (size.width / albumsCountInOneRow) -
|
final double sideOfThumbnail = (size.width / albumsCountInOneRow) -
|
||||||
(totalWhiteSpaceOfRow / albumsCountInOneRow);
|
(totalWhiteSpaceOfRow / albumsCountInOneRow);
|
||||||
|
|
|
@ -131,12 +131,12 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
|
||||||
false,
|
false,
|
||||||
onChanged: (enablePassword) async {
|
onChanged: (enablePassword) async {
|
||||||
if (enablePassword) {
|
if (enablePassword) {
|
||||||
var inputResult =
|
final inputResult =
|
||||||
await _displayLinkPasswordInput(context);
|
await _displayLinkPasswordInput(context);
|
||||||
if (inputResult != null &&
|
if (inputResult != null &&
|
||||||
inputResult == 'ok' &&
|
inputResult == 'ok' &&
|
||||||
_textFieldController.text.trim().isNotEmpty) {
|
_textFieldController.text.trim().isNotEmpty) {
|
||||||
var propToUpdate = await _getEncryptedPassword(
|
final propToUpdate = await _getEncryptedPassword(
|
||||||
_textFieldController.text,
|
_textFieldController.text,
|
||||||
);
|
);
|
||||||
await _updateUrlSettings(context, propToUpdate);
|
await _updateUrlSettings(context, propToUpdate);
|
||||||
|
@ -250,10 +250,10 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
|
||||||
CupertinoButton(
|
CupertinoButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
int newValidTill = -1;
|
int newValidTill = -1;
|
||||||
int expireAfterInMicroseconds = _selectedExpiry.item3;
|
final int expireAfterInMicroseconds = _selectedExpiry.item3;
|
||||||
// need to manually select time
|
// need to manually select time
|
||||||
if (expireAfterInMicroseconds < 0) {
|
if (expireAfterInMicroseconds < 0) {
|
||||||
var timeInMicrosecondsFromEpoch =
|
final timeInMicrosecondsFromEpoch =
|
||||||
await _showDateTimePicker();
|
await _showDateTimePicker();
|
||||||
if (timeInMicrosecondsFromEpoch != null) {
|
if (timeInMicrosecondsFromEpoch != null) {
|
||||||
newValidTill = timeInMicrosecondsFromEpoch;
|
newValidTill = timeInMicrosecondsFromEpoch;
|
||||||
|
@ -293,7 +293,7 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
Theme.of(context).backgroundColor.withOpacity(0.95),
|
Theme.of(context).backgroundColor.withOpacity(0.95),
|
||||||
onSelectedItemChanged: (value) {
|
onSelectedItemChanged: (value) {
|
||||||
var firstWhere = _expiryOptions
|
final firstWhere = _expiryOptions
|
||||||
.firstWhere((element) => element.item1 == value);
|
.firstWhere((element) => element.item1 == value);
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedExpiry = firstWhere;
|
_selectedExpiry = firstWhere;
|
||||||
|
@ -410,8 +410,8 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
|
||||||
Sodium.cryptoPwhashAlgArgon2id13 == Sodium.cryptoPwhashAlgDefault,
|
Sodium.cryptoPwhashAlgArgon2id13 == Sodium.cryptoPwhashAlgDefault,
|
||||||
"mismatch in expected default pw hashing algo",
|
"mismatch in expected default pw hashing algo",
|
||||||
);
|
);
|
||||||
int memLimit = Sodium.cryptoPwhashMemlimitInteractive;
|
final int memLimit = Sodium.cryptoPwhashMemlimitInteractive;
|
||||||
int opsLimit = Sodium.cryptoPwhashOpslimitInteractive;
|
final int opsLimit = Sodium.cryptoPwhashOpslimitInteractive;
|
||||||
final kekSalt = CryptoUtil.getSaltToDeriveKey();
|
final kekSalt = CryptoUtil.getSaltToDeriveKey();
|
||||||
final result = await CryptoUtil.deriveKey(
|
final result = await CryptoUtil.deriveKey(
|
||||||
utf8.encode(pass),
|
utf8.encode(pass),
|
||||||
|
@ -444,7 +444,7 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Text _getLinkExpiryTimeWidget() {
|
Text _getLinkExpiryTimeWidget() {
|
||||||
int validTill = widget.collection.publicURLs?.first?.validTill ?? 0;
|
final int validTill = widget.collection.publicURLs?.first?.validTill ?? 0;
|
||||||
if (validTill == 0) {
|
if (validTill == 0) {
|
||||||
return const Text(
|
return const Text(
|
||||||
'Never',
|
'Never',
|
||||||
|
@ -470,7 +470,7 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _showDeviceLimitPicker() async {
|
Future<void> _showDeviceLimitPicker() async {
|
||||||
List<Text> options = [];
|
final List<Text> options = [];
|
||||||
for (int i = 50; i > 0; i--) {
|
for (int i = 50; i > 0; i--) {
|
||||||
options.add(
|
options.add(
|
||||||
Text(i.toString(), style: Theme.of(context).textTheme.subtitle1),
|
Text(i.toString(), style: Theme.of(context).textTheme.subtitle1),
|
||||||
|
|
|
@ -91,7 +91,7 @@ class _SharingDialogState extends State<SharingDialog> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FeatureFlagService.instance.disableUrlSharing()) {
|
if (!FeatureFlagService.instance.disableUrlSharing()) {
|
||||||
bool hasUrl = widget.collection.publicURLs?.isNotEmpty ?? false;
|
final bool hasUrl = widget.collection.publicURLs?.isNotEmpty ?? false;
|
||||||
children.addAll([
|
children.addAll([
|
||||||
const Padding(padding: EdgeInsets.all(16)),
|
const Padding(padding: EdgeInsets.all(16)),
|
||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
|
@ -246,10 +246,10 @@ class _SharingDialogState extends State<SharingDialog> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _getShareableUrlWidget(BuildContext parentContext) {
|
Widget _getShareableUrlWidget(BuildContext parentContext) {
|
||||||
String collectionKey = Base58Encode(
|
final String collectionKey = Base58Encode(
|
||||||
CollectionsService.instance.getCollectionKey(widget.collection.id),
|
CollectionsService.instance.getCollectionKey(widget.collection.id),
|
||||||
);
|
);
|
||||||
String url = "${widget.collection.publicURLs.first.url}#$collectionKey";
|
final String url = "${widget.collection.publicURLs.first.url}#$collectionKey";
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
@ -436,7 +436,7 @@ class _SharingDialogState extends State<SharingDialog> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showUnSupportedAlert() {
|
void _showUnSupportedAlert() {
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
title: const Text("Sorry"),
|
title: const Text("Sorry"),
|
||||||
content: const Text(
|
content: const Text(
|
||||||
"Sharing is not permitted for free accounts, please subscribe",
|
"Sharing is not permitted for free accounts, please subscribe",
|
||||||
|
|
|
@ -135,7 +135,7 @@ class _SyncStatusWidgetState extends State<SyncStatusWidget> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
bool isNotOutdatedEvent = _event != null &&
|
final bool isNotOutdatedEvent = _event != null &&
|
||||||
(_event.status == SyncStatus.completedBackup ||
|
(_event.status == SyncStatus.completedBackup ||
|
||||||
_event.status == SyncStatus.completedFirstGalleryImport) &&
|
_event.status == SyncStatus.completedFirstGalleryImport) &&
|
||||||
(DateTime.now().microsecondsSinceEpoch - _event.timestamp >
|
(DateTime.now().microsecondsSinceEpoch - _event.timestamp >
|
||||||
|
|
|
@ -70,11 +70,11 @@ class ColorFilterGenerator {
|
||||||
0,
|
0,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
double cosVal = cos(value);
|
final double cosVal = cos(value);
|
||||||
double sinVal = sin(value);
|
final double sinVal = sin(value);
|
||||||
double lumR = 0.213;
|
const double lumR = 0.213;
|
||||||
double lumG = 0.715;
|
const double lumG = 0.715;
|
||||||
double lumB = 0.072;
|
const double lumB = 0.072;
|
||||||
|
|
||||||
return List<double>.from(<double>[
|
return List<double>.from(<double>[
|
||||||
(lumR + (cosVal * (1 - lumR))) + (sinVal * (-lumR)),
|
(lumR + (cosVal * (1 - lumR))) + (sinVal * (-lumR)),
|
||||||
|
|
|
@ -157,7 +157,7 @@ class _ImageEditorPageState extends State<ImageEditorPage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildFlipButton() {
|
Widget _buildFlipButton() {
|
||||||
TextStyle subtitle2 = Theme.of(context).textTheme.subtitle2;
|
final TextStyle subtitle2 = Theme.of(context).textTheme.subtitle2;
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
|
@ -191,7 +191,7 @@ class _ImageEditorPageState extends State<ImageEditorPage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildRotateLeftButton() {
|
Widget _buildRotateLeftButton() {
|
||||||
TextStyle subtitle2 = Theme.of(context).textTheme.subtitle2;
|
final TextStyle subtitle2 = Theme.of(context).textTheme.subtitle2;
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
|
@ -221,7 +221,7 @@ class _ImageEditorPageState extends State<ImageEditorPage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildRotateRightButton() {
|
Widget _buildRotateRightButton() {
|
||||||
TextStyle subtitle2 = Theme.of(context).textTheme.subtitle2;
|
final TextStyle subtitle2 = Theme.of(context).textTheme.subtitle2;
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
|
@ -251,7 +251,7 @@ class _ImageEditorPageState extends State<ImageEditorPage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSaveButton() {
|
Widget _buildSaveButton() {
|
||||||
TextStyle subtitle2 = Theme.of(context).textTheme.subtitle2;
|
final TextStyle subtitle2 = Theme.of(context).textTheme.subtitle2;
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
|
@ -349,7 +349,7 @@ class _ImageEditorPageState extends State<ImageEditorPage> {
|
||||||
newFile.collectionID = widget.originalFile.collectionID;
|
newFile.collectionID = widget.originalFile.collectionID;
|
||||||
newFile.location = widget.originalFile.location;
|
newFile.location = widget.originalFile.location;
|
||||||
if (!newFile.hasLocation() && widget.originalFile.localID != null) {
|
if (!newFile.hasLocation() && widget.originalFile.localID != null) {
|
||||||
var assetEntity = await widget.originalFile.getAsset();
|
final assetEntity = await widget.originalFile.getAsset();
|
||||||
if (assetEntity != null) {
|
if (assetEntity != null) {
|
||||||
final latLong = await assetEntity.latlngAsync();
|
final latLong = await assetEntity.latlngAsync();
|
||||||
newFile.location = Location(latLong.latitude, latLong.longitude);
|
newFile.location = Location(latLong.latitude, latLong.longitude);
|
||||||
|
@ -394,7 +394,7 @@ class _ImageEditorPageState extends State<ImageEditorPage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSat() {
|
Widget _buildSat() {
|
||||||
TextStyle subtitle2 = Theme.of(context).textTheme.subtitle2;
|
final TextStyle subtitle2 = Theme.of(context).textTheme.subtitle2;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
|
padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
|
||||||
|
@ -440,7 +440,7 @@ class _ImageEditorPageState extends State<ImageEditorPage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildBrightness() {
|
Widget _buildBrightness() {
|
||||||
TextStyle subtitle2 = Theme.of(context).textTheme.subtitle2;
|
final TextStyle subtitle2 = Theme.of(context).textTheme.subtitle2;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
|
padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
|
||||||
|
@ -486,7 +486,7 @@ class _ImageEditorPageState extends State<ImageEditorPage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _showExitConfirmationDialog() async {
|
Future<void> _showExitConfirmationDialog() async {
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
title: const Text("Discard edits?"),
|
title: const Text("Discard edits?"),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class CustomAppBar extends PreferredSize {
|
class CustomAppBar extends PreferredSize {
|
||||||
|
@override
|
||||||
final Widget child;
|
final Widget child;
|
||||||
final double height;
|
final double height;
|
||||||
|
|
||||||
|
|
|
@ -139,7 +139,7 @@ class _DetailPageState extends State<DetailPage> {
|
||||||
return PageView.builder(
|
return PageView.builder(
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final file = _files[index];
|
final file = _files[index];
|
||||||
Widget content = FileWidget(
|
final Widget content = FileWidget(
|
||||||
file,
|
file,
|
||||||
autoPlay: !_hasPageChanged,
|
autoPlay: !_hasPageChanged,
|
||||||
tagPrefix: widget.config.tagPrefix,
|
tagPrefix: widget.config.tagPrefix,
|
||||||
|
|
|
@ -300,9 +300,9 @@ class FadingAppBarState extends State<FadingAppBar> {
|
||||||
Future<void> _download(File file) async {
|
Future<void> _download(File file) async {
|
||||||
final dialog = createProgressDialog(context, "Downloading...");
|
final dialog = createProgressDialog(context, "Downloading...");
|
||||||
await dialog.show();
|
await dialog.show();
|
||||||
FileType type = file.fileType;
|
final FileType type = file.fileType;
|
||||||
// save and track image for livePhoto/image and video for FileType.video
|
// save and track image for livePhoto/image and video for FileType.video
|
||||||
io.File fileToSave = await getFile(file);
|
final io.File fileToSave = await getFile(file);
|
||||||
final savedAsset = type == FileType.video
|
final savedAsset = type == FileType.video
|
||||||
? (await PhotoManager.editor.saveVideo(fileToSave, title: file.title))
|
? (await PhotoManager.editor.saveVideo(fileToSave, title: file.title))
|
||||||
: (await PhotoManager.editor
|
: (await PhotoManager.editor
|
||||||
|
@ -313,7 +313,7 @@ class FadingAppBarState extends State<FadingAppBar> {
|
||||||
await FilesDB.instance.insert(file);
|
await FilesDB.instance.insert(file);
|
||||||
|
|
||||||
if (type == FileType.livePhoto) {
|
if (type == FileType.livePhoto) {
|
||||||
io.File liveVideo = await getFileFromServer(file, liveVideo: true);
|
final io.File liveVideo = await getFileFromServer(file, liveVideo: true);
|
||||||
if (liveVideo == null) {
|
if (liveVideo == null) {
|
||||||
_logger.warning("Failed to find live video" + file.tag());
|
_logger.warning("Failed to find live video" + file.tag());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -59,7 +59,7 @@ class FadingBottomBarState extends State<FadingBottomBar> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _getBottomBar() {
|
Widget _getBottomBar() {
|
||||||
List<Widget> children = [];
|
final List<Widget> children = [];
|
||||||
children.add(
|
children.add(
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message: "Info",
|
message: "Info",
|
||||||
|
@ -103,7 +103,7 @@ class FadingBottomBarState extends State<FadingBottomBar> {
|
||||||
}
|
}
|
||||||
if (widget.file.uploadedFileID != null &&
|
if (widget.file.uploadedFileID != null &&
|
||||||
widget.file.ownerID == Configuration.instance.getUserID()) {
|
widget.file.ownerID == Configuration.instance.getUserID()) {
|
||||||
bool isArchived =
|
final bool isArchived =
|
||||||
widget.file.magicMetadata.visibility == kVisibilityArchive;
|
widget.file.magicMetadata.visibility == kVisibilityArchive;
|
||||||
children.add(
|
children.add(
|
||||||
Tooltip(
|
Tooltip(
|
||||||
|
@ -151,7 +151,7 @@ class FadingBottomBarState extends State<FadingBottomBar> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
var safeAreaBottomPadding = MediaQuery.of(context).padding.bottom * .5;
|
final safeAreaBottomPadding = MediaQuery.of(context).padding.bottom * .5;
|
||||||
return IgnorePointer(
|
return IgnorePointer(
|
||||||
ignoring: _shouldHide,
|
ignoring: _shouldHide,
|
||||||
child: AnimatedOpacity(
|
child: AnimatedOpacity(
|
||||||
|
|
|
@ -76,7 +76,7 @@ class _FileInfoWidgetState extends State<FileInfoWidget> {
|
||||||
_exifData["ISO"] != null;
|
_exifData["ISO"] != null;
|
||||||
final bool showDimension =
|
final bool showDimension =
|
||||||
_exifData["resolution"] != null && _exifData["megaPixels"] != null;
|
_exifData["resolution"] != null && _exifData["megaPixels"] != null;
|
||||||
var listTiles = <Widget>[
|
final listTiles = <Widget>[
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Padding(
|
leading: const Padding(
|
||||||
padding: EdgeInsets.only(top: 8, left: 6),
|
padding: EdgeInsets.only(top: 8, left: 6),
|
||||||
|
@ -207,7 +207,7 @@ class _FileInfoWidgetState extends State<FileInfoWidget> {
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (file.collectionID != null) {
|
if (file.collectionID != null) {
|
||||||
Navigator.pop(context); // info dialog
|
Navigator.pop(context); // info dialog
|
||||||
Collection c = CollectionsService.instance
|
final Collection c = CollectionsService.instance
|
||||||
.getCollectionByID(file.collectionID);
|
.getCollectionByID(file.collectionID);
|
||||||
routeToPage(
|
routeToPage(
|
||||||
context,
|
context,
|
||||||
|
|
|
@ -91,7 +91,7 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
|
||||||
// If yes, parent thumbnail widget can be stateless
|
// If yes, parent thumbnail widget can be stateless
|
||||||
Widget content;
|
Widget content;
|
||||||
if (image != null) {
|
if (image != null) {
|
||||||
List<Widget> contentChildren = [image];
|
final List<Widget> contentChildren = [image];
|
||||||
if (widget.file.fileType == FileType.video) {
|
if (widget.file.fileType == FileType.video) {
|
||||||
contentChildren.add(const VideoOverlayIcon());
|
contentChildren.add(const VideoOverlayIcon());
|
||||||
} else if (widget.file.fileType == FileType.livePhoto &&
|
} else if (widget.file.fileType == FileType.livePhoto &&
|
||||||
|
@ -105,7 +105,7 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
|
||||||
children: contentChildren,
|
children: contentChildren,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
List<Widget> viewChildren = [
|
final List<Widget> viewChildren = [
|
||||||
const ThumbnailPlaceHolder(),
|
const ThumbnailPlaceHolder(),
|
||||||
AnimatedOpacity(
|
AnimatedOpacity(
|
||||||
opacity: content == null ? 0 : 1.0,
|
opacity: content == null ? 0 : 1.0,
|
||||||
|
|
|
@ -242,7 +242,7 @@ class _VideoControlsState extends State<VideoControls> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _playPause() {
|
void _playPause() {
|
||||||
bool isFinished = _latestValue.position >= _latestValue.duration;
|
final bool isFinished = _latestValue.position >= _latestValue.duration;
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
if (controller.value.isPlaying) {
|
if (controller.value.isPlaying) {
|
||||||
|
|
|
@ -88,7 +88,7 @@ class _ZoomableImageState extends State<ZoomableImage>
|
||||||
content = const EnteLoadingWidget();
|
content = const EnteLoadingWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
GestureDragUpdateCallback verticalDragCallback = _isZooming
|
final GestureDragUpdateCallback verticalDragCallback = _isZooming
|
||||||
? null
|
? null
|
||||||
: (d) => {
|
: (d) => {
|
||||||
if (!_isZooming && d.delta.dy > kDragSensitivity)
|
if (!_isZooming && d.delta.dy > kDragSensitivity)
|
||||||
|
|
|
@ -152,7 +152,7 @@ class _ZoomableLiveImageState extends State<ZoomableLiveImage>
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoPlayerController _setVideoPlayerController({io.File file}) {
|
VideoPlayerController _setVideoPlayerController({io.File file}) {
|
||||||
var videoPlayerController = VideoPlayerController.file(file);
|
final videoPlayerController = VideoPlayerController.file(file);
|
||||||
return _videoPlayerController = videoPlayerController
|
return _videoPlayerController = videoPlayerController
|
||||||
..initialize().whenComplete(() {
|
..initialize().whenComplete(() {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
@ -164,8 +164,8 @@ class _ZoomableLiveImageState extends State<ZoomableLiveImage>
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showLivePhotoToast() async {
|
void _showLivePhotoToast() async {
|
||||||
var preferences = await SharedPreferences.getInstance();
|
final preferences = await SharedPreferences.getInstance();
|
||||||
int promptTillNow = preferences.getInt(kLivePhotoToastCounterKey) ?? 0;
|
final int promptTillNow = preferences.getInt(kLivePhotoToastCounterKey) ?? 0;
|
||||||
if (promptTillNow < kMaxLivePhotoToastCount && mounted) {
|
if (promptTillNow < kMaxLivePhotoToastCount && mounted) {
|
||||||
showToast(context, "Press and hold to play video");
|
showToast(context, "Press and hold to play video");
|
||||||
preferences.setInt(kLivePhotoToastCounterKey, promptTillNow + 1);
|
preferences.setInt(kLivePhotoToastCounterKey, promptTillNow + 1);
|
||||||
|
|
|
@ -183,7 +183,7 @@ class _GalleryState extends State<Gallery> {
|
||||||
return const EnteLoadingWidget();
|
return const EnteLoadingWidget();
|
||||||
},
|
},
|
||||||
emptyResultBuilder: (_) {
|
emptyResultBuilder: (_) {
|
||||||
List<Widget> children = [];
|
final List<Widget> children = [];
|
||||||
if (widget.header != null) {
|
if (widget.header != null) {
|
||||||
children.add(widget.header);
|
children.add(widget.header);
|
||||||
}
|
}
|
||||||
|
@ -269,8 +269,8 @@ class _GalleryState extends State<Gallery> {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _areFromSameDay(int firstCreationTime, int secondCreationTime) {
|
bool _areFromSameDay(int firstCreationTime, int secondCreationTime) {
|
||||||
var firstDate = DateTime.fromMicrosecondsSinceEpoch(firstCreationTime);
|
final firstDate = DateTime.fromMicrosecondsSinceEpoch(firstCreationTime);
|
||||||
var secondDate = DateTime.fromMicrosecondsSinceEpoch(secondCreationTime);
|
final secondDate = DateTime.fromMicrosecondsSinceEpoch(secondCreationTime);
|
||||||
return firstDate.year == secondDate.year &&
|
return firstDate.year == secondDate.year &&
|
||||||
firstDate.month == secondDate.month &&
|
firstDate.month == secondDate.month &&
|
||||||
firstDate.day == secondDate.day;
|
firstDate.day == secondDate.day;
|
||||||
|
|
|
@ -118,7 +118,7 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _getDefaultActions(BuildContext context) {
|
List<Widget> _getDefaultActions(BuildContext context) {
|
||||||
List<Widget> actions = <Widget>[];
|
final List<Widget> actions = <Widget>[];
|
||||||
if (Configuration.instance.hasConfiguredAccount() &&
|
if (Configuration.instance.hasConfiguredAccount() &&
|
||||||
widget.selectedFiles.files.isEmpty &&
|
widget.selectedFiles.files.isEmpty &&
|
||||||
(widget.type == GalleryType.localFolder ||
|
(widget.type == GalleryType.localFolder ||
|
||||||
|
@ -156,7 +156,7 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
bool isArchived = widget.collection.isArchived();
|
final bool isArchived = widget.collection.isArchived();
|
||||||
items.add(
|
items.add(
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
value: 2,
|
value: 2,
|
||||||
|
|
|
@ -66,7 +66,7 @@ class _GalleryOverlayWidgetState extends State<GalleryOverlayWidget> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
bool filesAreSelected = widget.selectedFiles.files.isNotEmpty;
|
final bool filesAreSelected = widget.selectedFiles.files.isNotEmpty;
|
||||||
final bottomPadding = Platform.isAndroid ? 0.0 : 12.0;
|
final bottomPadding = Platform.isAndroid ? 0.0 : 12.0;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.only(bottom: bottomPadding),
|
padding: EdgeInsets.only(bottom: bottomPadding),
|
||||||
|
@ -254,7 +254,7 @@ class _OverlayWidgetState extends State<OverlayWidget> {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _getActions(BuildContext context) {
|
List<Widget> _getActions(BuildContext context) {
|
||||||
List<Widget> actions = <Widget>[];
|
final List<Widget> actions = <Widget>[];
|
||||||
if (widget.type == GalleryType.trash) {
|
if (widget.type == GalleryType.trash) {
|
||||||
_addTrashAction(actions);
|
_addTrashAction(actions);
|
||||||
return actions;
|
return actions;
|
||||||
|
@ -372,7 +372,7 @@ class _OverlayWidgetState extends State<OverlayWidget> {
|
||||||
|
|
||||||
if (widget.type == GalleryType.homepage ||
|
if (widget.type == GalleryType.homepage ||
|
||||||
widget.type == GalleryType.archive) {
|
widget.type == GalleryType.archive) {
|
||||||
bool showArchive = widget.type == GalleryType.homepage;
|
final bool showArchive = widget.type == GalleryType.homepage;
|
||||||
actions.add(
|
actions.add(
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message: showArchive ? "Hide" : "Unhide",
|
message: showArchive ? "Hide" : "Unhide",
|
||||||
|
|
|
@ -48,7 +48,7 @@ class _TrashPageState extends State<TrashPage> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(Object context) {
|
Widget build(Object context) {
|
||||||
bool filesAreSelected = widget._selectedFiles.files.isNotEmpty;
|
final bool filesAreSelected = widget._selectedFiles.files.isNotEmpty;
|
||||||
|
|
||||||
final gallery = Gallery(
|
final gallery = Gallery(
|
||||||
asyncLoader: (creationStartTime, creationEndTime, {limit, asc}) {
|
asyncLoader: (creationStartTime, creationEndTime, {limit, asc}) {
|
||||||
|
|
|
@ -20,7 +20,7 @@ String convertBytesToReadableFormat(int bytes) {
|
||||||
String formatBytes(int bytes, [int decimals = 2]) {
|
String formatBytes(int bytes, [int decimals = 2]) {
|
||||||
if (bytes == 0) return '0 bytes';
|
if (bytes == 0) return '0 bytes';
|
||||||
const k = 1024;
|
const k = 1024;
|
||||||
int dm = decimals < 0 ? 0 : decimals;
|
final int dm = decimals < 0 ? 0 : decimals;
|
||||||
int i = (log(bytes) / log(k)).floor();
|
final int i = (log(bytes) / log(k)).floor();
|
||||||
return ((bytes / pow(k, i)).toStringAsFixed(dm)) + ' ' + kStorageUnits[i];
|
return ((bytes / pow(k, i)).toStringAsFixed(dm)) + ' ' + kStorageUnits[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,7 +131,7 @@ String getFullDate(DateTime dateTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
String daysLeft(int futureTime) {
|
String daysLeft(int futureTime) {
|
||||||
int daysLeft = ((futureTime - DateTime.now().microsecondsSinceEpoch) /
|
final int daysLeft = ((futureTime - DateTime.now().microsecondsSinceEpoch) /
|
||||||
Duration.microsecondsPerDay)
|
Duration.microsecondsPerDay)
|
||||||
.ceil();
|
.ceil();
|
||||||
return '$daysLeft day' + (daysLeft <= 1 ? "" : "s");
|
return '$daysLeft day' + (daysLeft <= 1 ? "" : "s");
|
||||||
|
@ -143,7 +143,7 @@ String formatDuration(Duration position) {
|
||||||
int seconds = ms ~/ 1000;
|
int seconds = ms ~/ 1000;
|
||||||
final int hours = seconds ~/ 3600;
|
final int hours = seconds ~/ 3600;
|
||||||
seconds = seconds % 3600;
|
seconds = seconds % 3600;
|
||||||
var minutes = seconds ~/ 60;
|
final minutes = seconds ~/ 60;
|
||||||
seconds = seconds % 60;
|
seconds = seconds % 60;
|
||||||
|
|
||||||
final hoursString = hours >= 10
|
final hoursString = hours >= 10
|
||||||
|
@ -230,15 +230,15 @@ String secondsToHHMMSS(int value) {
|
||||||
h = value ~/ 3600;
|
h = value ~/ 3600;
|
||||||
m = ((value - h * 3600)) ~/ 60;
|
m = ((value - h * 3600)) ~/ 60;
|
||||||
s = value - (h * 3600) - (m * 60);
|
s = value - (h * 3600) - (m * 60);
|
||||||
String hourLeft = h.toString().length < 2 ? "0" + h.toString() : h.toString();
|
final String hourLeft = h.toString().length < 2 ? "0" + h.toString() : h.toString();
|
||||||
|
|
||||||
String minuteLeft =
|
final String minuteLeft =
|
||||||
m.toString().length < 2 ? "0" + m.toString() : m.toString();
|
m.toString().length < 2 ? "0" + m.toString() : m.toString();
|
||||||
|
|
||||||
String secondsLeft =
|
final String secondsLeft =
|
||||||
s.toString().length < 2 ? "0" + s.toString() : s.toString();
|
s.toString().length < 2 ? "0" + s.toString() : s.toString();
|
||||||
|
|
||||||
String result = "$hourLeft:$minuteLeft:$secondsLeft";
|
final String result = "$hourLeft:$minuteLeft:$secondsLeft";
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -418,7 +418,7 @@ Future<List<String>> _deleteLocalFilesInBatches(
|
||||||
|
|
||||||
Future<bool> _localFileExist(File file) {
|
Future<bool> _localFileExist(File file) {
|
||||||
if (file.isSharedMediaToAppSandbox()) {
|
if (file.isSharedMediaToAppSandbox()) {
|
||||||
var localFile = io.File(getSharedMediaFilePath(file));
|
final localFile = io.File(getSharedMediaFilePath(file));
|
||||||
return localFile.exists();
|
return localFile.exists();
|
||||||
} else {
|
} else {
|
||||||
return file.getAsset().then((asset) {
|
return file.getAsset().then((asset) {
|
||||||
|
@ -434,7 +434,7 @@ Future<List<String>> _tryDeleteSharedMediaFiles(List<String> localIDs) {
|
||||||
final List<String> actuallyDeletedIDs = [];
|
final List<String> actuallyDeletedIDs = [];
|
||||||
try {
|
try {
|
||||||
return Future.forEach(localIDs, (id) async {
|
return Future.forEach(localIDs, (id) async {
|
||||||
String localPath = getSharedMediaPathFromLocalID(id);
|
final String localPath = getSharedMediaPathFromLocalID(id);
|
||||||
try {
|
try {
|
||||||
// verify the file exists as the OS may have already deleted it from cache
|
// verify the file exists as the OS may have already deleted it from cache
|
||||||
if (io.File(localPath).existsSync()) {
|
if (io.File(localPath).existsSync()) {
|
||||||
|
|
|
@ -29,7 +29,7 @@ Future<dynamic> showErrorDialog(
|
||||||
String title,
|
String title,
|
||||||
String content,
|
String content,
|
||||||
) {
|
) {
|
||||||
AlertDialog alert = AlertDialog(
|
final AlertDialog alert = AlertDialog(
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||||
title: Text(
|
title: Text(
|
||||||
title,
|
title,
|
||||||
|
@ -77,7 +77,7 @@ Future<T> showConfettiDialog<T>({
|
||||||
final pageBuilder = Builder(
|
final pageBuilder = Builder(
|
||||||
builder: builder,
|
builder: builder,
|
||||||
);
|
);
|
||||||
ConfettiController confettiController =
|
final ConfettiController confettiController =
|
||||||
ConfettiController(duration: const Duration(seconds: 1));
|
ConfettiController(duration: const Duration(seconds: 1));
|
||||||
confettiController.play();
|
confettiController.play();
|
||||||
return showDialog(
|
return showDialog(
|
||||||
|
|
|
@ -76,7 +76,7 @@ class DiffFetcher {
|
||||||
fileDecryptionKey,
|
fileDecryptionKey,
|
||||||
Sodium.base642bin(file.metadataDecryptionHeader),
|
Sodium.base642bin(file.metadataDecryptionHeader),
|
||||||
);
|
);
|
||||||
Map<String, dynamic> metadata =
|
final Map<String, dynamic> metadata =
|
||||||
jsonDecode(utf8.decode(encodedMetadata));
|
jsonDecode(utf8.decode(encodedMetadata));
|
||||||
file.applyMetadata(metadata);
|
file.applyMetadata(metadata);
|
||||||
if (item['magicMetadata'] != null) {
|
if (item['magicMetadata'] != null) {
|
||||||
|
|
|
@ -126,7 +126,7 @@ Future<void> _sendLogs(
|
||||||
String subject,
|
String subject,
|
||||||
String body,
|
String body,
|
||||||
) async {
|
) async {
|
||||||
String zipFilePath = await getZippedLogsFile(context);
|
final String zipFilePath = await getZippedLogsFile(context);
|
||||||
final Email email = Email(
|
final Email email = Email(
|
||||||
recipients: [toEmail],
|
recipients: [toEmail],
|
||||||
subject: subject,
|
subject: subject,
|
||||||
|
@ -150,7 +150,7 @@ Future<String> getZippedLogsFile(BuildContext context) async {
|
||||||
final tempPath = (await getTemporaryDirectory()).path;
|
final tempPath = (await getTemporaryDirectory()).path;
|
||||||
final zipFilePath =
|
final zipFilePath =
|
||||||
tempPath + "/logs-${Configuration.instance.getUserID() ?? 0}.zip";
|
tempPath + "/logs-${Configuration.instance.getUserID() ?? 0}.zip";
|
||||||
var encoder = ZipFileEncoder();
|
final encoder = ZipFileEncoder();
|
||||||
encoder.create(zipFilePath);
|
encoder.create(zipFilePath);
|
||||||
encoder.addDirectory(logsDirectory);
|
encoder.addDirectory(logsDirectory);
|
||||||
encoder.close();
|
encoder.close();
|
||||||
|
@ -187,8 +187,8 @@ Future<void> sendEmail(
|
||||||
String body,
|
String body,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
String clientDebugInfo = await _clientInfo();
|
final String clientDebugInfo = await _clientInfo();
|
||||||
EmailContent email = EmailContent(
|
final EmailContent email = EmailContent(
|
||||||
to: [
|
to: [
|
||||||
to,
|
to,
|
||||||
],
|
],
|
||||||
|
@ -210,7 +210,7 @@ Future<void> sendEmail(
|
||||||
throw Exception('Could not launch ${params.toString()}');
|
throw Exception('Could not launch ${params.toString()}');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
OpenMailAppResult result = await OpenMailApp.composeNewEmailInMailApp(
|
final OpenMailAppResult result = await OpenMailApp.composeNewEmailInMailApp(
|
||||||
nativePickerTitle: 'Select email app',
|
nativePickerTitle: 'Select email app',
|
||||||
emailContent: email,
|
emailContent: email,
|
||||||
);
|
);
|
||||||
|
@ -257,7 +257,7 @@ Future<void> sendEmail(
|
||||||
|
|
||||||
Future<String> _clientInfo() async {
|
Future<String> _clientInfo() async {
|
||||||
final packageInfo = await PackageInfo.fromPlatform();
|
final packageInfo = await PackageInfo.fromPlatform();
|
||||||
String debugInfo = '\n\n\n\n ------------------- \nFollowing information can '
|
final String debugInfo = '\n\n\n\n ------------------- \nFollowing information can '
|
||||||
'help us in debugging if you are facing any issue '
|
'help us in debugging if you are facing any issue '
|
||||||
'\nRegistered email: ${Configuration.instance.getEmail()}'
|
'\nRegistered email: ${Configuration.instance.getEmail()}'
|
||||||
'\nClient: ${packageInfo.packageName}'
|
'\nClient: ${packageInfo.packageName}'
|
||||||
|
|
|
@ -167,7 +167,7 @@ Future<List<File>> _computeFiles(
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<AssetEntity>> _getAllAssetLists(AssetPathEntity pathEntity) async {
|
Future<List<AssetEntity>> _getAllAssetLists(AssetPathEntity pathEntity) async {
|
||||||
List<AssetEntity> result = [];
|
final List<AssetEntity> result = [];
|
||||||
int currentPage = 0;
|
int currentPage = 0;
|
||||||
List<AssetEntity> currentPageResult = [];
|
List<AssetEntity> currentPageResult = [];
|
||||||
do {
|
do {
|
||||||
|
|
|
@ -155,7 +155,7 @@ class FileUploader {
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeFromQueueWhere(final bool Function(File) fn, final Error reason) {
|
void removeFromQueueWhere(final bool Function(File) fn, final Error reason) {
|
||||||
List<String> uploadsToBeRemoved = [];
|
final List<String> uploadsToBeRemoved = [];
|
||||||
_queue.entries
|
_queue.entries
|
||||||
.where((entry) => entry.value.status == UploadStatus.notStarted)
|
.where((entry) => entry.value.status == UploadStatus.notStarted)
|
||||||
.forEach((pendingUpload) {
|
.forEach((pendingUpload) {
|
||||||
|
@ -254,7 +254,7 @@ class FileUploader {
|
||||||
bool forcedUpload,
|
bool forcedUpload,
|
||||||
) async {
|
) async {
|
||||||
final connectivityResult = await (Connectivity().checkConnectivity());
|
final connectivityResult = await (Connectivity().checkConnectivity());
|
||||||
var canUploadUnderCurrentNetworkConditions =
|
final canUploadUnderCurrentNetworkConditions =
|
||||||
(connectivityResult == ConnectivityResult.wifi ||
|
(connectivityResult == ConnectivityResult.wifi ||
|
||||||
Configuration.instance.shouldBackupOverMobileData());
|
Configuration.instance.shouldBackupOverMobileData());
|
||||||
if (!canUploadUnderCurrentNetworkConditions && !forcedUpload) {
|
if (!canUploadUnderCurrentNetworkConditions && !forcedUpload) {
|
||||||
|
@ -311,7 +311,7 @@ class FileUploader {
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint8List key;
|
Uint8List key;
|
||||||
bool isUpdatedFile =
|
final bool isUpdatedFile =
|
||||||
file.uploadedFileID != null && file.updationTime == -1;
|
file.uploadedFileID != null && file.updationTime == -1;
|
||||||
if (isUpdatedFile) {
|
if (isUpdatedFile) {
|
||||||
_logger.info("File was updated " + file.toString());
|
_logger.info("File was updated " + file.toString());
|
||||||
|
@ -342,7 +342,7 @@ class FileUploader {
|
||||||
encryptedFilePath,
|
encryptedFilePath,
|
||||||
key: key,
|
key: key,
|
||||||
);
|
);
|
||||||
var thumbnailData = mediaUploadData.thumbnail;
|
final thumbnailData = mediaUploadData.thumbnail;
|
||||||
|
|
||||||
final encryptedThumbnailData =
|
final encryptedThumbnailData =
|
||||||
await CryptoUtil.encryptChaCha(thumbnailData, fileAttributes.key);
|
await CryptoUtil.encryptChaCha(thumbnailData, fileAttributes.key);
|
||||||
|
@ -354,11 +354,11 @@ class FileUploader {
|
||||||
.writeAsBytes(encryptedThumbnailData.encryptedData);
|
.writeAsBytes(encryptedThumbnailData.encryptedData);
|
||||||
|
|
||||||
final thumbnailUploadURL = await _getUploadURL();
|
final thumbnailUploadURL = await _getUploadURL();
|
||||||
String thumbnailObjectKey =
|
final String thumbnailObjectKey =
|
||||||
await _putFile(thumbnailUploadURL, encryptedThumbnailFile);
|
await _putFile(thumbnailUploadURL, encryptedThumbnailFile);
|
||||||
|
|
||||||
final fileUploadURL = await _getUploadURL();
|
final fileUploadURL = await _getUploadURL();
|
||||||
String fileObjectKey = await _putFile(fileUploadURL, encryptedFile);
|
final String fileObjectKey = await _putFile(fileUploadURL, encryptedFile);
|
||||||
|
|
||||||
final metadata = await file.getMetadataForUpload(mediaUploadData);
|
final metadata = await file.getMetadataForUpload(mediaUploadData);
|
||||||
final encryptedMetadataData = await CryptoUtil.encryptChaCha(
|
final encryptedMetadataData = await CryptoUtil.encryptChaCha(
|
||||||
|
@ -571,7 +571,7 @@ class FileUploader {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _onInvalidFileError(File file, InvalidFileError e) async {
|
Future _onInvalidFileError(File file, InvalidFileError e) async {
|
||||||
String ext = file.title == null ? "no title" : extension(file.title);
|
final String ext = file.title == null ? "no title" : extension(file.title);
|
||||||
_logger.severe(
|
_logger.severe(
|
||||||
"Invalid file: (ext: $ext) encountered: " + file.toString(),
|
"Invalid file: (ext: $ext) encountered: " + file.toString(),
|
||||||
e,
|
e,
|
||||||
|
|
|
@ -98,7 +98,7 @@ Future<MediaUploadData> _getMediaUploadDataFromAssetFile(ente.File file) async {
|
||||||
if (file.fileType == FileType.livePhoto && io.Platform.isIOS) {
|
if (file.fileType == FileType.livePhoto && io.Platform.isIOS) {
|
||||||
final io.File videoUrl = await Motionphoto.getLivePhotoFile(file.localID);
|
final io.File videoUrl = await Motionphoto.getLivePhotoFile(file.localID);
|
||||||
if (videoUrl == null || !videoUrl.existsSync()) {
|
if (videoUrl == null || !videoUrl.existsSync()) {
|
||||||
String errMsg =
|
final String errMsg =
|
||||||
"missing livePhoto url for ${file.toString()} with subType ${file.fileSubType}";
|
"missing livePhoto url for ${file.toString()} with subType ${file.fileSubType}";
|
||||||
_logger.severe(errMsg);
|
_logger.severe(errMsg);
|
||||||
throw InvalidFileUploadState(errMsg);
|
throw InvalidFileUploadState(errMsg);
|
||||||
|
@ -111,7 +111,7 @@ Future<MediaUploadData> _getMediaUploadDataFromAssetFile(ente.File file) async {
|
||||||
// .elp -> ente live photo
|
// .elp -> ente live photo
|
||||||
final livePhotoPath = tempPath + file.generatedID.toString() + ".elp";
|
final livePhotoPath = tempPath + file.generatedID.toString() + ".elp";
|
||||||
_logger.fine("Uploading zipped live photo from " + livePhotoPath);
|
_logger.fine("Uploading zipped live photo from " + livePhotoPath);
|
||||||
var encoder = ZipFileEncoder();
|
final encoder = ZipFileEncoder();
|
||||||
encoder.create(livePhotoPath);
|
encoder.create(livePhotoPath);
|
||||||
encoder.addFile(videoUrl, "video" + extension(videoUrl.path));
|
encoder.addFile(videoUrl, "video" + extension(videoUrl.path));
|
||||||
encoder.addFile(sourceFile, "image" + extension(sourceFile.path));
|
encoder.addFile(sourceFile, "image" + extension(sourceFile.path));
|
||||||
|
@ -168,8 +168,8 @@ Future<void> _decorateEnteFileData(ente.File file, AssetEntity asset) async {
|
||||||
Future<MediaUploadData> _getMediaUploadDataFromAppCache(ente.File file) async {
|
Future<MediaUploadData> _getMediaUploadDataFromAppCache(ente.File file) async {
|
||||||
io.File sourceFile;
|
io.File sourceFile;
|
||||||
Uint8List thumbnailData;
|
Uint8List thumbnailData;
|
||||||
bool isDeleted = false;
|
const bool isDeleted = false;
|
||||||
var localPath = getSharedMediaFilePath(file);
|
final localPath = getSharedMediaFilePath(file);
|
||||||
sourceFile = io.File(localPath);
|
sourceFile = io.File(localPath);
|
||||||
if (!sourceFile.existsSync()) {
|
if (!sourceFile.existsSync()) {
|
||||||
_logger.warning("File doesn't exist in app sandbox");
|
_logger.warning("File doesn't exist in app sandbox");
|
||||||
|
|
|
@ -40,7 +40,7 @@ Future<io.File> getFile(
|
||||||
if (file.isRemoteFile()) {
|
if (file.isRemoteFile()) {
|
||||||
return getFileFromServer(file, liveVideo: liveVideo);
|
return getFileFromServer(file, liveVideo: liveVideo);
|
||||||
} else {
|
} else {
|
||||||
String key = file.tag() + liveVideo.toString() + isOrigin.toString();
|
final String key = file.tag() + liveVideo.toString() + isOrigin.toString();
|
||||||
final cachedFile = FileLruCache.get(key);
|
final cachedFile = FileLruCache.get(key);
|
||||||
if (cachedFile == null) {
|
if (cachedFile == null) {
|
||||||
final diskFile = await _getLocalDiskFile(
|
final diskFile = await _getLocalDiskFile(
|
||||||
|
@ -69,7 +69,7 @@ Future<io.File> _getLocalDiskFile(
|
||||||
bool isOrigin = false,
|
bool isOrigin = false,
|
||||||
}) async {
|
}) async {
|
||||||
if (file.isSharedMediaToAppSandbox()) {
|
if (file.isSharedMediaToAppSandbox()) {
|
||||||
var localFile = io.File(getSharedMediaFilePath(file));
|
final localFile = io.File(getSharedMediaFilePath(file));
|
||||||
return localFile.exists().then((exist) {
|
return localFile.exists().then((exist) {
|
||||||
return exist ? localFile : null;
|
return exist ? localFile : null;
|
||||||
});
|
});
|
||||||
|
@ -194,17 +194,17 @@ Future<_LivePhoto> _downloadLivePhoto(
|
||||||
}
|
}
|
||||||
_logger.fine("Decoded zipped live photo from " + decryptedFile.path);
|
_logger.fine("Decoded zipped live photo from " + decryptedFile.path);
|
||||||
io.File imageFileCache, videoFileCache;
|
io.File imageFileCache, videoFileCache;
|
||||||
List<int> bytes = await decryptedFile.readAsBytes();
|
final List<int> bytes = await decryptedFile.readAsBytes();
|
||||||
Archive archive = ZipDecoder().decodeBytes(bytes);
|
final Archive archive = ZipDecoder().decodeBytes(bytes);
|
||||||
final tempPath = Configuration.instance.getTempDirectory();
|
final tempPath = Configuration.instance.getTempDirectory();
|
||||||
// Extract the contents of Zip compressed archive to disk
|
// Extract the contents of Zip compressed archive to disk
|
||||||
for (ArchiveFile archiveFile in archive) {
|
for (ArchiveFile archiveFile in archive) {
|
||||||
if (archiveFile.isFile) {
|
if (archiveFile.isFile) {
|
||||||
String filename = archiveFile.name;
|
final String filename = archiveFile.name;
|
||||||
String fileExtension = getExtension(archiveFile.name);
|
final String fileExtension = getExtension(archiveFile.name);
|
||||||
String decodePath =
|
final String decodePath =
|
||||||
tempPath + file.uploadedFileID.toString() + filename;
|
tempPath + file.uploadedFileID.toString() + filename;
|
||||||
List<int> data = archiveFile.content;
|
final List<int> data = archiveFile.content;
|
||||||
if (filename.startsWith("image")) {
|
if (filename.startsWith("image")) {
|
||||||
final imageFile = io.File(decodePath);
|
final imageFile = io.File(decodePath);
|
||||||
await imageFile.create(recursive: true);
|
await imageFile.create(recursive: true);
|
||||||
|
@ -259,8 +259,8 @@ Future<io.File> _downloadAndCache(
|
||||||
if (decryptedFile == null) {
|
if (decryptedFile == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var decryptedFilePath = decryptedFile.path;
|
final decryptedFilePath = decryptedFile.path;
|
||||||
String fileExtension = getExtension(file.title);
|
final String fileExtension = getExtension(file.title);
|
||||||
var outputFile = decryptedFile;
|
var outputFile = decryptedFile;
|
||||||
if ((fileExtension == "unknown" && file.fileType == FileType.image) ||
|
if ((fileExtension == "unknown" && file.fileType == FileType.image) ||
|
||||||
(io.Platform.isAndroid && fileExtension == "heic")) {
|
(io.Platform.isAndroid && fileExtension == "heic")) {
|
||||||
|
|
|
@ -27,7 +27,7 @@ class HexEncoder extends Converter<List<int>, String> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String convert(List<int> bytes) {
|
String convert(List<int> bytes) {
|
||||||
StringBuffer buffer = StringBuffer();
|
final StringBuffer buffer = StringBuffer();
|
||||||
for (int part in bytes) {
|
for (int part in bytes) {
|
||||||
if (part & 0xff != part) {
|
if (part & 0xff != part) {
|
||||||
throw const FormatException("Non-byte integer detected");
|
throw const FormatException("Non-byte integer detected");
|
||||||
|
@ -53,10 +53,10 @@ class HexDecoder extends Converter<String, List<int>> {
|
||||||
if (str.length % 2 != 0) {
|
if (str.length % 2 != 0) {
|
||||||
str = "0" + str;
|
str = "0" + str;
|
||||||
}
|
}
|
||||||
Uint8List result = Uint8List(str.length ~/ 2);
|
final Uint8List result = Uint8List(str.length ~/ 2);
|
||||||
for (int i = 0; i < result.length; i++) {
|
for (int i = 0; i < result.length; i++) {
|
||||||
int firstDigit = _alphabet.indexOf(str[i * 2]);
|
final int firstDigit = _alphabet.indexOf(str[i * 2]);
|
||||||
int secondDigit = _alphabet.indexOf(str[i * 2 + 1]);
|
final int secondDigit = _alphabet.indexOf(str[i * 2 + 1]);
|
||||||
if (firstDigit == -1 || secondDigit == -1) {
|
if (firstDigit == -1 || secondDigit == -1) {
|
||||||
throw FormatException("Non-hex character detected in $hex");
|
throw FormatException("Non-hex character detected in $hex");
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ Future<void> changeCollectionVisibility(
|
||||||
);
|
);
|
||||||
await dialog.show();
|
await dialog.show();
|
||||||
try {
|
try {
|
||||||
Map<String, dynamic> update = {kMagicKeyVisibility: newVisibility};
|
final Map<String, dynamic> update = {kMagicKeyVisibility: newVisibility};
|
||||||
await CollectionsService.instance.updateMagicMetadata(collection, update);
|
await CollectionsService.instance.updateMagicMetadata(collection, update);
|
||||||
// Force reload home gallery to pull in the now unarchived files
|
// Force reload home gallery to pull in the now unarchived files
|
||||||
Bus.instance.fire(ForceReloadHomeGalleryEvent());
|
Bus.instance.fire(ForceReloadHomeGalleryEvent());
|
||||||
|
@ -135,7 +135,7 @@ Future<void> _updatePublicMetadata(
|
||||||
final dialog = createProgressDialog(context, 'please wait...');
|
final dialog = createProgressDialog(context, 'please wait...');
|
||||||
await dialog.show();
|
await dialog.show();
|
||||||
try {
|
try {
|
||||||
Map<String, dynamic> update = {key: value};
|
final Map<String, dynamic> update = {key: value};
|
||||||
await FileMagicService.instance.updatePublicMagicMetadata(files, update);
|
await FileMagicService.instance.updatePublicMagicMetadata(files, update);
|
||||||
showShortToast(context, 'done');
|
showShortToast(context, 'done');
|
||||||
await dialog.hide();
|
await dialog.hide();
|
||||||
|
|
|
@ -44,12 +44,12 @@ Future<void> share(
|
||||||
|
|
||||||
Rect shareButtonRect(BuildContext context, GlobalKey shareButtonKey) {
|
Rect shareButtonRect(BuildContext context, GlobalKey shareButtonKey) {
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
RenderBox renderBox = shareButtonKey?.currentContext?.findRenderObject();
|
final RenderBox renderBox = shareButtonKey?.currentContext?.findRenderObject();
|
||||||
if (renderBox == null) {
|
if (renderBox == null) {
|
||||||
return Rect.fromLTWH(0, 0, size.width, size.height / 2);
|
return Rect.fromLTWH(0, 0, size.width, size.height / 2);
|
||||||
}
|
}
|
||||||
size = renderBox.size;
|
size = renderBox.size;
|
||||||
Offset position = renderBox.localToGlobal(Offset.zero);
|
final Offset position = renderBox.localToGlobal(Offset.zero);
|
||||||
return Rect.fromCenter(
|
return Rect.fromCenter(
|
||||||
center: position + Offset(size.width / 2, size.height / 2),
|
center: position + Offset(size.width / 2, size.height / 2),
|
||||||
width: size.width,
|
width: size.width,
|
||||||
|
@ -65,7 +65,7 @@ Future<List<File>> convertIncomingSharedMediaToFile(
|
||||||
List<SharedMediaFile> sharedMedia,
|
List<SharedMediaFile> sharedMedia,
|
||||||
int collectionID,
|
int collectionID,
|
||||||
) async {
|
) async {
|
||||||
List<File> localFiles = [];
|
final List<File> localFiles = [];
|
||||||
for (var media in sharedMedia) {
|
for (var media in sharedMedia) {
|
||||||
if (!(media.type == SharedMediaType.IMAGE ||
|
if (!(media.type == SharedMediaType.IMAGE ||
|
||||||
media.type == SharedMediaType.VIDEO)) {
|
media.type == SharedMediaType.VIDEO)) {
|
||||||
|
@ -74,7 +74,7 @@ Future<List<File>> convertIncomingSharedMediaToFile(
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var enteFile = File();
|
final enteFile = File();
|
||||||
// fileName: img_x.jpg
|
// fileName: img_x.jpg
|
||||||
enteFile.title = basename(media.path);
|
enteFile.title = basename(media.path);
|
||||||
var ioFile = dartio.File(media.path);
|
var ioFile = dartio.File(media.path);
|
||||||
|
|
|
@ -62,7 +62,7 @@ class TrashDiffFetcher {
|
||||||
fileDecryptionKey,
|
fileDecryptionKey,
|
||||||
Sodium.base642bin(trash.metadataDecryptionHeader),
|
Sodium.base642bin(trash.metadataDecryptionHeader),
|
||||||
);
|
);
|
||||||
Map<String, dynamic> metadata =
|
final Map<String, dynamic> metadata =
|
||||||
jsonDecode(utf8.decode(encodedMetadata));
|
jsonDecode(utf8.decode(encodedMetadata));
|
||||||
trash.applyMetadata(metadata);
|
trash.applyMetadata(metadata);
|
||||||
if (item["file"]['magicMetadata'] != null) {
|
if (item["file"]['magicMetadata'] != null) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ void validatePreVerificationStateCheck(
|
||||||
}
|
}
|
||||||
// check password encoding issues
|
// check password encoding issues
|
||||||
try {
|
try {
|
||||||
Uint8List passwordL = utf8.encode(password);
|
final Uint8List passwordL = utf8.encode(password);
|
||||||
try {
|
try {
|
||||||
utf8.decode(passwordL);
|
utf8.decode(passwordL);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue