Fix user storage indicator
This commit is contained in:
parent
fd5b234ba9
commit
1c77951431
4 changed files with 148 additions and 30 deletions
|
@ -39,4 +39,11 @@ class UserApi {
|
||||||
final data = jsonDecode(response.body);
|
final data = jsonDecode(response.body);
|
||||||
return PersonalProfile.fromMap(data);
|
return PersonalProfile.fromMap(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<StorageQuota> getStorageQuota(ApiClient client) async {
|
||||||
|
final response = await client.get("/users/${client.userId}/storage");
|
||||||
|
client.checkResponse(response);
|
||||||
|
final data = jsonDecode(response.body);
|
||||||
|
return StorageQuota.fromMap(data);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'package:recon/auxiliary.dart';
|
||||||
|
import 'package:recon/models/users/entitlement.dart';
|
||||||
import 'package:recon/models/users/user_profile.dart';
|
import 'package:recon/models/users/user_profile.dart';
|
||||||
|
|
||||||
class PersonalProfile {
|
class PersonalProfile {
|
||||||
|
@ -6,18 +8,21 @@ class PersonalProfile {
|
||||||
final String email;
|
final String email;
|
||||||
final DateTime? publicBanExpiration;
|
final DateTime? publicBanExpiration;
|
||||||
final String? publicBanType;
|
final String? publicBanType;
|
||||||
final List<StorageQuotas> storageQuotas;
|
|
||||||
final Map<String, int> quotaBytesSource;
|
|
||||||
final int quotaBytes;
|
|
||||||
final int usedBytes;
|
|
||||||
final bool twoFactor;
|
final bool twoFactor;
|
||||||
final bool isPatreonSupporter;
|
|
||||||
final UserProfile userProfile;
|
final UserProfile userProfile;
|
||||||
|
final List<Entitlement> entitlements;
|
||||||
|
final List<SupporterMetadata> supporterMetadata;
|
||||||
|
|
||||||
PersonalProfile({
|
PersonalProfile({
|
||||||
required this.id, required this.username, required this.email, required this.publicBanExpiration,
|
required this.id,
|
||||||
required this.publicBanType, required this.storageQuotas, required this.quotaBytesSource, required this.quotaBytes,
|
required this.username,
|
||||||
required this.usedBytes, required this.twoFactor, required this.isPatreonSupporter, required this.userProfile,
|
required this.email,
|
||||||
|
required this.publicBanExpiration,
|
||||||
|
required this.publicBanType,
|
||||||
|
required this.twoFactor,
|
||||||
|
required this.userProfile,
|
||||||
|
required this.entitlements,
|
||||||
|
required this.supporterMetadata,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory PersonalProfile.fromMap(Map map) {
|
factory PersonalProfile.fromMap(Map map) {
|
||||||
|
@ -27,34 +32,83 @@ class PersonalProfile {
|
||||||
email: map["email"] ?? "",
|
email: map["email"] ?? "",
|
||||||
publicBanExpiration: DateTime.tryParse(map["publicBanExpiration"] ?? ""),
|
publicBanExpiration: DateTime.tryParse(map["publicBanExpiration"] ?? ""),
|
||||||
publicBanType: map["publicBanType"],
|
publicBanType: map["publicBanType"],
|
||||||
storageQuotas: (map["storageQuotas"] as List? ?? []).map((e) => StorageQuotas.fromMap(e)).toList(),
|
|
||||||
quotaBytesSource: (map["quotaBytesSources"] as Map? ?? {}).map((key, value) => MapEntry(key, value as int)),
|
|
||||||
quotaBytes: map["quotaBytes"] ?? 0,
|
|
||||||
usedBytes: map["usedBytes"] ?? 0,
|
|
||||||
twoFactor: map["2fa_login"] ?? false,
|
twoFactor: map["2fa_login"] ?? false,
|
||||||
isPatreonSupporter: map["patreonData"]?["isPatreonSupporter"] ?? false,
|
|
||||||
userProfile: UserProfile.fromMap(map["profile"]),
|
userProfile: UserProfile.fromMap(map["profile"]),
|
||||||
|
entitlements: ((map["entitlements"] ?? []) as List).map((e) => Entitlement.fromMap(e)).toList(),
|
||||||
|
supporterMetadata: ((map["supporterMetadata"] ?? []) as List).map((e) => SupporterMetadata.fromMap(e)).toList(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get isPatreonSupporter =>
|
||||||
|
supporterMetadata.whereType<PatreonSupporter>().any((element) => element.isActiveSupporter);
|
||||||
}
|
}
|
||||||
|
|
||||||
class StorageQuotas {
|
class StorageQuota {
|
||||||
final String id;
|
final String id;
|
||||||
final int bytes;
|
final int usedBytes;
|
||||||
final DateTime addedOn;
|
final int quotaBytes;
|
||||||
final DateTime expiresOn;
|
final int fullQuotaBytes;
|
||||||
final String giftedByUserId;
|
|
||||||
|
|
||||||
StorageQuotas({required this.id, required this.bytes, required this.addedOn, required this.expiresOn,
|
StorageQuota({
|
||||||
required this.giftedByUserId});
|
required this.id,
|
||||||
|
required this.usedBytes,
|
||||||
|
required this.quotaBytes,
|
||||||
|
required this.fullQuotaBytes,
|
||||||
|
});
|
||||||
|
|
||||||
factory StorageQuotas.fromMap(Map map) {
|
factory StorageQuota.fromMap(Map map) {
|
||||||
return StorageQuotas(
|
return StorageQuota(
|
||||||
id: map["id"] ?? "",
|
id: map["id"] ?? "",
|
||||||
bytes: map["bytes"] ?? 0,
|
usedBytes: map["usedBytes"] ?? 0,
|
||||||
addedOn: DateTime.tryParse(map["addedOn"]) ?? DateTime.fromMillisecondsSinceEpoch(0),
|
quotaBytes: map["quotaBytes"] ?? 0,
|
||||||
expiresOn: DateTime.tryParse(map["expiresOn"]) ?? DateTime.fromMillisecondsSinceEpoch(0),
|
fullQuotaBytes: map["fullQuotaBytes"] ?? 0,
|
||||||
giftedByUserId: map["giftedByUserId"] ?? "",
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SupporterMetadata {
|
||||||
|
SupporterMetadata();
|
||||||
|
|
||||||
|
factory SupporterMetadata.fromMap(Map map) {
|
||||||
|
final type = map["\$type"];
|
||||||
|
return switch (type) {
|
||||||
|
"patreon" => PatreonSupporter.fromMap(map),
|
||||||
|
_ => SupporterMetadata(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PatreonSupporter extends SupporterMetadata {
|
||||||
|
final bool isActiveSupporter;
|
||||||
|
final int totalSupportMonths;
|
||||||
|
final int totalSupportCents;
|
||||||
|
final int lastTierCents;
|
||||||
|
final int highestTierCents;
|
||||||
|
final int lowestTierCents;
|
||||||
|
final DateTime firstSupportTimestamp;
|
||||||
|
final DateTime lastSupportTimestamp;
|
||||||
|
|
||||||
|
PatreonSupporter({
|
||||||
|
required this.isActiveSupporter,
|
||||||
|
required this.totalSupportMonths,
|
||||||
|
required this.totalSupportCents,
|
||||||
|
required this.lastTierCents,
|
||||||
|
required this.highestTierCents,
|
||||||
|
required this.lowestTierCents,
|
||||||
|
required this.firstSupportTimestamp,
|
||||||
|
required this.lastSupportTimestamp,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory PatreonSupporter.fromMap(Map map) {
|
||||||
|
return PatreonSupporter(
|
||||||
|
isActiveSupporter: map["isActiveSupporter"],
|
||||||
|
totalSupportMonths: map["totalSupportMonths"],
|
||||||
|
totalSupportCents: map["totalSupportCents"],
|
||||||
|
lastTierCents: map["lastTierCents"],
|
||||||
|
highestTierCents: map["highestTierCents"],
|
||||||
|
lowestTierCents: map["lowestTierCents"],
|
||||||
|
firstSupportTimestamp: DateTime.tryParse(map["firstSupportTimestamp"] ?? "") ?? DateTimeX.epoch,
|
||||||
|
lastSupportTimestamp: DateTime.tryParse(map["lastSupportTimestamp"] ?? "") ?? DateTimeX.epoch,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
49
lib/models/users/entitlement.dart
Normal file
49
lib/models/users/entitlement.dart
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import 'package:recon/auxiliary.dart';
|
||||||
|
|
||||||
|
class Entitlement {
|
||||||
|
Entitlement();
|
||||||
|
|
||||||
|
factory Entitlement.fromMap(Map map) {
|
||||||
|
final type = map["\$type"];
|
||||||
|
|
||||||
|
return switch (type) {
|
||||||
|
"storageSpace" => StorageSpace.fromMap(map),
|
||||||
|
_ => Entitlement(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StorageSpace extends Entitlement {
|
||||||
|
final int bytes;
|
||||||
|
final int maximumShareLevel;
|
||||||
|
final String storageId;
|
||||||
|
final String group;
|
||||||
|
final DateTime startsOn;
|
||||||
|
final DateTime expiresOn;
|
||||||
|
final String name;
|
||||||
|
final String description;
|
||||||
|
|
||||||
|
StorageSpace({
|
||||||
|
required this.bytes,
|
||||||
|
required this.maximumShareLevel,
|
||||||
|
required this.storageId,
|
||||||
|
required this.group,
|
||||||
|
required this.startsOn,
|
||||||
|
required this.expiresOn,
|
||||||
|
required this.name,
|
||||||
|
required this.description,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory StorageSpace.fromMap(Map map) {
|
||||||
|
return StorageSpace(
|
||||||
|
bytes: map["bytes"],
|
||||||
|
maximumShareLevel: map["maximumShareLevel"],
|
||||||
|
storageId: map["storageId"],
|
||||||
|
group: map["group"],
|
||||||
|
startsOn: DateTime.tryParse(map["startsOn"] ?? "") ?? DateTimeX.epoch,
|
||||||
|
expiresOn: DateTime.tryParse(map["expiresOn"] ?? "") ?? DateTimeX.epoch,
|
||||||
|
name: map["name"],
|
||||||
|
description: map["description"],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ class MyProfileDialog extends StatefulWidget {
|
||||||
class _MyProfileDialogState extends State<MyProfileDialog> {
|
class _MyProfileDialogState extends State<MyProfileDialog> {
|
||||||
ClientHolder? _clientHolder;
|
ClientHolder? _clientHolder;
|
||||||
Future<PersonalProfile>? _personalProfileFuture;
|
Future<PersonalProfile>? _personalProfileFuture;
|
||||||
|
Future<StorageQuota>? _storageQuotaFuture;
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -27,6 +28,7 @@ class _MyProfileDialogState extends State<MyProfileDialog> {
|
||||||
_clientHolder = clientHolder;
|
_clientHolder = clientHolder;
|
||||||
final apiClient = _clientHolder!.apiClient;
|
final apiClient = _clientHolder!.apiClient;
|
||||||
_personalProfileFuture = UserApi.getPersonalProfile(apiClient);
|
_personalProfileFuture = UserApi.getPersonalProfile(apiClient);
|
||||||
|
_storageQuotaFuture = UserApi.getStorageQuota(apiClient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +89,13 @@ class _MyProfileDialogState extends State<MyProfileDialog> {
|
||||||
children: [Text("Ban Expiration: ", style: tt.labelLarge,),
|
children: [Text("Ban Expiration: ", style: tt.labelLarge,),
|
||||||
Text(dateFormat.format(profile.publicBanExpiration!))],
|
Text(dateFormat.format(profile.publicBanExpiration!))],
|
||||||
),
|
),
|
||||||
StorageIndicator(usedBytes: profile.usedBytes, maxBytes: profile.quotaBytes,),
|
FutureBuilder(
|
||||||
|
future: _storageQuotaFuture,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final storage = snapshot.data;
|
||||||
|
return StorageIndicator(usedBytes: storage?.usedBytes ?? 0, maxBytes: storage?.fullQuotaBytes ?? 1,);
|
||||||
|
}
|
||||||
|
),
|
||||||
const SizedBox(height: 12,),
|
const SizedBox(height: 12,),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue