add thumbhash support to mobile app
This commit is contained in:
parent
48e4ea5231
commit
000c2bf43f
6 changed files with 305 additions and 57 deletions
|
@ -30,7 +30,8 @@ class Asset {
|
|||
exifInfo =
|
||||
remote.exifInfo != null ? ExifInfo.fromDto(remote.exifInfo!) : null,
|
||||
isFavorite = remote.isFavorite,
|
||||
isArchived = remote.isArchived;
|
||||
isArchived = remote.isArchived,
|
||||
thumbhash = remote.thumbhash;
|
||||
|
||||
Asset.local(AssetEntity local, List<int> hash)
|
||||
: localId = local.id,
|
||||
|
@ -74,6 +75,7 @@ class Asset {
|
|||
this.exifInfo,
|
||||
required this.isFavorite,
|
||||
required this.isArchived,
|
||||
required this.thumbhash,
|
||||
});
|
||||
|
||||
@ignore
|
||||
|
@ -108,6 +110,8 @@ class Asset {
|
|||
)
|
||||
String checksum;
|
||||
|
||||
String? thumbhash;
|
||||
|
||||
@Index(unique: false, replace: false, type: IndexType.hash)
|
||||
String? remoteId;
|
||||
|
||||
|
@ -180,6 +184,7 @@ class Asset {
|
|||
if (other is! Asset) return false;
|
||||
return id == other.id &&
|
||||
checksum == other.checksum &&
|
||||
thumbhash == other.thumbhash &&
|
||||
remoteId == other.remoteId &&
|
||||
localId == other.localId &&
|
||||
ownerId == other.ownerId &&
|
||||
|
@ -202,6 +207,7 @@ class Asset {
|
|||
int get hashCode =>
|
||||
id.hashCode ^
|
||||
checksum.hashCode ^
|
||||
thumbhash.hashCode ^
|
||||
remoteId.hashCode ^
|
||||
localId.hashCode ^
|
||||
ownerId.hashCode ^
|
||||
|
@ -222,6 +228,7 @@ class Asset {
|
|||
bool canUpdate(Asset a) {
|
||||
assert(isInDb);
|
||||
assert(checksum == a.checksum);
|
||||
assert(thumbhash == a.thumbhash);
|
||||
assert(a.storage != AssetState.merged);
|
||||
return a.updatedAt.isAfter(updatedAt) ||
|
||||
a.isRemote && !isRemote ||
|
||||
|
@ -292,6 +299,7 @@ class Asset {
|
|||
Asset _copyWith({
|
||||
Id? id,
|
||||
String? checksum,
|
||||
String? thumbhash,
|
||||
String? remoteId,
|
||||
String? localId,
|
||||
int? ownerId,
|
||||
|
@ -311,6 +319,7 @@ class Asset {
|
|||
Asset(
|
||||
id: id ?? this.id,
|
||||
checksum: checksum ?? this.checksum,
|
||||
thumbhash: thumbhash ?? this.thumbhash,
|
||||
remoteId: remoteId ?? this.remoteId,
|
||||
localId: localId ?? this.localId,
|
||||
ownerId: ownerId ?? this.ownerId,
|
||||
|
@ -365,6 +374,7 @@ class Asset {
|
|||
"remoteId": "${remoteId ?? "N/A"}",
|
||||
"localId": "${localId ?? "N/A"}",
|
||||
"checksum": "$checksum",
|
||||
"thumbhash": "$thumbhash",
|
||||
"ownerId": $ownerId,
|
||||
"livePhotoVideoId": "${livePhotoVideoId ?? "N/A"}",
|
||||
"fileCreatedAt": "$fileCreatedAt",
|
||||
|
|
|
@ -77,19 +77,24 @@ const AssetSchema = CollectionSchema(
|
|||
name: r'remoteId',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'type': PropertySchema(
|
||||
r'thumbhash': PropertySchema(
|
||||
id: 12,
|
||||
name: r'thumbhash',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'type': PropertySchema(
|
||||
id: 13,
|
||||
name: r'type',
|
||||
type: IsarType.byte,
|
||||
enumMap: _AssettypeEnumValueMap,
|
||||
),
|
||||
r'updatedAt': PropertySchema(
|
||||
id: 13,
|
||||
id: 14,
|
||||
name: r'updatedAt',
|
||||
type: IsarType.dateTime,
|
||||
),
|
||||
r'width': PropertySchema(
|
||||
id: 14,
|
||||
id: 15,
|
||||
name: r'width',
|
||||
type: IsarType.int,
|
||||
)
|
||||
|
@ -179,6 +184,12 @@ int _assetEstimateSize(
|
|||
bytesCount += 3 + value.length * 3;
|
||||
}
|
||||
}
|
||||
{
|
||||
final value = object.thumbhash;
|
||||
if (value != null) {
|
||||
bytesCount += 3 + value.length * 3;
|
||||
}
|
||||
}
|
||||
return bytesCount;
|
||||
}
|
||||
|
||||
|
@ -200,9 +211,10 @@ void _assetSerialize(
|
|||
writer.writeString(offsets[9], object.localId);
|
||||
writer.writeLong(offsets[10], object.ownerId);
|
||||
writer.writeString(offsets[11], object.remoteId);
|
||||
writer.writeByte(offsets[12], object.type.index);
|
||||
writer.writeDateTime(offsets[13], object.updatedAt);
|
||||
writer.writeInt(offsets[14], object.width);
|
||||
writer.writeString(offsets[12], object.thumbhash);
|
||||
writer.writeByte(offsets[13], object.type.index);
|
||||
writer.writeDateTime(offsets[14], object.updatedAt);
|
||||
writer.writeInt(offsets[15], object.width);
|
||||
}
|
||||
|
||||
Asset _assetDeserialize(
|
||||
|
@ -225,10 +237,11 @@ Asset _assetDeserialize(
|
|||
localId: reader.readStringOrNull(offsets[9]),
|
||||
ownerId: reader.readLong(offsets[10]),
|
||||
remoteId: reader.readStringOrNull(offsets[11]),
|
||||
type: _AssettypeValueEnumMap[reader.readByteOrNull(offsets[12])] ??
|
||||
thumbhash: reader.readStringOrNull(offsets[12]),
|
||||
type: _AssettypeValueEnumMap[reader.readByteOrNull(offsets[13])] ??
|
||||
AssetType.other,
|
||||
updatedAt: reader.readDateTime(offsets[13]),
|
||||
width: reader.readIntOrNull(offsets[14]),
|
||||
updatedAt: reader.readDateTime(offsets[14]),
|
||||
width: reader.readIntOrNull(offsets[15]),
|
||||
);
|
||||
return object;
|
||||
}
|
||||
|
@ -265,11 +278,13 @@ P _assetDeserializeProp<P>(
|
|||
case 11:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 12:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 13:
|
||||
return (_AssettypeValueEnumMap[reader.readByteOrNull(offset)] ??
|
||||
AssetType.other) as P;
|
||||
case 13:
|
||||
return (reader.readDateTime(offset)) as P;
|
||||
case 14:
|
||||
return (reader.readDateTime(offset)) as P;
|
||||
case 15:
|
||||
return (reader.readIntOrNull(offset)) as P;
|
||||
default:
|
||||
throw IsarError('Unknown property with id $propertyId');
|
||||
|
@ -1786,6 +1801,152 @@ extension AssetQueryFilter on QueryBuilder<Asset, Asset, QFilterCondition> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterFilterCondition> thumbhashIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
property: r'thumbhash',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterFilterCondition> thumbhashIsNotNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||
property: r'thumbhash',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterFilterCondition> thumbhashEqualTo(
|
||||
String? value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'thumbhash',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterFilterCondition> thumbhashGreaterThan(
|
||||
String? value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
include: include,
|
||||
property: r'thumbhash',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterFilterCondition> thumbhashLessThan(
|
||||
String? value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.lessThan(
|
||||
include: include,
|
||||
property: r'thumbhash',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterFilterCondition> thumbhashBetween(
|
||||
String? lower,
|
||||
String? upper, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.between(
|
||||
property: r'thumbhash',
|
||||
lower: lower,
|
||||
includeLower: includeLower,
|
||||
upper: upper,
|
||||
includeUpper: includeUpper,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterFilterCondition> thumbhashStartsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.startsWith(
|
||||
property: r'thumbhash',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterFilterCondition> thumbhashEndsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.endsWith(
|
||||
property: r'thumbhash',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterFilterCondition> thumbhashContains(
|
||||
String value,
|
||||
{bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.contains(
|
||||
property: r'thumbhash',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterFilterCondition> thumbhashMatches(
|
||||
String pattern,
|
||||
{bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.matches(
|
||||
property: r'thumbhash',
|
||||
wildcard: pattern,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterFilterCondition> thumbhashIsEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'thumbhash',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterFilterCondition> thumbhashIsNotEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
property: r'thumbhash',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterFilterCondition> typeEqualTo(
|
||||
AssetType value) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
|
@ -2110,6 +2271,18 @@ extension AssetQuerySortBy on QueryBuilder<Asset, Asset, QSortBy> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterSortBy> sortByThumbhash() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'thumbhash', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterSortBy> sortByThumbhashDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'thumbhash', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterSortBy> sortByType() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'type', Sort.asc);
|
||||
|
@ -2304,6 +2477,18 @@ extension AssetQuerySortThenBy on QueryBuilder<Asset, Asset, QSortThenBy> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterSortBy> thenByThumbhash() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'thumbhash', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterSortBy> thenByThumbhashDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'thumbhash', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterSortBy> thenByType() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'type', Sort.asc);
|
||||
|
@ -2420,6 +2605,13 @@ extension AssetQueryWhereDistinct on QueryBuilder<Asset, Asset, QDistinct> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QDistinct> distinctByThumbhash(
|
||||
{bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'thumbhash', caseSensitive: caseSensitive);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, Asset, QDistinct> distinctByType() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'type');
|
||||
|
@ -2518,6 +2710,12 @@ extension AssetQueryProperty on QueryBuilder<Asset, Asset, QQueryProperty> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, String?, QQueryOperations> thumbhashProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'thumbhash');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Asset, AssetType, QQueryOperations> typeProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'type');
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||
import 'package:flutter_thumbhash/flutter_thumbhash.dart';
|
||||
import 'package:immich_mobile/shared/models/asset.dart';
|
||||
import 'package:immich_mobile/shared/models/store.dart';
|
||||
import 'package:immich_mobile/utils/image_url_builder.dart';
|
||||
|
@ -86,6 +87,7 @@ class ImmichImage extends StatelessWidget {
|
|||
}
|
||||
final String? token = Store.get(StoreKey.accessToken);
|
||||
final String thumbnailRequestUrl = getThumbnailUrl(asset);
|
||||
|
||||
return CachedNetworkImage(
|
||||
imageUrl: thumbnailRequestUrl,
|
||||
httpHeaders: {"Authorization": "Bearer $token"},
|
||||
|
@ -98,7 +100,14 @@ class ImmichImage extends StatelessWidget {
|
|||
fit: fit,
|
||||
fadeInDuration: const Duration(milliseconds: 250),
|
||||
progressIndicatorBuilder: (context, url, downloadProgress) {
|
||||
if (useGrayBoxPlaceholder) {
|
||||
if (asset.thumbhash != null) {
|
||||
return FittedBox(
|
||||
fit: BoxFit.fill,
|
||||
child: Image(
|
||||
image: ThumbHash.fromBase64(asset.thumbhash!).toImage(),
|
||||
),
|
||||
);
|
||||
} else if (useGrayBoxPlaceholder) {
|
||||
return const DecoratedBox(
|
||||
decoration: BoxDecoration(color: Colors.grey),
|
||||
);
|
||||
|
|
102
mobile/openapi/lib/model/user_response_dto.dart
generated
102
mobile/openapi/lib/model/user_response_dto.dart
generated
|
@ -52,61 +52,64 @@ class UserResponseDto {
|
|||
String oauthId;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is UserResponseDto &&
|
||||
other.id == id &&
|
||||
other.email == email &&
|
||||
other.firstName == firstName &&
|
||||
other.lastName == lastName &&
|
||||
other.storageLabel == storageLabel &&
|
||||
other.profileImagePath == profileImagePath &&
|
||||
other.shouldChangePassword == shouldChangePassword &&
|
||||
other.isAdmin == isAdmin &&
|
||||
other.createdAt == createdAt &&
|
||||
other.deletedAt == deletedAt &&
|
||||
other.updatedAt == updatedAt &&
|
||||
other.oauthId == oauthId;
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is UserResponseDto &&
|
||||
other.id == id &&
|
||||
other.email == email &&
|
||||
other.firstName == firstName &&
|
||||
other.lastName == lastName &&
|
||||
other.storageLabel == storageLabel &&
|
||||
other.profileImagePath == profileImagePath &&
|
||||
other.shouldChangePassword == shouldChangePassword &&
|
||||
other.isAdmin == isAdmin &&
|
||||
other.createdAt == createdAt &&
|
||||
other.deletedAt == deletedAt &&
|
||||
other.updatedAt == updatedAt &&
|
||||
other.oauthId == oauthId;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(id.hashCode) +
|
||||
(email.hashCode) +
|
||||
(firstName.hashCode) +
|
||||
(lastName.hashCode) +
|
||||
(storageLabel == null ? 0 : storageLabel!.hashCode) +
|
||||
(profileImagePath.hashCode) +
|
||||
(shouldChangePassword.hashCode) +
|
||||
(isAdmin.hashCode) +
|
||||
(createdAt.hashCode) +
|
||||
(deletedAt == null ? 0 : deletedAt!.hashCode) +
|
||||
(updatedAt.hashCode) +
|
||||
(oauthId.hashCode);
|
||||
// ignore: unnecessary_parenthesis
|
||||
(id.hashCode) +
|
||||
(email.hashCode) +
|
||||
(firstName.hashCode) +
|
||||
(lastName.hashCode) +
|
||||
(storageLabel == null ? 0 : storageLabel!.hashCode) +
|
||||
(profileImagePath.hashCode) +
|
||||
(shouldChangePassword.hashCode) +
|
||||
(isAdmin.hashCode) +
|
||||
(createdAt.hashCode) +
|
||||
(deletedAt == null ? 0 : deletedAt!.hashCode) +
|
||||
(updatedAt.hashCode) +
|
||||
(oauthId.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'UserResponseDto[id=$id, email=$email, firstName=$firstName, lastName=$lastName, storageLabel=$storageLabel, profileImagePath=$profileImagePath, shouldChangePassword=$shouldChangePassword, isAdmin=$isAdmin, createdAt=$createdAt, deletedAt=$deletedAt, updatedAt=$updatedAt, oauthId=$oauthId]';
|
||||
String toString() =>
|
||||
'UserResponseDto[id=$id, email=$email, firstName=$firstName, lastName=$lastName, storageLabel=$storageLabel, profileImagePath=$profileImagePath, shouldChangePassword=$shouldChangePassword, isAdmin=$isAdmin, createdAt=$createdAt, deletedAt=$deletedAt, updatedAt=$updatedAt, oauthId=$oauthId]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'id'] = this.id;
|
||||
json[r'email'] = this.email;
|
||||
json[r'firstName'] = this.firstName;
|
||||
json[r'lastName'] = this.lastName;
|
||||
json[r'id'] = this.id;
|
||||
json[r'email'] = this.email;
|
||||
json[r'firstName'] = this.firstName;
|
||||
json[r'lastName'] = this.lastName;
|
||||
if (this.storageLabel != null) {
|
||||
json[r'storageLabel'] = this.storageLabel;
|
||||
} else {
|
||||
// json[r'storageLabel'] = null;
|
||||
}
|
||||
json[r'profileImagePath'] = this.profileImagePath;
|
||||
json[r'shouldChangePassword'] = this.shouldChangePassword;
|
||||
json[r'isAdmin'] = this.isAdmin;
|
||||
json[r'createdAt'] = this.createdAt.toUtc().toIso8601String();
|
||||
json[r'profileImagePath'] = this.profileImagePath;
|
||||
json[r'shouldChangePassword'] = this.shouldChangePassword;
|
||||
json[r'isAdmin'] = this.isAdmin;
|
||||
json[r'createdAt'] = this.createdAt.toUtc().toIso8601String();
|
||||
if (this.deletedAt != null) {
|
||||
json[r'deletedAt'] = this.deletedAt!.toUtc().toIso8601String();
|
||||
} else {
|
||||
// json[r'deletedAt'] = null;
|
||||
}
|
||||
json[r'updatedAt'] = this.updatedAt.toUtc().toIso8601String();
|
||||
json[r'oauthId'] = this.oauthId;
|
||||
json[r'updatedAt'] = this.updatedAt.toUtc().toIso8601String();
|
||||
json[r'oauthId'] = this.oauthId;
|
||||
return json;
|
||||
}
|
||||
|
||||
|
@ -122,8 +125,10 @@ class UserResponseDto {
|
|||
// Note 2: this code is stripped in release mode!
|
||||
assert(() {
|
||||
requiredKeys.forEach((key) {
|
||||
assert(json.containsKey(key), 'Required key "UserResponseDto[$key]" is missing from JSON.');
|
||||
assert(json[key] != null, 'Required key "UserResponseDto[$key]" has a null value in JSON.');
|
||||
assert(json.containsKey(key),
|
||||
'Required key "UserResponseDto[$key]" is missing from JSON.');
|
||||
assert(json[key] != null,
|
||||
'Required key "UserResponseDto[$key]" has a null value in JSON.');
|
||||
});
|
||||
return true;
|
||||
}());
|
||||
|
@ -135,7 +140,8 @@ class UserResponseDto {
|
|||
lastName: mapValueOfType<String>(json, r'lastName')!,
|
||||
storageLabel: mapValueOfType<String>(json, r'storageLabel'),
|
||||
profileImagePath: mapValueOfType<String>(json, r'profileImagePath')!,
|
||||
shouldChangePassword: mapValueOfType<bool>(json, r'shouldChangePassword')!,
|
||||
shouldChangePassword:
|
||||
mapValueOfType<bool>(json, r'shouldChangePassword')!,
|
||||
isAdmin: mapValueOfType<bool>(json, r'isAdmin')!,
|
||||
createdAt: mapDateTime(json, r'createdAt', '')!,
|
||||
deletedAt: mapDateTime(json, r'deletedAt', ''),
|
||||
|
@ -146,7 +152,10 @@ class UserResponseDto {
|
|||
return null;
|
||||
}
|
||||
|
||||
static List<UserResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
static List<UserResponseDto> listFromJson(
|
||||
dynamic json, {
|
||||
bool growable = false,
|
||||
}) {
|
||||
final result = <UserResponseDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
|
@ -174,13 +183,19 @@ class UserResponseDto {
|
|||
}
|
||||
|
||||
// maps a json object with a list of UserResponseDto-objects as value to a dart map
|
||||
static Map<String, List<UserResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
static Map<String, List<UserResponseDto>> mapListFromJson(
|
||||
dynamic json, {
|
||||
bool growable = false,
|
||||
}) {
|
||||
final map = <String, List<UserResponseDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = UserResponseDto.listFromJson(entry.value, growable: growable,);
|
||||
map[entry.key] = UserResponseDto.listFromJson(
|
||||
entry.value,
|
||||
growable: growable,
|
||||
);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
|
@ -202,4 +217,3 @@ class UserResponseDto {
|
|||
'oauthId',
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -453,6 +453,14 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_thumbhash:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_thumbhash
|
||||
sha256: "0a21f7fc4ffefe79f93b047780ad7d5af42a0f0a49b9ec5fb94005e6deebe4ad"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.0+1"
|
||||
flutter_udid:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1224,6 +1232,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1"
|
||||
thumbhash:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: thumbhash
|
||||
sha256: "5f6d31c5279ca0b5caa81ec10aae8dcaab098d82cb699ea66ada4ed09c794a37"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.0+1"
|
||||
time:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -47,6 +47,7 @@ dependencies:
|
|||
permission_handler: ^10.2.0
|
||||
device_info_plus: ^8.1.0
|
||||
crypto: ^3.0.3 # TODO remove once native crypto is used on iOS
|
||||
flutter_thumbhash: 0.1.0+1
|
||||
|
||||
openapi:
|
||||
path: openapi
|
||||
|
|
Loading…
Add table
Reference in a new issue