Merge pull request #502 from ente-io/migrate-to-null-safety

This commit is contained in:
Neeraj Gupta 2022-09-21 12:56:17 +05:30 committed by GitHub
commit 6f7539eadb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 146 additions and 334 deletions

View file

@ -1,5 +1,3 @@
// @dart=2.9
class InvalidFileError extends ArgumentError { class InvalidFileError extends ArgumentError {
InvalidFileError(String message) : super(message); InvalidFileError(String message) : super(message);
} }

View file

@ -262,7 +262,7 @@ class FilesDB {
ALTER TABLE $filesTable ADD COLUMN $columnMMdVersion INTEGER DEFAULT 0; ALTER TABLE $filesTable ADD COLUMN $columnMMdVersion INTEGER DEFAULT 0;
''', ''',
''' '''
ALTER TABLE $filesTable ADD COLUMN $columnMMdVisibility INTEGER DEFAULT $kVisibilityVisible; ALTER TABLE $filesTable ADD COLUMN $columnMMdVisibility INTEGER DEFAULT $visibilityVisible;
''' '''
]; ];
} }
@ -461,7 +461,7 @@ class FilesDB {
int ownerID, { int ownerID, {
int limit, int limit,
bool asc, bool asc,
int visibility = kVisibilityVisible, int visibility = visibilityVisible,
Set<int> ignoredCollectionIDs, Set<int> ignoredCollectionIDs,
}) async { }) async {
final db = await instance.database; final db = await instance.database;
@ -484,7 +484,7 @@ class FilesDB {
Future<Set<int>> getCollectionIDsOfHiddenFiles( Future<Set<int>> getCollectionIDsOfHiddenFiles(
int ownerID, { int ownerID, {
int visibility = kVisibilityArchive, int visibility = visibilityArchive,
}) async { }) async {
final db = await instance.database; final db = await instance.database;
final results = await db.query( final results = await db.query(
@ -517,7 +517,7 @@ class FilesDB {
where: where:
'$columnCreationTime >= ? AND $columnCreationTime <= ? AND ($columnOwnerID IS NULL OR $columnOwnerID = ?) AND ($columnMMdVisibility IS NULL OR $columnMMdVisibility = ?)' '$columnCreationTime >= ? AND $columnCreationTime <= ? AND ($columnOwnerID IS NULL OR $columnOwnerID = ?) AND ($columnMMdVisibility IS NULL OR $columnMMdVisibility = ?)'
' AND ($columnLocalID IS NOT NULL OR ($columnCollectionID IS NOT NULL AND $columnCollectionID IS NOT -1))', ' AND ($columnLocalID IS NOT NULL OR ($columnCollectionID IS NOT NULL AND $columnCollectionID IS NOT -1))',
whereArgs: [startTime, endTime, ownerID, kVisibilityVisible], whereArgs: [startTime, endTime, ownerID, visibilityVisible],
orderBy: orderBy:
'$columnCreationTime ' + order + ', $columnModificationTime ' + order, '$columnCreationTime ' + order + ', $columnModificationTime ' + order,
limit: limit, limit: limit,
@ -569,7 +569,7 @@ class FilesDB {
int endTime, { int endTime, {
int limit, int limit,
bool asc, bool asc,
int visibility = kVisibilityVisible, int visibility = visibilityVisible,
}) async { }) async {
final db = await instance.database; final db = await instance.database;
final order = (asc ?? false ? 'ASC' : 'DESC'); final order = (asc ?? false ? 'ASC' : 'DESC');
@ -618,7 +618,7 @@ class FilesDB {
whereClause += " OR "; whereClause += " OR ";
} }
} }
whereClause += ") AND $columnMMdVisibility = $kVisibilityVisible"; whereClause += ") AND $columnMMdVisibility = $visibilityVisible";
final results = await db.query( final results = await db.query(
filesTable, filesTable,
where: whereClause, where: whereClause,
@ -1168,7 +1168,7 @@ class FilesDB {
SELECT $columnCollectionID, MAX($columnCreationTime) AS max_creation_time SELECT $columnCollectionID, MAX($columnCreationTime) AS max_creation_time
FROM $filesTable FROM $filesTable
WHERE ($columnCollectionID IS NOT NULL AND $columnCollectionID IS WHERE ($columnCollectionID IS NOT NULL AND $columnCollectionID IS
NOT -1 AND $columnMMdVisibility = $kVisibilityVisible AND NOT -1 AND $columnMMdVisibility = $visibilityVisible AND
$columnUploadedFileID IS NOT -1) $columnUploadedFileID IS NOT -1)
GROUP BY $columnCollectionID GROUP BY $columnCollectionID
) latest_files ) latest_files
@ -1366,7 +1366,7 @@ class FilesDB {
row[columnMMdVersion] = file.mMdVersion ?? 0; row[columnMMdVersion] = file.mMdVersion ?? 0;
row[columnMMdEncodedJson] = file.mMdEncodedJson ?? '{}'; row[columnMMdEncodedJson] = file.mMdEncodedJson ?? '{}';
row[columnMMdVisibility] = row[columnMMdVisibility] =
file.magicMetadata?.visibility ?? kVisibilityVisible; file.magicMetadata?.visibility ?? visibilityVisible;
row[columnPubMMdVersion] = file.pubMmdVersion ?? 0; row[columnPubMMdVersion] = file.pubMmdVersion ?? 0;
row[columnPubMMdEncodedJson] = file.pubMmdEncodedJson ?? '{}'; row[columnPubMMdEncodedJson] = file.pubMmdEncodedJson ?? '{}';
if (file.pubMagicMetadata != null && if (file.pubMagicMetadata != null &&
@ -1405,7 +1405,7 @@ class FilesDB {
row[columnMMdVersion] = file.mMdVersion ?? 0; row[columnMMdVersion] = file.mMdVersion ?? 0;
row[columnMMdEncodedJson] = file.mMdEncodedJson ?? '{}'; row[columnMMdEncodedJson] = file.mMdEncodedJson ?? '{}';
row[columnMMdVisibility] = row[columnMMdVisibility] =
file.magicMetadata?.visibility ?? kVisibilityVisible; file.magicMetadata?.visibility ?? visibilityVisible;
row[columnPubMMdVersion] = file.pubMmdVersion ?? 0; row[columnPubMMdVersion] = file.pubMmdVersion ?? 0;
row[columnPubMMdEncodedJson] = file.pubMmdEncodedJson ?? '{}'; row[columnPubMMdEncodedJson] = file.pubMmdEncodedJson ?? '{}';

View file

@ -18,7 +18,7 @@ class BillingPlans {
factory BillingPlans.fromMap(Map<String, dynamic>? map) { factory BillingPlans.fromMap(Map<String, dynamic>? map) {
if (map == null) { if (map == null) {
throw ArgumentError('argument is null'); throw Exception('Argument is null');
} }
return BillingPlans( return BillingPlans(
@ -53,7 +53,7 @@ class FreePlan {
factory FreePlan.fromMap(Map<String, dynamic>? map) { factory FreePlan.fromMap(Map<String, dynamic>? map) {
if (map == null) { if (map == null) {
throw ArgumentError('argument is null'); throw Exception('Argument is null');
} }
return FreePlan( return FreePlan(
@ -97,7 +97,7 @@ class BillingPlan {
factory BillingPlan.fromMap(Map<String, dynamic>? map) { factory BillingPlan.fromMap(Map<String, dynamic>? map) {
if (map == null) { if (map == null) {
throw ArgumentError('argument is null'); throw Exception('Argument is null');
} }
return BillingPlan( return BillingPlan(

View file

@ -1,28 +1,25 @@
// @dart=2.9
import 'dart:convert'; import 'dart:convert';
import 'dart:core'; import 'dart:core';
import 'package:flutter/foundation.dart';
import 'package:photos/models/magic_metadata.dart'; import 'package:photos/models/magic_metadata.dart';
class Collection { class Collection {
final int id; final int id;
final User owner; final User? owner;
final String encryptedKey; final String encryptedKey;
final String keyDecryptionNonce; final String? keyDecryptionNonce;
final String name; final String? name;
final String encryptedName; final String encryptedName;
final String nameDecryptionNonce; final String nameDecryptionNonce;
final CollectionType type; final CollectionType type;
final CollectionAttributes attributes; final CollectionAttributes? attributes;
final List<User> sharees; final List<User?>? sharees;
final List<PublicURL> publicURLs; final List<PublicURL?>? publicURLs;
final int updationTime; final int updationTime;
final bool isDeleted; final bool isDeleted;
String mMdEncodedJson; String? mMdEncodedJson;
int mMdVersion = 0; int mMdVersion = 0;
CollectionMagicMetadata _mmd; CollectionMagicMetadata? _mmd;
CollectionMagicMetadata get magicMetadata => CollectionMagicMetadata get magicMetadata =>
_mmd ?? CollectionMagicMetadata.fromEncodedJson(mMdEncodedJson ?? '{}'); _mmd ?? CollectionMagicMetadata.fromEncodedJson(mMdEncodedJson ?? '{}');
@ -46,7 +43,7 @@ class Collection {
}); });
bool isArchived() { bool isArchived() {
return mMdVersion > 0 && magicMetadata.visibility == kVisibilityArchive; return mMdVersion > 0 && magicMetadata.visibility == visibilityArchive;
} }
static CollectionType typeFromString(String type) { static CollectionType typeFromString(String type) {
@ -71,21 +68,21 @@ class Collection {
} }
Collection copyWith({ Collection copyWith({
int id, int? id,
User owner, User? owner,
String encryptedKey, String? encryptedKey,
String keyDecryptionNonce, String? keyDecryptionNonce,
String name, String? name,
String encryptedName, String? encryptedName,
String nameDecryptionNonce, String? nameDecryptionNonce,
CollectionType type, CollectionType? type,
CollectionAttributes attributes, CollectionAttributes? attributes,
List<User> sharees, List<User>? sharees,
List<PublicURL> publicURLs, List<PublicURL>? publicURLs,
int updationTime, int? updationTime,
bool isDeleted, bool? isDeleted,
String mMdEncodedJson, String? mMdEncodedJson,
int mMdVersion, int? mMdVersion,
}) { }) {
final Collection result = Collection( final Collection result = Collection(
id ?? this.id, id ?? this.id,
@ -118,15 +115,17 @@ class Collection {
'nameDecryptionNonce': nameDecryptionNonce, 'nameDecryptionNonce': nameDecryptionNonce,
'type': typeToString(type), 'type': typeToString(type),
'attributes': attributes?.toMap(), 'attributes': attributes?.toMap(),
'sharees': sharees?.map((x) => x?.toMap())?.toList(), 'sharees': sharees?.map((x) => x?.toMap()).toList(),
'publicURLs': publicURLs?.map((x) => x?.toMap())?.toList(), 'publicURLs': publicURLs?.map((x) => x?.toMap()).toList(),
'updationTime': updationTime, 'updationTime': updationTime,
'isDeleted': isDeleted, 'isDeleted': isDeleted,
}; };
} }
factory Collection.fromMap(Map<String, dynamic> map) { factory Collection.fromMap(Map<String, dynamic>? map) {
if (map == null) return null; if (map == null) {
throw Exception('Argument is null');
}
final sharees = (map['sharees'] == null || map['sharees'].length == 0) final sharees = (map['sharees'] == null || map['sharees'].length == 0)
? <User>[] ? <User>[]
: List<User>.from(map['sharees'].map((x) => User.fromMap(x))); : List<User>.from(map['sharees'].map((x) => User.fromMap(x)));
@ -152,53 +151,6 @@ class Collection {
isDeleted: map['isDeleted'] ?? false, isDeleted: map['isDeleted'] ?? false,
); );
} }
String toJson() => json.encode(toMap());
factory Collection.fromJson(String source) =>
Collection.fromMap(json.decode(source));
@override
String toString() {
return 'Collection(id: $id, owner: $owner, encryptedKey: $encryptedKey, keyDecryptionNonce: $keyDecryptionNonce, name: $name, encryptedName: $encryptedName, nameDecryptionNonce: $nameDecryptionNonce, type: $type, attributes: $attributes, sharees: $sharees, publicURLs: $publicURLs, updationTime: $updationTime, isDeleted: $isDeleted)';
}
@override
bool operator ==(Object o) {
if (identical(this, o)) return true;
return o is Collection &&
o.id == id &&
o.owner == owner &&
o.encryptedKey == encryptedKey &&
o.keyDecryptionNonce == keyDecryptionNonce &&
o.name == name &&
o.encryptedName == encryptedName &&
o.nameDecryptionNonce == nameDecryptionNonce &&
o.type == type &&
o.attributes == attributes &&
listEquals(o.sharees, sharees) &&
listEquals(o.publicURLs, publicURLs) &&
o.updationTime == updationTime &&
o.isDeleted == isDeleted;
}
@override
int get hashCode {
return id.hashCode ^
owner.hashCode ^
encryptedKey.hashCode ^
keyDecryptionNonce.hashCode ^
name.hashCode ^
encryptedName.hashCode ^
nameDecryptionNonce.hashCode ^
type.hashCode ^
attributes.hashCode ^
sharees.hashCode ^
publicURLs.hashCode ^
updationTime.hashCode ^
isDeleted.hashCode;
}
} }
enum CollectionType { enum CollectionType {
@ -208,9 +160,9 @@ enum CollectionType {
} }
class CollectionAttributes { class CollectionAttributes {
final String encryptedPath; final String? encryptedPath;
final String pathDecryptionNonce; final String? pathDecryptionNonce;
final int version; final int? version;
CollectionAttributes({ CollectionAttributes({
this.encryptedPath, this.encryptedPath,
@ -218,18 +170,6 @@ class CollectionAttributes {
this.version, this.version,
}); });
CollectionAttributes copyWith({
String encryptedPath,
String pathDecryptionNonce,
int version,
}) {
return CollectionAttributes(
encryptedPath: encryptedPath ?? this.encryptedPath,
pathDecryptionNonce: pathDecryptionNonce ?? this.pathDecryptionNonce,
version: version ?? this.version,
);
}
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
final map = <String, dynamic>{}; final map = <String, dynamic>{};
if (encryptedPath != null) { if (encryptedPath != null) {
@ -242,8 +182,10 @@ class CollectionAttributes {
return map; return map;
} }
factory CollectionAttributes.fromMap(Map<String, dynamic> map) { factory CollectionAttributes.fromMap(Map<String, dynamic>? map) {
if (map == null) return null; if (map == null) {
throw Exception('Argument is null');
}
return CollectionAttributes( return CollectionAttributes(
encryptedPath: map['encryptedPath'], encryptedPath: map['encryptedPath'],
@ -251,54 +193,19 @@ class CollectionAttributes {
version: map['version'] ?? 0, version: map['version'] ?? 0,
); );
} }
String toJson() => json.encode(toMap());
factory CollectionAttributes.fromJson(String source) =>
CollectionAttributes.fromMap(json.decode(source));
@override
String toString() =>
'CollectionAttributes(encryptedPath: $encryptedPath, pathDecryptionNonce: $pathDecryptionNonce, version: $version)';
@override
bool operator ==(Object o) {
if (identical(this, o)) return true;
return o is CollectionAttributes &&
o.encryptedPath == encryptedPath &&
o.pathDecryptionNonce == pathDecryptionNonce &&
o.version == version;
}
@override
int get hashCode =>
encryptedPath.hashCode ^ pathDecryptionNonce.hashCode ^ version.hashCode;
} }
class User { class User {
int id; int? id;
String email; String email;
String name; String? name;
User({ User({
this.id, this.id,
this.email, required this.email,
this.name, this.name,
}); });
User copyWith({
int id,
String email,
String name,
}) {
return User(
id: id ?? this.id,
email: email ?? this.email,
name: name ?? this.name,
);
}
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {
'id': id, 'id': id,
@ -307,8 +214,10 @@ class User {
}; };
} }
factory User.fromMap(Map<String, dynamic> map) { factory User.fromMap(Map<String, dynamic>? map) {
if (map == null) return null; if (map == null) {
throw Exception('Argument is null');
}
return User( return User(
id: map['id'], id: map['id'],
@ -320,34 +229,21 @@ class User {
String toJson() => json.encode(toMap()); String toJson() => json.encode(toMap());
factory User.fromJson(String source) => User.fromMap(json.decode(source)); factory User.fromJson(String source) => User.fromMap(json.decode(source));
@override
String toString() => 'CollectionOwner(id: $id, email: $email, name: $name)';
@override
bool operator ==(Object o) {
if (identical(this, o)) return true;
return o is User && o.id == id && o.email == email && o.name == name;
}
@override
int get hashCode => id.hashCode ^ email.hashCode ^ name.hashCode;
} }
class PublicURL { class PublicURL {
String url; String url;
int deviceLimit; int deviceLimit;
int validTill; int validTill;
bool enableDownload = true; bool enableDownload;
bool passwordEnabled = false; bool passwordEnabled;
PublicURL({ PublicURL({
this.url, required this.url,
this.deviceLimit, required this.deviceLimit,
this.validTill, required this.validTill,
this.enableDownload, this.enableDownload = true,
this.passwordEnabled, this.passwordEnabled = false,
}); });
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
@ -360,8 +256,10 @@ class PublicURL {
}; };
} }
factory PublicURL.fromMap(Map<String, dynamic> map) { factory PublicURL.fromMap(Map<String, dynamic>? map) {
if (map == null) return null; if (map == null) {
throw Exception('Argument is null');
}
return PublicURL( return PublicURL(
url: map['url'], url: map['url'],
@ -371,33 +269,4 @@ class PublicURL {
passwordEnabled: map['passwordEnabled'] ?? false, passwordEnabled: map['passwordEnabled'] ?? false,
); );
} }
String toJson() => json.encode(toMap());
factory PublicURL.fromJson(String source) =>
PublicURL.fromMap(json.decode(source));
@override
String toString() =>
'PublicUrl( url: $url, deviceLimit: $deviceLimit, validTill: $validTill, , enableDownload: $enableDownload, , passwordEnabled: $passwordEnabled)';
@override
bool operator ==(Object o) {
if (identical(this, o)) return true;
return o is PublicURL &&
o.deviceLimit == deviceLimit &&
o.url == url &&
o.validTill == validTill &&
o.enableDownload == enableDownload &&
o.passwordEnabled == passwordEnabled;
}
@override
int get hashCode =>
deviceLimit.hashCode ^
url.hashCode ^
validTill.hashCode ^
enableDownload.hashCode ^
passwordEnabled.hashCode;
} }

View file

@ -33,7 +33,7 @@ class CollectionFileItem {
factory CollectionFileItem.fromMap(Map<String, dynamic>? map) { factory CollectionFileItem.fromMap(Map<String, dynamic>? map) {
if (map == null) { if (map == null) {
throw ArgumentError('argument is null'); throw Exception('Argument is null');
} }
return CollectionFileItem( return CollectionFileItem(

View file

@ -1,14 +1,12 @@
// @dart=2.9
import 'dart:convert'; import 'dart:convert';
const kVisibilityVisible = 0; const visibilityVisible = 0;
const kVisibilityArchive = 1; const visibilityArchive = 1;
const kMagicKeyVisibility = 'visibility'; const magicKeyVisibility = 'visibility';
const kPubMagicKeyEditedTime = 'editedTime'; const pubMagicKeyEditedTime = 'editedTime';
const kPubMagicKeyEditedName = 'editedName'; const pubMagicKeyEditedName = 'editedName';
class MagicMetadata { class MagicMetadata {
// 0 -> visible // 0 -> visible
@ -16,23 +14,19 @@ class MagicMetadata {
// 2 -> hidden etc? // 2 -> hidden etc?
int visibility; int visibility;
MagicMetadata({this.visibility}); MagicMetadata({required this.visibility});
factory MagicMetadata.fromEncodedJson(String encodedJson) => factory MagicMetadata.fromEncodedJson(String encodedJson) =>
MagicMetadata.fromJson(jsonDecode(encodedJson)); MagicMetadata.fromJson(jsonDecode(encodedJson));
factory MagicMetadata.fromJson(dynamic json) => MagicMetadata.fromMap(json); factory MagicMetadata.fromJson(dynamic json) => MagicMetadata.fromMap(json);
Map<String, dynamic> toJson() { factory MagicMetadata.fromMap(Map<String, dynamic>? map) {
final map = <String, dynamic>{}; if (map == null) {
map[kMagicKeyVisibility] = visibility; throw Exception('Argument is null');
return map; }
}
factory MagicMetadata.fromMap(Map<String, dynamic> map) {
if (map == null) return null;
return MagicMetadata( return MagicMetadata(
visibility: map[kMagicKeyVisibility] ?? kVisibilityVisible, visibility: map[magicKeyVisibility] ?? visibilityVisible,
); );
} }
} }
@ -41,7 +35,7 @@ class PubMagicMetadata {
int editedTime; int editedTime;
String editedName; String editedName;
PubMagicMetadata({this.editedTime, this.editedName}); PubMagicMetadata({required this.editedTime, required this.editedName});
factory PubMagicMetadata.fromEncodedJson(String encodedJson) => factory PubMagicMetadata.fromEncodedJson(String encodedJson) =>
PubMagicMetadata.fromJson(jsonDecode(encodedJson)); PubMagicMetadata.fromJson(jsonDecode(encodedJson));
@ -49,18 +43,13 @@ class PubMagicMetadata {
factory PubMagicMetadata.fromJson(dynamic json) => factory PubMagicMetadata.fromJson(dynamic json) =>
PubMagicMetadata.fromMap(json); PubMagicMetadata.fromMap(json);
Map<String, dynamic> toJson() { factory PubMagicMetadata.fromMap(Map<String, dynamic>? map) {
final map = <String, dynamic>{}; if (map == null) {
map[kPubMagicKeyEditedTime] = editedTime; throw Exception('Argument is null');
map[kPubMagicKeyEditedName] = editedName; }
return map;
}
factory PubMagicMetadata.fromMap(Map<String, dynamic> map) {
if (map == null) return null;
return PubMagicMetadata( return PubMagicMetadata(
editedTime: map[kPubMagicKeyEditedTime], editedTime: map[pubMagicKeyEditedTime],
editedName: map[kPubMagicKeyEditedName], editedName: map[pubMagicKeyEditedName],
); );
} }
} }
@ -71,7 +60,7 @@ class CollectionMagicMetadata {
// 2 -> hidden etc? // 2 -> hidden etc?
int visibility; int visibility;
CollectionMagicMetadata({this.visibility}); CollectionMagicMetadata({required this.visibility});
factory CollectionMagicMetadata.fromEncodedJson(String encodedJson) => factory CollectionMagicMetadata.fromEncodedJson(String encodedJson) =>
CollectionMagicMetadata.fromJson(jsonDecode(encodedJson)); CollectionMagicMetadata.fromJson(jsonDecode(encodedJson));
@ -79,16 +68,12 @@ class CollectionMagicMetadata {
factory CollectionMagicMetadata.fromJson(dynamic json) => factory CollectionMagicMetadata.fromJson(dynamic json) =>
CollectionMagicMetadata.fromMap(json); CollectionMagicMetadata.fromMap(json);
Map<String, dynamic> toJson() { factory CollectionMagicMetadata.fromMap(Map<String, dynamic>? map) {
final map = <String, dynamic>{}; if (map == null) {
map[kMagicKeyVisibility] = visibility; throw Exception('Argument is null');
return map; }
}
factory CollectionMagicMetadata.fromMap(Map<String, dynamic> map) {
if (map == null) return null;
return CollectionMagicMetadata( return CollectionMagicMetadata(
visibility: map[kMagicKeyVisibility] ?? kVisibilityVisible, visibility: map[magicKeyVisibility] ?? visibilityVisible,
); );
} }
} }

View file

@ -14,7 +14,7 @@ class AlbumSearchResult extends SearchResult {
@override @override
String name() { String name() {
return collectionWithThumbnail.collection.name; return collectionWithThumbnail.collection.name!;
} }
@override @override

View file

@ -34,7 +34,7 @@ class Subscription {
factory Subscription.fromMap(Map<String, dynamic>? map) { factory Subscription.fromMap(Map<String, dynamic>? map) {
if (map == null) { if (map == null) {
throw ArgumentError("argument is null"); throw Exception("Argument is null");
} }
return Subscription( return Subscription(
productID: map['productID'], productID: map['productID'],

View file

@ -1,5 +1,3 @@
// @dart=2.9
import 'dart:math'; import 'dart:math';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
@ -11,7 +9,7 @@ class UserDetails {
final int fileCount; final int fileCount;
final int sharedCollectionsCount; final int sharedCollectionsCount;
final Subscription subscription; final Subscription subscription;
final FamilyData familyData; final FamilyData? familyData;
UserDetails( UserDetails(
this.email, this.email,
@ -28,8 +26,8 @@ class UserDetails {
bool isFamilyAdmin() { bool isFamilyAdmin() {
assert(isPartOfFamily(), "verify user is part of family before calling"); assert(isPartOfFamily(), "verify user is part of family before calling");
final FamilyMember currentUserMember = familyData?.members final FamilyMember currentUserMember = familyData!.members!
?.firstWhere((element) => element.email.trim() == email.trim()); .firstWhere((element) => element.email.trim() == email.trim());
return currentUserMember.isAdmin; return currentUserMember.isAdmin;
} }
@ -37,24 +35,20 @@ class UserDetails {
// belong to family group. Otherwise, it will return storage consumed by // belong to family group. Otherwise, it will return storage consumed by
// current user // current user
int getFamilyOrPersonalUsage() { int getFamilyOrPersonalUsage() {
return isPartOfFamily() ? familyData.getTotalUsage() : usage; return isPartOfFamily() ? familyData!.getTotalUsage() : usage;
} }
int getFreeStorage() { int getFreeStorage() {
return max( return max(
isPartOfFamily() isPartOfFamily()
? (familyData.storage - familyData.getTotalUsage()) ? (familyData!.storage - familyData!.getTotalUsage())
: (subscription.storage - (usage)), : (subscription.storage - (usage)),
0, 0,
); );
} }
int getTotalStorage() { int getTotalStorage() {
return isPartOfFamily() ? familyData.storage : subscription.storage; return isPartOfFamily() ? familyData!.storage : subscription.storage;
}
int getPersonalUsage() {
return usage;
} }
factory UserDetails.fromMap(Map<String, dynamic> map) { factory UserDetails.fromMap(Map<String, dynamic> map) {
@ -67,17 +61,6 @@ class UserDetails {
FamilyData.fromMap(map['familyData']), FamilyData.fromMap(map['familyData']),
); );
} }
Map<String, dynamic> toMap() {
return {
'email': email,
'usage': usage,
'fileCount': fileCount,
'sharedCollectionsCount': sharedCollectionsCount,
'subscription': subscription,
'familyData': familyData
};
}
} }
class FamilyMember { class FamilyMember {
@ -96,14 +79,10 @@ class FamilyMember {
map['isAdmin'] as bool, map['isAdmin'] as bool,
); );
} }
Map<String, dynamic> toMap() {
return {'email': email, 'usage': usage, 'id': id, 'isAdmin': isAdmin};
}
} }
class FamilyData { class FamilyData {
final List<FamilyMember> members; final List<FamilyMember>? members;
// Storage available based on the family plan // Storage available based on the family plan
final int storage; final int storage;
@ -112,13 +91,11 @@ class FamilyData {
FamilyData(this.members, this.storage, this.expiryTime); FamilyData(this.members, this.storage, this.expiryTime);
int getTotalUsage() { int getTotalUsage() {
return members.map((e) => e.usage).toList().sum; return members!.map((e) => e.usage).toList().sum;
} }
factory FamilyData.fromMap(Map<String, dynamic> map) { static fromMap(Map<String, dynamic>? map) {
if (map == null) { if (map == null) return null;
return null;
}
assert(map['members'] != null && map['members'].length >= 0); assert(map['members'] != null && map['members'].length >= 0);
final members = List<FamilyMember>.from( final members = List<FamilyMember>.from(
map['members'].map((x) => FamilyMember.fromMap(x)), map['members'].map((x) => FamilyMember.fromMap(x)),
@ -129,12 +106,4 @@ class FamilyData {
map['expiryTime'] as int, map['expiryTime'] as int,
); );
} }
Map<String, dynamic> toMap() {
return {
'members': members.map((x) => x?.toMap())?.toList(),
'storage': storage,
'expiryTime': expiryTime
};
}
} }

View file

@ -32,9 +32,9 @@ class FileMagicService {
FileMagicService._privateConstructor(); FileMagicService._privateConstructor();
Future<void> changeVisibility(List<File> files, int visibility) async { Future<void> changeVisibility(List<File> files, int visibility) async {
final Map<String, dynamic> update = {kMagicKeyVisibility: visibility}; final Map<String, dynamic> update = {magicKeyVisibility: visibility};
await _updateMagicData(files, update); await _updateMagicData(files, update);
if (visibility == kVisibilityVisible) { if (visibility == visibilityVisible) {
// 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());
Bus.instance Bus.instance
@ -64,7 +64,8 @@ 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.
final 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;
}); });
@ -134,7 +135,8 @@ 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.
final 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;
}); });

View file

@ -46,7 +46,7 @@ class HiddenCollectionsButtonWidget extends StatelessWidget {
const Padding(padding: EdgeInsets.all(6)), const Padding(padding: EdgeInsets.all(6)),
FutureBuilder<int>( FutureBuilder<int>(
future: FilesDB.instance.fileCountWithVisibility( future: FilesDB.instance.fileCountWithVisibility(
kVisibilityArchive, visibilityArchive,
Configuration.instance.getUserID(), Configuration.instance.getUserID(),
), ),
builder: (context, snapshot) { builder: (context, snapshot) {

View file

@ -87,7 +87,7 @@ class ValidityWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (currentSubscription == null) { if (currentSubscription == null) {
return Container(); return const SizedBox.shrink();
} }
final endDate = getDateAndMonthAndYear( final endDate = getDateAndMonthAndYear(
DateTime.fromMicrosecondsSinceEpoch(currentSubscription.expiryTime), DateTime.fromMicrosecondsSinceEpoch(currentSubscription.expiryTime),

View file

@ -106,7 +106,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()) {
final bool isArchived = final bool isArchived =
widget.file.magicMetadata.visibility == kVisibilityArchive; widget.file.magicMetadata.visibility == visibilityArchive;
children.add( children.add(
Tooltip( Tooltip(
message: isArchived ? "Unhide" : "Hide", message: isArchived ? "Unhide" : "Hide",
@ -123,7 +123,7 @@ class FadingBottomBarState extends State<FadingBottomBar> {
await changeVisibility( await changeVisibility(
context, context,
[widget.file], [widget.file],
isArchived ? kVisibilityVisible : kVisibilityArchive, isArchived ? visibilityVisible : visibilityArchive,
); );
safeRefresh(); safeRefresh();
}, },

View file

@ -33,7 +33,7 @@ class ArchivePage extends StatelessWidget {
creationStartTime, creationStartTime,
creationEndTime, creationEndTime,
Configuration.instance.getUserID(), Configuration.instance.getUserID(),
visibility: kVisibilityArchive, visibility: visibilityArchive,
limit: limit, limit: limit,
asc: asc, asc: asc,
); );

View file

@ -220,8 +220,8 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
context, context,
widget.collection, widget.collection,
widget.collection.isArchived() widget.collection.isArchived()
? kVisibilityVisible ? visibilityVisible
: kVisibilityArchive, : visibilityArchive,
); );
} else if (value == 3) { } else if (value == 3) {
await _trashCollection(); await _trashCollection();

View file

@ -382,7 +382,7 @@ class _OverlayWidgetState extends State<OverlayWidget> {
onPressed: () { onPressed: () {
_handleVisibilityChangeRequest( _handleVisibilityChangeRequest(
context, context,
showArchive ? kVisibilityArchive : kVisibilityVisible, showArchive ? visibilityArchive : visibilityVisible,
); );
}, },
), ),

View file

@ -1,5 +1,3 @@
// @dart=2.9
import 'package:local_auth/auth_strings.dart'; import 'package:local_auth/auth_strings.dart';
import 'package:local_auth/local_auth.dart'; import 'package:local_auth/local_auth.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';

View file

@ -1,5 +1,3 @@
// @dart=2.9
import 'dart:math'; import 'dart:math';
double convertBytesToGBs(final int bytes, {int precision = 2}) { double convertBytesToGBs(final int bytes, {int precision = 2}) {
@ -8,15 +6,15 @@ double convertBytesToGBs(final int bytes, {int precision = 2}) {
); );
} }
final kStorageUnits = ["bytes", "KB", "MB", "GB"]; final storageUnits = ["bytes", "KB", "MB", "GB"];
String convertBytesToReadableFormat(int bytes) { String convertBytesToReadableFormat(int bytes) {
int storageUnitIndex = 0; int storageUnitIndex = 0;
while (bytes >= 1024 && storageUnitIndex < kStorageUnits.length - 1) { while (bytes >= 1024 && storageUnitIndex < storageUnits.length - 1) {
storageUnitIndex++; storageUnitIndex++;
bytes = (bytes / 1024).round(); bytes = (bytes / 1024).round();
} }
return bytes.toString() + " " + kStorageUnits[storageUnitIndex]; return bytes.toString() + " " + storageUnits[storageUnitIndex];
} }
String formatBytes(int bytes, [int decimals = 2]) { String formatBytes(int bytes, [int decimals = 2]) {
@ -24,5 +22,5 @@ String formatBytes(int bytes, [int decimals = 2]) {
const k = 1024; const k = 1024;
final int dm = decimals < 0 ? 0 : decimals; final int dm = decimals < 0 ? 0 : decimals;
final 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)) + ' ' + storageUnits[i];
} }

View file

@ -1,5 +1,3 @@
// @dart=2.9
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -7,13 +5,13 @@ import 'package:flutter/material.dart';
class Debouncer { class Debouncer {
final Duration _duration; final Duration _duration;
final ValueNotifier<bool> _debounceActiveNotifier = ValueNotifier(false); final ValueNotifier<bool> _debounceActiveNotifier = ValueNotifier(false);
Timer _debounceTimer; Timer? _debounceTimer;
Debouncer(this._duration); Debouncer(this._duration);
void run(Future<void> Function() fn) { void run(Future<void> Function() fn) {
if (isActive()) { if (isActive()) {
_debounceTimer.cancel(); _debounceTimer!.cancel();
} }
_debounceTimer = Timer(_duration, () async { _debounceTimer = Timer(_duration, () async {
await fn(); await fn();
@ -24,11 +22,11 @@ class Debouncer {
void cancelDebounce() { void cancelDebounce() {
if (_debounceTimer != null) { if (_debounceTimer != null) {
_debounceTimer.cancel(); _debounceTimer!.cancel();
} }
} }
bool isActive() => _debounceTimer != null && _debounceTimer.isActive; bool isActive() => _debounceTimer != null && _debounceTimer!.isActive;
ValueNotifier<bool> get debounceActiveNotifier { ValueNotifier<bool> get debounceActiveNotifier {
return _debounceActiveNotifier; return _debounceActiveNotifier;

View file

@ -1,5 +1,3 @@
// @dart=2.9
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
enum AlbumSortKey { enum AlbumSortKey {
@ -13,15 +11,14 @@ class LocalSettings {
static final LocalSettings instance = LocalSettings._privateConstructor(); static final LocalSettings instance = LocalSettings._privateConstructor();
static const kCollectionSortPref = "collection_sort_pref"; static const kCollectionSortPref = "collection_sort_pref";
SharedPreferences _prefs; late SharedPreferences _prefs;
Future<void> init() async { Future<void> init() async {
_prefs = await SharedPreferences.getInstance(); _prefs = await SharedPreferences.getInstance();
} }
AlbumSortKey albumSortKey() { AlbumSortKey albumSortKey() {
return AlbumSortKey.values[_prefs.getInt(kCollectionSortPref) ?? 0] ?? return AlbumSortKey.values[_prefs.getInt(kCollectionSortPref) ?? 0];
AlbumSortKey.lastUpdated;
} }
Future<bool> setAlbumSortKey(AlbumSortKey key) { Future<bool> setAlbumSortKey(AlbumSortKey key) {

View file

@ -23,14 +23,14 @@ Future<void> changeVisibility(
) async { ) async {
final dialog = createProgressDialog( final dialog = createProgressDialog(
context, context,
newVisibility == kVisibilityArchive ? "Hiding..." : "Unhiding...", newVisibility == visibilityArchive ? "Hiding..." : "Unhiding...",
); );
await dialog.show(); await dialog.show();
try { try {
await FileMagicService.instance.changeVisibility(files, newVisibility); await FileMagicService.instance.changeVisibility(files, newVisibility);
showShortToast( showShortToast(
context, context,
newVisibility == kVisibilityArchive newVisibility == visibilityArchive
? "Successfully hidden" ? "Successfully hidden"
: "Successfully unhidden", : "Successfully unhidden",
); );
@ -50,17 +50,17 @@ Future<void> changeCollectionVisibility(
) async { ) async {
final dialog = createProgressDialog( final dialog = createProgressDialog(
context, context,
newVisibility == kVisibilityArchive ? "Hiding..." : "Unhiding...", newVisibility == visibilityArchive ? "Hiding..." : "Unhiding...",
); );
await dialog.show(); await dialog.show();
try { try {
final Map<String, dynamic> update = {kMagicKeyVisibility: newVisibility}; final Map<String, dynamic> update = {magicKeyVisibility: 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());
showShortToast( showShortToast(
context, context,
newVisibility == kVisibilityArchive newVisibility == visibilityArchive
? "Successfully hidden" ? "Successfully hidden"
: "Successfully unhidden", : "Successfully unhidden",
); );
@ -82,7 +82,7 @@ Future<bool> editTime(
await _updatePublicMetadata( await _updatePublicMetadata(
context, context,
files, files,
kPubMagicKeyEditedTime, pubMagicKeyEditedTime,
editedTime, editedTime,
); );
return true; return true;
@ -115,7 +115,7 @@ Future<bool> editFilename(
await _updatePublicMetadata( await _updatePublicMetadata(
context, context,
List.of([file]), List.of([file]),
kPubMagicKeyEditedName, pubMagicKeyEditedName,
result, result,
); );
return true; return true;
@ -152,5 +152,5 @@ Future<void> _updatePublicMetadata(
} }
bool _shouldReloadGallery(String key) { bool _shouldReloadGallery(String key) {
return key == kPubMagicKeyEditedTime; return key == pubMagicKeyEditedTime;
} }

View file

@ -1,10 +1,8 @@
// @dart=2.9
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
Future<T> routeToPage<T extends Object>( Future<T?> routeToPage<T extends Object>(
BuildContext context, BuildContext context,
Widget page, { Widget page, {
bool forceCustomPageRoute = false, bool forceCustomPageRoute = false,
@ -63,13 +61,13 @@ class SwipeableRouteBuilder<T> extends PageRoute<T> {
const CupertinoPageTransitionsBuilder(); // Default iOS/macOS (to get the swipe right to go back gesture) const CupertinoPageTransitionsBuilder(); // Default iOS/macOS (to get the swipe right to go back gesture)
// final PageTransitionsBuilder matchingBuilder = const FadeUpwardsPageTransitionsBuilder(); // Default Android/Linux/Windows // final PageTransitionsBuilder matchingBuilder = const FadeUpwardsPageTransitionsBuilder(); // Default Android/Linux/Windows
SwipeableRouteBuilder({this.pageBuilder}); SwipeableRouteBuilder({required this.pageBuilder});
@override @override
Color get barrierColor => null; Null get barrierColor => null;
@override @override
String get barrierLabel => null; Null get barrierLabel => null;
@override @override
Widget buildPage( Widget buildPage(
@ -110,21 +108,21 @@ class SwipeableRouteBuilder<T> extends PageRoute<T> {
class TransparentRoute extends PageRoute<void> { class TransparentRoute extends PageRoute<void> {
TransparentRoute({ TransparentRoute({
@required this.builder, required this.builder,
RouteSettings settings, RouteSettings? settings,
}) : assert(builder != null), }) : assert(builder != null),
super(settings: settings, fullscreenDialog: false); super(settings: settings, fullscreenDialog: false);
final WidgetBuilder builder; final WidgetBuilder? builder;
@override @override
bool get opaque => false; bool get opaque => false;
@override @override
Color get barrierColor => null; Null get barrierColor => null;
@override @override
String get barrierLabel => null; Null get barrierLabel => null;
@override @override
bool get maintainState => true; bool get maintainState => true;
@ -138,7 +136,7 @@ class TransparentRoute extends PageRoute<void> {
Animation<double> animation, Animation<double> animation,
Animation<double> secondaryAnimation, Animation<double> secondaryAnimation,
) { ) {
final result = builder(context); final result = builder!(context);
return FadeTransition( return FadeTransition(
opacity: Tween<double>(begin: 0, end: 1).animate(animation), opacity: Tween<double>(begin: 0, end: 1).animate(animation),
child: Semantics( child: Semantics(