0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-01-21 00:52:43 -05:00

Use CachedNetworkImage and separate cache for thumbnails on library page (#509)

* Use CachedNetworkImage and separate cache for thumbnails on library page

* Use caching for shared albums as well

* Introduce cache service
This commit is contained in:
Matthias Rupp 2022-08-21 18:41:36 +02:00 committed by GitHub
parent 3125d04f32
commit 8e4c4c34e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 81 additions and 30 deletions

View file

@ -1,16 +1,25 @@
import 'dart:math';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:immich_mobile/constants/hive_box.dart'; import 'package:immich_mobile/constants/hive_box.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/shared/services/cache.service.dart';
import 'package:immich_mobile/utils/image_url_builder.dart';
import 'package:openapi/api.dart'; import 'package:openapi/api.dart';
import 'package:transparent_image/transparent_image.dart';
class AlbumThumbnailCard extends StatelessWidget { class AlbumThumbnailCard extends StatelessWidget {
const AlbumThumbnailCard({Key? key, required this.album}) : super(key: key); const AlbumThumbnailCard({
Key? key,
required this.album,
required this.cacheService,
}) : super(key: key);
final AlbumResponseDto album; final AlbumResponseDto album;
final CacheService cacheService;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -29,19 +38,19 @@ class AlbumThumbnailCard extends StatelessWidget {
children: [ children: [
ClipRRect( ClipRRect(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
child: FadeInImage( child: CachedNetworkImage(
cacheManager: cacheService.getCache(CacheType.albumThumbnail),
memCacheHeight: max(400, cardSize.toInt() * 3),
width: cardSize, width: cardSize,
height: cardSize, height: cardSize,
fit: BoxFit.cover, fit: BoxFit.cover,
placeholder: MemoryImage(kTransparentImage), fadeInDuration: const Duration(milliseconds: 200),
image: NetworkImage( imageUrl:
'${box.get(serverEndpointKey)}/asset/thumbnail/${album.albumThumbnailAssetId}?format=JPEG', getAlbumThumbnailUrl(album, type: ThumbnailFormat.JPEG),
headers: { httpHeaders: {
"Authorization": "Bearer ${box.get(accessTokenKey)}" "Authorization": "Bearer ${box.get(accessTokenKey)}"
}, },
), cacheKey: "${album.albumThumbnailAssetId}",
fadeInDuration: const Duration(milliseconds: 200),
fadeOutDuration: const Duration(milliseconds: 200),
), ),
), ),
Padding( Padding(

View file

@ -6,6 +6,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/album/providers/album.provider.dart'; import 'package:immich_mobile/modules/album/providers/album.provider.dart';
import 'package:immich_mobile/modules/album/ui/album_thumbnail_card.dart'; import 'package:immich_mobile/modules/album/ui/album_thumbnail_card.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/shared/services/cache.service.dart';
class LibraryPage extends HookConsumerWidget { class LibraryPage extends HookConsumerWidget {
const LibraryPage({Key? key}) : super(key: key); const LibraryPage({Key? key}) : super(key: key);
@ -13,6 +14,7 @@ class LibraryPage extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final albums = ref.watch(albumProvider); final albums = ref.watch(albumProvider);
final cacheService = ref.watch(cacheServiceProvider);
useEffect( useEffect(
() { () {
@ -102,6 +104,7 @@ class LibraryPage extends HookConsumerWidget {
_buildCreateAlbumButton(), _buildCreateAlbumButton(),
for (var album in albums) for (var album in albums)
AlbumThumbnailCard( AlbumThumbnailCard(
cacheService: cacheService,
album: album, album: album,
), ),
], ],

View file

@ -1,4 +1,5 @@
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
@ -8,8 +9,9 @@ import 'package:immich_mobile/constants/hive_box.dart';
import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart'; import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart';
import 'package:immich_mobile/modules/album/ui/sharing_sliver_appbar.dart'; import 'package:immich_mobile/modules/album/ui/sharing_sliver_appbar.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/shared/services/cache.service.dart';
import 'package:immich_mobile/utils/image_url_builder.dart';
import 'package:openapi/api.dart'; import 'package:openapi/api.dart';
import 'package:transparent_image/transparent_image.dart';
class SharingPage extends HookConsumerWidget { class SharingPage extends HookConsumerWidget {
const SharingPage({Key? key}) : super(key: key); const SharingPage({Key? key}) : super(key: key);
@ -19,6 +21,7 @@ class SharingPage extends HookConsumerWidget {
var box = Hive.box(userInfoBox); var box = Hive.box(userInfoBox);
var thumbnailRequestUrl = '${box.get(serverEndpointKey)}/asset/thumbnail'; var thumbnailRequestUrl = '${box.get(serverEndpointKey)}/asset/thumbnail';
final List<AlbumResponseDto> sharedAlbums = ref.watch(sharedAlbumProvider); final List<AlbumResponseDto> sharedAlbums = ref.watch(sharedAlbumProvider);
final CacheService cacheService = ref.watch(cacheServiceProvider);
useEffect( useEffect(
() { () {
@ -32,29 +35,26 @@ class SharingPage extends HookConsumerWidget {
return SliverList( return SliverList(
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) { (BuildContext context, int index) {
String thumbnailUrl = sharedAlbums[index].albumThumbnailAssetId != final album = sharedAlbums[index];
null
? "$thumbnailRequestUrl/${sharedAlbums[index].albumThumbnailAssetId}"
: "https://images.unsplash.com/photo-1612178537253-bccd437b730e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NXx8Ymxhbmt8ZW58MHx8MHx8&auto=format&fit=crop&w=700&q=60";
return ListTile( return ListTile(
contentPadding: contentPadding:
const EdgeInsets.symmetric(vertical: 12, horizontal: 12), const EdgeInsets.symmetric(vertical: 12, horizontal: 12),
leading: ClipRRect( leading: ClipRRect(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
child: FadeInImage( child: CachedNetworkImage(
width: 60, width: 60,
height: 60, height: 60,
memCacheHeight: 200,
fit: BoxFit.cover, fit: BoxFit.cover,
placeholder: MemoryImage(kTransparentImage), cacheManager:
image: NetworkImage( cacheService.getCache(CacheType.sharedAlbumThumbnail),
thumbnailUrl, imageUrl: getAlbumThumbnailUrl(album),
headers: { cacheKey: album.albumThumbnailAssetId,
httpHeaders: {
"Authorization": "Bearer ${box.get(accessTokenKey)}" "Authorization": "Bearer ${box.get(accessTokenKey)}"
}, },
),
fadeInDuration: const Duration(milliseconds: 200), fadeInDuration: const Duration(milliseconds: 200),
fadeOutDuration: const Duration(milliseconds: 200),
), ),
), ),
title: Text( title: Text(

View file

@ -0,0 +1,21 @@
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
enum CacheType {
albumThumbnail,
sharedAlbumThumbnail;
}
final cacheServiceProvider = Provider((_) => CacheService());
class CacheService {
BaseCacheManager getCache(CacheType type) {
return _getDefaultCache(type.name);
}
BaseCacheManager _getDefaultCache(String cacheName) {
return CacheManager(Config(cacheName));
}
}

View file

@ -3,14 +3,31 @@ import 'package:openapi/api.dart';
import '../constants/hive_box.dart'; import '../constants/hive_box.dart';
String getThumbnailUrl(final AssetResponseDto asset, String getThumbnailUrl(
{ThumbnailFormat type = ThumbnailFormat.WEBP}) { final AssetResponseDto asset, {
final box = Hive.box(userInfoBox); ThumbnailFormat type = ThumbnailFormat.WEBP,
}) {
return _getThumbnailUrl(asset.id, type: type);
}
return '${box.get(serverEndpointKey)}/asset/thumbnail/${asset.id}?format=${type.value}'; String getAlbumThumbnailUrl(
final AlbumResponseDto album, {
ThumbnailFormat type = ThumbnailFormat.WEBP,
}) {
if (album.albumThumbnailAssetId == null) {
return '';
}
return _getThumbnailUrl(album.albumThumbnailAssetId!, type: type);
} }
String getImageUrl(final AssetResponseDto asset) { String getImageUrl(final AssetResponseDto asset) {
final box = Hive.box(userInfoBox); final box = Hive.box(userInfoBox);
return '${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}&isThumb=false'; return '${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}&isThumb=false';
} }
String _getThumbnailUrl(final String id,
{ThumbnailFormat type = ThumbnailFormat.WEBP}) {
final box = Hive.box(userInfoBox);
return '${box.get(serverEndpointKey)}/asset/thumbnail/${id}?format=${type.value}';
}

View file

@ -322,7 +322,7 @@ packages:
source: hosted source: hosted
version: "0.6.8" version: "0.6.8"
flutter_cache_manager: flutter_cache_manager:
dependency: transitive dependency: "direct main"
description: description:
name: flutter_cache_manager name: flutter_cache_manager
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"

View file

@ -43,6 +43,7 @@ dependencies:
easy_localization: ^3.0.1 easy_localization: ^3.0.1
share_plus: ^4.0.10 share_plus: ^4.0.10
flutter_displaymode: ^0.4.0 flutter_displaymode: ^0.4.0
flutter_cache_manager: 3.3.0
path: ^1.8.1 path: ^1.8.1
path_provider: ^2.0.11 path_provider: ^2.0.11