resolved merge conflicts

This commit is contained in:
Ashil Kandapath 2022-08-30 10:33:56 +05:30
commit e8e89b1bf2
88 changed files with 360 additions and 254 deletions

View file

@ -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

View file

@ -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);
} }

View file

@ -29,6 +29,7 @@ import 'package:photos/services/memories_service.dart';
import 'package:photos/services/search_service.dart'; import 'package:photos/services/search_service.dart';
import 'package:photos/services/sync_service.dart'; import 'package:photos/services/sync_service.dart';
import 'package:photos/utils/crypto_util.dart'; import 'package:photos/utils/crypto_util.dart';
import 'package:photos/utils/validator_util.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
import 'package:wakelock/wakelock.dart'; import 'package:wakelock/wakelock.dart';
@ -111,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";
@ -242,12 +243,21 @@ class Configuration {
String password, String password,
KeyAttributes attributes, KeyAttributes attributes,
) async { ) async {
_logger.info('Start decryptAndSaveSecrets');
validatePreVerificationStateCheck(
attributes,
password,
getEncryptedToken(),
);
_logger.info('state validation done');
final kek = await CryptoUtil.deriveKey( final kek = await CryptoUtil.deriveKey(
utf8.encode(password), utf8.encode(password),
Sodium.base642bin(attributes.kekSalt), Sodium.base642bin(attributes.kekSalt),
attributes.memLimit, attributes.memLimit,
attributes.opsLimit, attributes.opsLimit,
); );
_logger.info('user-key done');
Uint8List key; Uint8List key;
try { try {
key = CryptoUtil.decryptSync( key = CryptoUtil.decryptSync(
@ -256,20 +266,24 @@ class Configuration {
Sodium.base642bin(attributes.keyDecryptionNonce), Sodium.base642bin(attributes.keyDecryptionNonce),
); );
} catch (e) { } catch (e) {
_logger.severe('master-key failed, incorrect password?', e);
throw Exception("Incorrect password"); throw Exception("Incorrect password");
} }
_logger.info("master-key done");
await setKey(Sodium.bin2base64(key)); await setKey(Sodium.bin2base64(key));
final secretKey = CryptoUtil.decryptSync( final secretKey = CryptoUtil.decryptSync(
Sodium.base642bin(attributes.encryptedSecretKey), Sodium.base642bin(attributes.encryptedSecretKey),
key, key,
Sodium.base642bin(attributes.secretKeyDecryptionNonce), Sodium.base642bin(attributes.secretKeyDecryptionNonce),
); );
_logger.info("secret-key done");
await setSecretKey(Sodium.bin2base64(secretKey)); await setSecretKey(Sodium.bin2base64(secretKey));
final token = CryptoUtil.openSealSync( final token = CryptoUtil.openSealSync(
Sodium.base642bin(getEncryptedToken()), Sodium.base642bin(getEncryptedToken()),
Sodium.base642bin(attributes.publicKey), Sodium.base642bin(attributes.publicKey),
secretKey, secretKey,
); );
_logger.info('appToken done');
await setToken( await setToken(
Sodium.bin2base64(token, variant: Sodium.base64VariantUrlsafe), Sodium.bin2base64(token, variant: Sodium.base64VariantUrlsafe),
); );

View file

@ -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");
} }
} }

View file

@ -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],

View file

@ -40,8 +40,8 @@ class FilesMigrationDB {
// 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,

View file

@ -95,8 +95,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);
} }
@ -425,7 +425,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);
} }
@ -451,7 +451,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);
} }
@ -483,7 +483,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);
} }
@ -674,7 +674,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(
@ -937,7 +937,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',
), ),
@ -947,7 +947,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',
), ),
@ -1152,9 +1152,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;
} }

View file

@ -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,

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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,

View file

@ -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");

View file

@ -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,

View file

@ -61,7 +61,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;

View file

@ -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,
); );

View file

@ -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;

View file

@ -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(

View file

@ -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);

View file

@ -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 {

View file

@ -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;
} }

View file

@ -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;

View file

@ -63,14 +63,14 @@ class FileMigrationService {
} }
// migration only needs to run if Android API Level is 29 or higher // migration only needs to run if Android API Level is 29 or higher
final int version = int.parse(await PhotoManager.systemVersion()); final int version = int.parse(await PhotoManager.systemVersion());
bool isMigrationRequired = version >= 29; final bool isMigrationRequired = version >= 29;
if (isMigrationRequired) { if (isMigrationRequired) {
await _importLocalFilesForMigration(); await _importLocalFilesForMigration();
final sTime = DateTime.now().microsecondsSinceEpoch; final sTime = DateTime.now().microsecondsSinceEpoch;
bool hasData = true; bool hasData = true;
const int limitInBatch = 100; const int limitInBatch = 100;
while (hasData) { while (hasData) {
var localIDsToProcess = await _filesMigrationDB final localIDsToProcess = await _filesMigrationDB
.getLocalIDsForPotentialReUpload(limitInBatch); .getLocalIDsForPotentialReUpload(limitInBatch);
if (localIDsToProcess.isEmpty) { if (localIDsToProcess.isEmpty) {
hasData = false; hasData = false;
@ -91,15 +91,15 @@ class FileMigrationService {
List<String> localIDsToProcess, List<String> localIDsToProcess,
) async { ) async {
_logger.info("files to process ${localIDsToProcess.length}"); _logger.info("files to process ${localIDsToProcess.length}");
var localIDsWithLocation = <String>[]; final localIDsWithLocation = <String>[];
for (var localID in localIDsToProcess) { for (var localID in localIDsToProcess) {
bool hasLocation = false; bool hasLocation = false;
try { try {
var assetEntity = await AssetEntity.fromId(localID); final assetEntity = await AssetEntity.fromId(localID);
if (assetEntity == null) { if (assetEntity == null) {
continue; continue;
} }
var latLng = await assetEntity.latlngAsync(); final latLng = await assetEntity.latlngAsync();
if ((latLng.longitude ?? 0.0) != 0.0 || if ((latLng.longitude ?? 0.0) != 0.0 ||
(latLng.longitude ?? 0.0) != 0.0) { (latLng.longitude ?? 0.0) != 0.0) {
_logger.finest( _logger.finest(
@ -125,7 +125,7 @@ class FileMigrationService {
} }
final sTime = DateTime.now().microsecondsSinceEpoch; final sTime = DateTime.now().microsecondsSinceEpoch;
_logger.info('importing files without location info'); _logger.info('importing files without location info');
var fileLocalIDs = await _filesDB.getLocalFilesBackedUpWithoutLocation(); final fileLocalIDs = await _filesDB.getLocalFilesBackedUpWithoutLocation();
await _filesMigrationDB.insertMultiple(fileLocalIDs); await _filesMigrationDB.insertMultiple(fileLocalIDs);
final eTime = DateTime.now().microsecondsSinceEpoch; final eTime = DateTime.now().microsecondsSinceEpoch;
final d = Duration(microseconds: eTime - sTime); final d = Duration(microseconds: eTime - sTime);

View file

@ -162,7 +162,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;
} }
} }
@ -177,7 +177,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;
} }
} }
@ -192,7 +192,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;
} }
} }
@ -273,9 +273,9 @@ class LocalSyncService {
); );
try { try {
if (Platform.isIOS) { if (Platform.isIOS) {
var assetEntity = await AssetEntity.fromId(file.localID); final assetEntity = await AssetEntity.fromId(file.localID);
if (assetEntity != null) { if (assetEntity != null) {
var isLocallyAvailable = final isLocallyAvailable =
await assetEntity.isLocallyAvailable(isOrigin: true); await assetEntity.isLocallyAvailable(isOrigin: true);
_logger.info( _logger.info(
're-upload asset ${file.toString()} with localAvailableFlag ' 're-upload asset ${file.toString()} with localAvailableFlag '

View file

@ -265,7 +265,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) {
@ -374,8 +374,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
@ -420,7 +420,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;

View file

@ -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: {

View file

@ -181,7 +181,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(

View file

@ -3,10 +3,13 @@ import 'package:logging/logging.dart';
import 'package:photos/core/configuration.dart'; import 'package:photos/core/configuration.dart';
import 'package:photos/core/event_bus.dart'; import 'package:photos/core/event_bus.dart';
import 'package:photos/events/subscription_purchased_event.dart'; import 'package:photos/events/subscription_purchased_event.dart';
import 'package:photos/models/key_attributes.dart';
import 'package:photos/ui/account/recovery_page.dart'; import 'package:photos/ui/account/recovery_page.dart';
import 'package:photos/ui/common/dialogs.dart';
import 'package:photos/ui/common/dynamic_fab.dart'; import 'package:photos/ui/common/dynamic_fab.dart';
import 'package:photos/ui/home_widget.dart'; import 'package:photos/ui/home_widget.dart';
import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/dialog_util.dart';
import 'package:photos/utils/email_util.dart';
class PasswordReentryPage extends StatefulWidget { class PasswordReentryPage extends StatefulWidget {
const PasswordReentryPage({Key key}) : super(key: key); const PasswordReentryPage({Key key}) : super(key: key);
@ -16,6 +19,7 @@ class PasswordReentryPage extends StatefulWidget {
} }
class _PasswordReentryPageState extends State<PasswordReentryPage> { class _PasswordReentryPageState extends State<PasswordReentryPage> {
final _logger = Logger((_PasswordReentryPageState).toString());
final _passwordController = TextEditingController(); final _passwordController = TextEditingController();
final FocusNode _passwordFocusNode = FocusNode(); final FocusNode _passwordFocusNode = FocusNode();
String email; String email;
@ -72,9 +76,26 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
Configuration.instance.getKeyAttributes(), Configuration.instance.getKeyAttributes(),
); );
} catch (e, s) { } catch (e, s) {
Logger("PRP").severe("Password verification failed", e, s); _logger.severe("Password verification failed", e, s);
await dialog.hide(); await dialog.hide();
showErrorDialog(context, "Incorrect password", "Please try again");
final dialogUserChoice = await showChoiceDialog(
context,
"Incorrect password",
"Please try again",
firstAction: "Contact Support",
firstActionColor: Theme.of(context).colorScheme.primary,
secondAction: "Ok",
secondActionColor: Theme.of(context).colorScheme.primary,
);
if (dialogUserChoice == DialogUserChoice.firstChoice) {
await sendLogs(
context,
"Contact support",
"support@ente.io",
postShare: () {},
);
}
return; return;
} }
await dialog.hide(); await dialog.hide();
@ -231,4 +252,10 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
], ],
); );
} }
void validatePreVerificationState(KeyAttributes keyAttributes) {
if (keyAttributes == null) {
throw Exception("Key Attributes can not be null");
}
}
} }

View file

@ -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(

View file

@ -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: [

View file

@ -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));

View file

@ -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);

View file

@ -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));

View file

@ -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(

View file

@ -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,

View file

@ -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",

View file

@ -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,

View file

@ -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);
} }
}); });

View file

@ -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);
} }

View file

@ -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(

View file

@ -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;
} }

View file

@ -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,

View file

@ -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);

View file

@ -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?",

View file

@ -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";

View file

@ -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,

View file

@ -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: [

View file

@ -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) {

View file

@ -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 " +

View file

@ -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(

View file

@ -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(

View file

@ -83,6 +83,7 @@ class _SecuritySectionWidgetState extends State<SecuritySectionWidget> {
return Switch.adaptive( return Switch.adaptive(
value: snapshot.data, value: snapshot.data,
onChanged: (value) async { onChanged: (value) async {
<<<<<<< HEAD
if (await LocalAuthentication().isDeviceSupported()) { if (await LocalAuthentication().isDeviceSupported()) {
AppLock.of(context).setEnabled(false); AppLock.of(context).setEnabled(false);
String reason = String reason =
@ -95,6 +96,18 @@ class _SecuritySectionWidgetState extends State<SecuritySectionWidget> {
showToast(context, reason); showToast(context, reason);
return; return;
} }
=======
AppLock.of(context).setEnabled(false);
const String reason =
"Please authenticate to configure two-factor authentication";
final result = await requestAuthentication(reason);
AppLock.of(context).setEnabled(
Configuration.instance.shouldShowLockScreen(),
);
if (!result) {
showToast(context, reason);
return;
>>>>>>> master
} }
if (value) { if (value) {
UserService.instance.setupTwoFactor(context); UserService.instance.setupTwoFactor(context);
@ -167,7 +180,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(
@ -281,7 +294,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?",

View file

@ -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: () {

View file

@ -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);

View file

@ -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),

View file

@ -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",

View file

@ -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 >

View file

@ -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)),

View file

@ -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(

View file

@ -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;

View file

@ -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,

View file

@ -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 {

View file

@ -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(

View file

@ -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,

View file

@ -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,

View file

@ -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) {

View file

@ -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)

View file

@ -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);

View file

@ -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;

View file

@ -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,

View file

@ -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",

View file

@ -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}) {

View file

@ -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];
} }

View file

@ -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;
} }

View file

@ -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()) {

View file

@ -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(

View file

@ -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) {

View file

@ -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}'

View file

@ -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 {

View file

@ -209,7 +209,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) {
@ -308,7 +308,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) {
@ -363,7 +363,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());
@ -381,7 +381,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);
@ -393,11 +393,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 = final metadata =
await file.getMetadataForUpload(mediaUploadData.sourceFile); await file.getMetadataForUpload(mediaUploadData.sourceFile);
@ -496,7 +496,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,

View file

@ -76,7 +76,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);
@ -85,7 +85,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));
@ -136,8 +136,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");

View file

@ -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")) {

View file

@ -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");
} }

View file

@ -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();

View file

@ -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);

View file

@ -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) {

View file

@ -0,0 +1,50 @@
import 'dart:convert';
import 'dart:typed_data';
import 'package:logging/logging.dart';
import 'package:photos/models/key_attributes.dart';
Logger _logger = Logger("Validator");
void validatePreVerificationStateCheck(
KeyAttributes keyAttr,
String password,
String encryptedToken,
) {
nullOrEmptyArgCheck(encryptedToken, "encryptedToken");
nullOrEmptyArgCheck(password, "userPassword");
if (keyAttr == null) {
throw ArgumentError("key Attributes can not be null");
}
nullOrEmptyArgCheck(keyAttr.kekSalt, "keySalt");
nullOrEmptyArgCheck(keyAttr.encryptedKey, "encryptedKey");
nullOrEmptyArgCheck(keyAttr.keyDecryptionNonce, "keyDecryptionNonce");
nullOrEmptyArgCheck(keyAttr.encryptedSecretKey, "encryptedSecretKey");
nullOrEmptyArgCheck(
keyAttr.secretKeyDecryptionNonce,
"secretKeyDecryptionNonce",
);
nullOrEmptyArgCheck(keyAttr.publicKey, "publicKey");
if ((keyAttr.memLimit ?? 0) <= 0 || (keyAttr.opsLimit ?? 0) <= 0) {
throw ArgumentError("Key mem/OpsLimit can not be null or <0");
}
// check password encoding issues
try {
final Uint8List passwordL = utf8.encode(password);
try {
utf8.decode(passwordL);
} catch (e) {
_logger.severe("CRITICAL: password decode failed", e);
rethrow;
}
} catch (e) {
_logger.severe('CRITICAL: password encode failed');
rethrow;
}
}
void nullOrEmptyArgCheck(String value, String name) {
if (value == null || value.isEmpty) {
throw ArgumentError("Critical: $name is nullOrEmpty");
}
}

View file

@ -11,7 +11,7 @@ description: ente photos application
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 0.6.26+356 version: 0.6.29+359
environment: environment:
sdk: ">=2.10.0 <3.0.0" sdk: ">=2.10.0 <3.0.0"