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:
parent
3125d04f32
commit
8e4c4c34e4
7 changed files with 81 additions and 30 deletions
|
@ -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(
|
||||||
|
|
|
@ -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,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -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(
|
||||||
|
|
21
mobile/lib/shared/services/cache.service.dart
Normal file
21
mobile/lib/shared/services/cache.service.dart
Normal 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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}';
|
||||||
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue