1
0
mirror of https://github.com/immich-app/immich.git synced 2024-12-21 01:39:59 +02:00
immich/mobile/lib/utils/openapi_extensions.dart
Fynn Petersen-Frey 47f5e4134e
feat(mobile): use cached asset info if unchanged instead of downloading all assets (#1017)
* feat(mobile): use cached asset info if unchanged instead of downloading all assets

This adds an HTTP ETag to the getAllAssets endpoint and client-side support in the app.
If locally cache content is identical to the content on the server, the potentially large list of all assets does not need to be downloaded.

* use ts import instead of require
2022-11-26 10:16:02 -06:00

54 lines
1.9 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart';
import 'package:openapi/api.dart';
import 'tuple.dart';
/// Extension methods to retrieve ETag together with the API call
extension WithETag on AssetApi {
/// Get all AssetEntity belong to the user
///
/// Parameters:
///
/// * [String] eTag:
/// ETag of data already cached on the client
Future<Pair<List<AssetResponseDto>, String?>?> getAllAssetsWithETag({
String? eTag,
}) async {
final response = await getAllAssetsWithHttpInfo(
ifNoneMatch: eTag,
);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
// When a remote server returns no body with a status of 204, we shall not decode it.
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body.isNotEmpty &&
response.statusCode != HttpStatus.noContent) {
final responseBody = await _decodeBodyBytes(response);
final etag = response.headers[HttpHeaders.etagHeader];
final data = (await apiClient.deserializeAsync(
responseBody, 'List<AssetResponseDto>') as List)
.cast<AssetResponseDto>()
.toList();
return Pair(data, etag);
}
return null;
}
}
/// Returns the decoded body as UTF-8 if the given headers indicate an 'application/json'
/// content type. Otherwise, returns the decoded body as decoded by dart:http package.
Future<String> _decodeBodyBytes(Response response) async {
final contentType = response.headers['content-type'];
return contentType != null &&
contentType.toLowerCase().startsWith('application/json')
? response.bodyBytes.isEmpty
? ''
: utf8.decode(response.bodyBytes)
: response.body;
}