mirror of
				https://github.com/KevinMidboe/immich.git
				synced 2025-10-29 17:40:28 +00:00 
			
		
		
		
	fix(mobile): stack count reset when navigating to library (#4647)
Co-authored-by: shalong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
		
							
								
								
									
										2
									
								
								cli/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								cli/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							| @@ -771,7 +771,7 @@ export interface AssetResponseDto { | ||||
|      * @type {number} | ||||
|      * @memberof AssetResponseDto | ||||
|      */ | ||||
|     'stackCount': number; | ||||
|     'stackCount': number | null; | ||||
|     /** | ||||
|      *  | ||||
|      * @type {string} | ||||
|   | ||||
| @@ -83,7 +83,7 @@ class GalleryViewerPage extends HookConsumerWidget { | ||||
|         navStack.length > 2 && | ||||
|         navStack.elementAt(navStack.length - 2).name == TrashRoute.name; | ||||
|     final stackIndex = useState(-1); | ||||
|     final stack = showStack && currentAsset.stackCount > 0 | ||||
|     final stack = showStack && currentAsset.stackChildrenCount > 0 | ||||
|         ? ref.watch(assetStackStateProvider(currentAsset)) | ||||
|         : <Asset>[]; | ||||
|     final stackElements = showStack ? [currentAsset, ...stack] : <Asset>[]; | ||||
|   | ||||
| @@ -104,16 +104,16 @@ class ThumbnailImage extends StatelessWidget { | ||||
|         right: 5, | ||||
|         child: Row( | ||||
|           children: [ | ||||
|             if (asset.stackCount > 1) | ||||
|             if (asset.stackChildrenCount > 1) | ||||
|               Text( | ||||
|                 "${asset.stackCount}", | ||||
|                 "${asset.stackChildrenCount}", | ||||
|                 style: const TextStyle( | ||||
|                   color: Colors.white, | ||||
|                   fontSize: 10, | ||||
|                   fontWeight: FontWeight.bold, | ||||
|                 ), | ||||
|               ), | ||||
|             if (asset.stackCount > 1) | ||||
|             if (asset.stackChildrenCount > 1) | ||||
|               const SizedBox( | ||||
|                 width: 3, | ||||
|               ), | ||||
| @@ -233,7 +233,7 @@ class ThumbnailImage extends StatelessWidget { | ||||
|               ), | ||||
|             ), | ||||
|           if (!asset.isImage) buildVideoIcon(), | ||||
|           if (asset.isImage && asset.stackCount > 0) buildStackIcon(), | ||||
|           if (asset.isImage && asset.stackChildrenCount > 0) buildStackIcon(), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   | ||||
| @@ -153,7 +153,10 @@ class Asset { | ||||
|  | ||||
|   String? stackParentId; | ||||
|  | ||||
|   int stackCount; | ||||
|   @ignore | ||||
|   int get stackChildrenCount => stackCount ?? 0; | ||||
|  | ||||
|   int? stackCount; | ||||
|  | ||||
|   /// `true` if this [Asset] is present on the device | ||||
|   @ignore | ||||
| @@ -253,7 +256,11 @@ class Asset { | ||||
|         isFavorite != a.isFavorite || | ||||
|         isArchived != a.isArchived || | ||||
|         isTrashed != a.isTrashed || | ||||
|         stackCount != a.stackCount; | ||||
|         // no local stack count or different count from remote | ||||
|         ((stackCount == null && a.stackCount != null) || | ||||
|             (stackCount != null && | ||||
|                 a.stackCount != null && | ||||
|                 stackCount != a.stackCount)); | ||||
|   } | ||||
|  | ||||
|   /// Returns a new [Asset] with values from this and merged & updated with [a] | ||||
| @@ -269,6 +276,7 @@ class Asset { | ||||
|           width: a.width ?? width, | ||||
|           height: a.height ?? height, | ||||
|           exifInfo: a.exifInfo?.copyWith(id: id) ?? exifInfo, | ||||
|           stackCount: a.stackCount ?? stackCount, | ||||
|         ); | ||||
|       } else if (isRemote) { | ||||
|         return _copyWith( | ||||
| @@ -299,7 +307,7 @@ class Asset { | ||||
|           height: a.height, | ||||
|           livePhotoVideoId: a.livePhotoVideoId, | ||||
|           stackParentId: a.stackParentId, | ||||
|           stackCount: a.stackCount, | ||||
|           stackCount: a.stackCount ?? stackCount, | ||||
|           // isFavorite + isArchived are not set by device-only assets | ||||
|           isFavorite: a.isFavorite, | ||||
|           isArchived: a.isArchived, | ||||
|   | ||||
| @@ -250,7 +250,7 @@ Asset _assetDeserialize( | ||||
|     localId: reader.readStringOrNull(offsets[10]), | ||||
|     ownerId: reader.readLong(offsets[11]), | ||||
|     remoteId: reader.readStringOrNull(offsets[12]), | ||||
|     stackCount: reader.readLong(offsets[13]), | ||||
|     stackCount: reader.readLongOrNull(offsets[13]), | ||||
|     stackParentId: reader.readStringOrNull(offsets[14]), | ||||
|     type: _AssettypeValueEnumMap[reader.readByteOrNull(offsets[15])] ?? | ||||
|         AssetType.other, | ||||
| @@ -294,7 +294,7 @@ P _assetDeserializeProp<P>( | ||||
|     case 12: | ||||
|       return (reader.readStringOrNull(offset)) as P; | ||||
|     case 13: | ||||
|       return (reader.readLong(offset)) as P; | ||||
|       return (reader.readLongOrNull(offset)) as P; | ||||
|     case 14: | ||||
|       return (reader.readStringOrNull(offset)) as P; | ||||
|     case 15: | ||||
| @@ -1825,8 +1825,24 @@ extension AssetQueryFilter on QueryBuilder<Asset, Asset, QFilterCondition> { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   QueryBuilder<Asset, Asset, QAfterFilterCondition> stackCountIsNull() { | ||||
|     return QueryBuilder.apply(this, (query) { | ||||
|       return query.addFilterCondition(const FilterCondition.isNull( | ||||
|         property: r'stackCount', | ||||
|       )); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   QueryBuilder<Asset, Asset, QAfterFilterCondition> stackCountIsNotNull() { | ||||
|     return QueryBuilder.apply(this, (query) { | ||||
|       return query.addFilterCondition(const FilterCondition.isNotNull( | ||||
|         property: r'stackCount', | ||||
|       )); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   QueryBuilder<Asset, Asset, QAfterFilterCondition> stackCountEqualTo( | ||||
|       int value) { | ||||
|       int? value) { | ||||
|     return QueryBuilder.apply(this, (query) { | ||||
|       return query.addFilterCondition(FilterCondition.equalTo( | ||||
|         property: r'stackCount', | ||||
| @@ -1836,7 +1852,7 @@ extension AssetQueryFilter on QueryBuilder<Asset, Asset, QFilterCondition> { | ||||
|   } | ||||
|  | ||||
|   QueryBuilder<Asset, Asset, QAfterFilterCondition> stackCountGreaterThan( | ||||
|     int value, { | ||||
|     int? value, { | ||||
|     bool include = false, | ||||
|   }) { | ||||
|     return QueryBuilder.apply(this, (query) { | ||||
| @@ -1849,7 +1865,7 @@ extension AssetQueryFilter on QueryBuilder<Asset, Asset, QFilterCondition> { | ||||
|   } | ||||
|  | ||||
|   QueryBuilder<Asset, Asset, QAfterFilterCondition> stackCountLessThan( | ||||
|     int value, { | ||||
|     int? value, { | ||||
|     bool include = false, | ||||
|   }) { | ||||
|     return QueryBuilder.apply(this, (query) { | ||||
| @@ -1862,8 +1878,8 @@ extension AssetQueryFilter on QueryBuilder<Asset, Asset, QFilterCondition> { | ||||
|   } | ||||
|  | ||||
|   QueryBuilder<Asset, Asset, QAfterFilterCondition> stackCountBetween( | ||||
|     int lower, | ||||
|     int upper, { | ||||
|     int? lower, | ||||
|     int? upper, { | ||||
|     bool includeLower = true, | ||||
|     bool includeUpper = true, | ||||
|   }) { | ||||
| @@ -2854,7 +2870,7 @@ extension AssetQueryProperty on QueryBuilder<Asset, Asset, QQueryProperty> { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   QueryBuilder<Asset, int, QQueryOperations> stackCountProperty() { | ||||
|   QueryBuilder<Asset, int?, QQueryOperations> stackCountProperty() { | ||||
|     return QueryBuilder.apply(this, (query) { | ||||
|       return query.addPropertyName(r'stackCount'); | ||||
|     }); | ||||
|   | ||||
							
								
								
									
										10
									
								
								mobile/openapi/lib/model/asset_response_dto.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										10
									
								
								mobile/openapi/lib/model/asset_response_dto.dart
									
									
									
										generated
									
									
									
								
							| @@ -118,7 +118,7 @@ class AssetResponseDto { | ||||
| 
 | ||||
|   List<AssetResponseDto> stack; | ||||
| 
 | ||||
|   int stackCount; | ||||
|   int? stackCount; | ||||
| 
 | ||||
|   String? stackParentId; | ||||
| 
 | ||||
| @@ -194,7 +194,7 @@ class AssetResponseDto { | ||||
|     (resized.hashCode) + | ||||
|     (smartInfo == null ? 0 : smartInfo!.hashCode) + | ||||
|     (stack.hashCode) + | ||||
|     (stackCount.hashCode) + | ||||
|     (stackCount == null ? 0 : stackCount!.hashCode) + | ||||
|     (stackParentId == null ? 0 : stackParentId!.hashCode) + | ||||
|     (tags.hashCode) + | ||||
|     (thumbhash == null ? 0 : thumbhash!.hashCode) + | ||||
| @@ -248,7 +248,11 @@ class AssetResponseDto { | ||||
|     //  json[r'smartInfo'] = null; | ||||
|     } | ||||
|       json[r'stack'] = this.stack; | ||||
|     if (this.stackCount != null) { | ||||
|       json[r'stackCount'] = this.stackCount; | ||||
|     } else { | ||||
|     //  json[r'stackCount'] = null; | ||||
|     } | ||||
|     if (this.stackParentId != null) { | ||||
|       json[r'stackParentId'] = this.stackParentId; | ||||
|     } else { | ||||
| @@ -299,7 +303,7 @@ class AssetResponseDto { | ||||
|         resized: mapValueOfType<bool>(json, r'resized')!, | ||||
|         smartInfo: SmartInfoResponseDto.fromJson(json[r'smartInfo']), | ||||
|         stack: AssetResponseDto.listFromJson(json[r'stack']), | ||||
|         stackCount: mapValueOfType<int>(json, r'stackCount')!, | ||||
|         stackCount: mapValueOfType<int>(json, r'stackCount'), | ||||
|         stackParentId: mapValueOfType<String>(json, r'stackParentId'), | ||||
|         tags: TagResponseDto.listFromJson(json[r'tags']), | ||||
|         thumbhash: mapValueOfType<String>(json, r'thumbhash'), | ||||
|   | ||||
| @@ -6009,6 +6009,7 @@ | ||||
|             "type": "array" | ||||
|           }, | ||||
|           "stackCount": { | ||||
|             "nullable": true, | ||||
|             "type": "integer" | ||||
|           }, | ||||
|           "stackParentId": { | ||||
|   | ||||
| @@ -45,7 +45,7 @@ export class AssetResponseDto extends SanitizedAssetResponseDto { | ||||
|   stackParentId?: string | null; | ||||
|   stack?: AssetResponseDto[]; | ||||
|   @ApiProperty({ type: 'integer' }) | ||||
|   stackCount!: number; | ||||
|   stackCount!: number | null; | ||||
| } | ||||
|  | ||||
| export type AssetMapOptions = { | ||||
| @@ -102,7 +102,7 @@ export function mapAsset(entity: AssetEntity, options: AssetMapOptions = {}): As | ||||
|     checksum: entity.checksum.toString('base64'), | ||||
|     stackParentId: entity.stackParentId, | ||||
|     stack: withStack ? entity.stack?.map((a) => mapAsset(a, { stripMetadata })) ?? undefined : undefined, | ||||
|     stackCount: entity.stack?.length ?? 0, | ||||
|     stackCount: entity.stack?.length ?? null, | ||||
|     isExternal: entity.isExternal, | ||||
|     isOffline: entity.isOffline, | ||||
|     isReadOnly: entity.isReadOnly, | ||||
|   | ||||
							
								
								
									
										2
									
								
								web/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								web/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							| @@ -771,7 +771,7 @@ export interface AssetResponseDto { | ||||
|      * @type {number} | ||||
|      * @memberof AssetResponseDto | ||||
|      */ | ||||
|     'stackCount': number; | ||||
|     'stackCount': number | null; | ||||
|     /** | ||||
|      *  | ||||
|      * @type {string} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user