mirror of
https://github.com/immich-app/immich.git
synced 2024-11-28 09:33:27 +02:00
fix(mobile): Fixed iOS 16 overflow cache and memory leaked in gallery viewer. (#700)
This commit is contained in:
parent
6b3f8e548d
commit
47b73a5b64
@ -1,5 +1,4 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:photo_view/photo_view.dart';
|
||||
|
||||
@ -58,14 +57,6 @@ class _RemotePhotoViewState extends State<RemotePhotoView> {
|
||||
widget.isZoomedFunction();
|
||||
}
|
||||
|
||||
void _fireStartLoadingEvent() {
|
||||
widget.onLoadingStart();
|
||||
}
|
||||
|
||||
void _fireFinishedLoadingEvent() {
|
||||
widget.onLoadingCompleted();
|
||||
}
|
||||
|
||||
CachedNetworkImageProvider _authorizedImageProvider(
|
||||
String url,
|
||||
String cacheKey,
|
||||
@ -94,12 +85,6 @@ class _RemotePhotoViewState extends State<RemotePhotoView> {
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
if (newStatus != _RemoteImageStatus.full) {
|
||||
_fireStartLoadingEvent();
|
||||
} else {
|
||||
_fireFinishedLoadingEvent();
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_status = newStatus;
|
||||
_imageProvider = provider;
|
||||
@ -147,21 +132,23 @@ class _RemotePhotoViewState extends State<RemotePhotoView> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_loadImages();
|
||||
super.initState();
|
||||
_loadImages();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() async {
|
||||
super.dispose();
|
||||
await thumbnailProvider.evict();
|
||||
await fullProvider.evict();
|
||||
|
||||
if (widget.previewUrl != null) {
|
||||
if (_status == _RemoteImageStatus.full) {
|
||||
await fullProvider.evict();
|
||||
} else if (_status == _RemoteImageStatus.preview) {
|
||||
await previewProvider.evict();
|
||||
} else if (_status == _RemoteImageStatus.thumbnail) {
|
||||
await thumbnailProvider.evict();
|
||||
}
|
||||
|
||||
_imageProvider.evict();
|
||||
await _imageProvider.evict();
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,8 +163,6 @@ class RemotePhotoView extends StatefulWidget {
|
||||
required this.onSwipeDown,
|
||||
required this.onSwipeUp,
|
||||
this.previewUrl,
|
||||
required this.onLoadingCompleted,
|
||||
required this.onLoadingStart,
|
||||
required this.cacheKey,
|
||||
}) : super(key: key);
|
||||
|
||||
@ -185,8 +170,6 @@ class RemotePhotoView extends StatefulWidget {
|
||||
final String imageUrl;
|
||||
final String authToken;
|
||||
final String? previewUrl;
|
||||
final Function onLoadingCompleted;
|
||||
final Function onLoadingStart;
|
||||
final String cacheKey;
|
||||
|
||||
final void Function() onSwipeDown;
|
||||
|
@ -24,11 +24,9 @@ class TopControlAppBar extends ConsumerWidget with PreferredSizeWidget {
|
||||
double iconSize = 18.0;
|
||||
|
||||
return AppBar(
|
||||
// iconTheme: IconThemeData(color: Colors.grey[100]),
|
||||
// actionsIconTheme: IconThemeData(color: Colors.grey[100]),
|
||||
foregroundColor: Colors.grey[100],
|
||||
toolbarHeight: 60,
|
||||
backgroundColor: Colors.black,
|
||||
backgroundColor: Colors.transparent,
|
||||
leading: IconButton(
|
||||
onPressed: () {
|
||||
AutoRouter.of(context).pop();
|
||||
|
@ -121,8 +121,6 @@ class GalleryViewerPage extends HookConsumerWidget {
|
||||
authToken: 'Bearer ${box.get(accessTokenKey)}',
|
||||
isZoomedFunction: isZoomedMethod,
|
||||
isZoomedListener: isZoomedListener,
|
||||
onLoadingCompleted: () => {},
|
||||
onLoadingStart: () => {},
|
||||
asset: assetList[index],
|
||||
heroTag: assetList[index].id,
|
||||
threeStageLoading: threeStageLoading.value,
|
||||
|
@ -18,8 +18,6 @@ class ImageViewerPage extends HookConsumerWidget {
|
||||
final String authToken;
|
||||
final ValueNotifier<bool> isZoomedListener;
|
||||
final void Function() isZoomedFunction;
|
||||
final void Function() onLoadingCompleted;
|
||||
final void Function() onLoadingStart;
|
||||
final bool threeStageLoading;
|
||||
|
||||
ImageViewerPage({
|
||||
@ -29,8 +27,6 @@ class ImageViewerPage extends HookConsumerWidget {
|
||||
required this.authToken,
|
||||
required this.isZoomedFunction,
|
||||
required this.isZoomedListener,
|
||||
required this.onLoadingCompleted,
|
||||
required this.onLoadingStart,
|
||||
required this.threeStageLoading,
|
||||
}) : super(key: key);
|
||||
|
||||
@ -83,8 +79,6 @@ class ImageViewerPage extends HookConsumerWidget {
|
||||
isZoomedListener: isZoomedListener,
|
||||
onSwipeDown: () => AutoRouter.of(context).pop(),
|
||||
onSwipeUp: () => showInfo(),
|
||||
onLoadingCompleted: onLoadingCompleted,
|
||||
onLoadingStart: onLoadingStart,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -26,7 +26,7 @@ class AvailableAlbum {
|
||||
|
||||
String get name => albumEntity.name;
|
||||
|
||||
int get assetCount => albumEntity.assetCount;
|
||||
Future<int> get assetCount => albumEntity.assetCountAsync;
|
||||
|
||||
String get id => albumEntity.id;
|
||||
|
||||
|
@ -183,17 +183,21 @@ class BackupNotifier extends StateNotifier<BackUpState> {
|
||||
for (AssetPathEntity album in albums) {
|
||||
AvailableAlbum availableAlbum = AvailableAlbum(albumEntity: album);
|
||||
|
||||
var assetList =
|
||||
await album.getAssetListRange(start: 0, end: album.assetCount);
|
||||
var assetCountInAlbum = await album.assetCountAsync;
|
||||
if (assetCountInAlbum > 0) {
|
||||
var assetList =
|
||||
await album.getAssetListRange(start: 0, end: assetCountInAlbum);
|
||||
|
||||
if (assetList.isNotEmpty) {
|
||||
var thumbnailAsset = assetList.first;
|
||||
var thumbnailData = await thumbnailAsset
|
||||
.thumbnailDataWithSize(const ThumbnailSize(512, 512));
|
||||
availableAlbum = availableAlbum.copyWith(thumbnailData: thumbnailData);
|
||||
if (assetList.isNotEmpty) {
|
||||
var thumbnailAsset = assetList.first;
|
||||
var thumbnailData = await thumbnailAsset
|
||||
.thumbnailDataWithSize(const ThumbnailSize(512, 512));
|
||||
availableAlbum =
|
||||
availableAlbum.copyWith(thumbnailData: thumbnailData);
|
||||
}
|
||||
|
||||
availableAlbums.add(availableAlbum);
|
||||
}
|
||||
|
||||
availableAlbums.add(availableAlbum);
|
||||
}
|
||||
|
||||
state = state.copyWith(availableAlbums: availableAlbums);
|
||||
@ -296,14 +300,18 @@ class BackupNotifier extends StateNotifier<BackUpState> {
|
||||
Set<AssetEntity> assetsFromExcludedAlbums = {};
|
||||
|
||||
for (var album in state.selectedBackupAlbums) {
|
||||
var assets = await album.albumEntity
|
||||
.getAssetListRange(start: 0, end: album.assetCount);
|
||||
var assets = await album.albumEntity.getAssetListRange(
|
||||
start: 0,
|
||||
end: await album.albumEntity.assetCountAsync,
|
||||
);
|
||||
assetsFromSelectedAlbums.addAll(assets);
|
||||
}
|
||||
|
||||
for (var album in state.excludedBackupAlbums) {
|
||||
var assets = await album.albumEntity
|
||||
.getAssetListRange(start: 0, end: album.assetCount);
|
||||
var assets = await album.albumEntity.getAssetListRange(
|
||||
start: 0,
|
||||
end: await album.albumEntity.assetCountAsync,
|
||||
);
|
||||
assetsFromExcludedAlbums.addAll(assets);
|
||||
}
|
||||
|
||||
@ -353,11 +361,8 @@ class BackupNotifier extends StateNotifier<BackUpState> {
|
||||
final bool isEnabled = await _backgroundService.isBackgroundBackupEnabled();
|
||||
state = state.copyWith(backgroundBackup: isEnabled);
|
||||
if (state.backupProgress != BackUpProgressEnum.inBackground) {
|
||||
await Future.wait([
|
||||
_getBackupAlbumsInfo(),
|
||||
_updateServerInfo(),
|
||||
]);
|
||||
|
||||
await _getBackupAlbumsInfo();
|
||||
await _updateServerInfo();
|
||||
await _updateBackupAssetCount();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -205,15 +203,23 @@ class AlbumInfoCard extends HookConsumerWidget {
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 2.0),
|
||||
child: Text(
|
||||
albumInfo.assetCount.toString() +
|
||||
(albumInfo.isAll
|
||||
? " (${'backup_all'.tr()})"
|
||||
: ""),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
child: FutureBuilder(
|
||||
builder: ((context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
return Text(
|
||||
snapshot.data.toString() +
|
||||
(albumInfo.isAll
|
||||
? " (${'backup_all'.tr()})"
|
||||
: ""),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
);
|
||||
}
|
||||
return const Text("0");
|
||||
}),
|
||||
future: albumInfo.assetCount,
|
||||
),
|
||||
)
|
||||
],
|
||||
|
@ -32,7 +32,7 @@ class ThumbnailImage extends HookConsumerWidget {
|
||||
ref.watch(homePageStateProvider).isMultiSelectEnable;
|
||||
var deviceId = ref.watch(authenticationProvider).deviceId;
|
||||
|
||||
Widget _buildSelectionIcon(AssetResponseDto asset) {
|
||||
Widget buildSelectionIcon(AssetResponseDto asset) {
|
||||
if (selectedAsset.contains(asset)) {
|
||||
return Icon(
|
||||
Icons.check_circle,
|
||||
@ -48,7 +48,6 @@ class ThumbnailImage extends HookConsumerWidget {
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
debugPrint("View ${asset.id}");
|
||||
if (isMultiSelectEnable &&
|
||||
selectedAsset.contains(asset) &&
|
||||
selectedAsset.length == 1) {
|
||||
@ -91,10 +90,12 @@ class ThumbnailImage extends HookConsumerWidget {
|
||||
: const Border(),
|
||||
),
|
||||
child: CachedNetworkImage(
|
||||
cacheKey: asset.id,
|
||||
cacheKey: 'thumbnail-image-${asset.id}',
|
||||
width: 300,
|
||||
height: 300,
|
||||
memCacheHeight: asset.type == AssetTypeEnum.IMAGE ? 250 : 400,
|
||||
memCacheHeight: 200,
|
||||
maxWidthDiskCache: 200,
|
||||
maxHeightDiskCache: 200,
|
||||
fit: BoxFit.cover,
|
||||
imageUrl: thumbnailRequestUrl,
|
||||
httpHeaders: {
|
||||
@ -109,7 +110,9 @@ class ThumbnailImage extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
errorWidget: (context, url, error) {
|
||||
// debugPrint("Error getting thumbnail $url = $error");
|
||||
debugPrint("Error getting thumbnail $url = $error");
|
||||
CachedNetworkImage.evictFromCache(thumbnailRequestUrl);
|
||||
|
||||
return Icon(
|
||||
Icons.image_not_supported_outlined,
|
||||
color: Theme.of(context).primaryColor,
|
||||
@ -122,7 +125,7 @@ class ThumbnailImage extends HookConsumerWidget {
|
||||
padding: const EdgeInsets.all(3.0),
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: _buildSelectionIcon(asset),
|
||||
child: buildSelectionIcon(asset),
|
||||
),
|
||||
),
|
||||
if (showStorageIndicator)
|
||||
|
@ -59,8 +59,6 @@ class _$AppRouter extends RootStackRouter {
|
||||
authToken: args.authToken,
|
||||
isZoomedFunction: args.isZoomedFunction,
|
||||
isZoomedListener: args.isZoomedListener,
|
||||
onLoadingCompleted: args.onLoadingCompleted,
|
||||
onLoadingStart: args.onLoadingStart,
|
||||
threeStageLoading: args.threeStageLoading));
|
||||
},
|
||||
VideoViewerRoute.name: (routeData) {
|
||||
@ -297,8 +295,6 @@ class ImageViewerRoute extends PageRouteInfo<ImageViewerRouteArgs> {
|
||||
required String authToken,
|
||||
required void Function() isZoomedFunction,
|
||||
required ValueNotifier<bool> isZoomedListener,
|
||||
required void Function() onLoadingCompleted,
|
||||
required void Function() onLoadingStart,
|
||||
required bool threeStageLoading})
|
||||
: super(ImageViewerRoute.name,
|
||||
path: '/image-viewer-page',
|
||||
@ -309,8 +305,6 @@ class ImageViewerRoute extends PageRouteInfo<ImageViewerRouteArgs> {
|
||||
authToken: authToken,
|
||||
isZoomedFunction: isZoomedFunction,
|
||||
isZoomedListener: isZoomedListener,
|
||||
onLoadingCompleted: onLoadingCompleted,
|
||||
onLoadingStart: onLoadingStart,
|
||||
threeStageLoading: threeStageLoading));
|
||||
|
||||
static const String name = 'ImageViewerRoute';
|
||||
@ -324,8 +318,6 @@ class ImageViewerRouteArgs {
|
||||
required this.authToken,
|
||||
required this.isZoomedFunction,
|
||||
required this.isZoomedListener,
|
||||
required this.onLoadingCompleted,
|
||||
required this.onLoadingStart,
|
||||
required this.threeStageLoading});
|
||||
|
||||
final Key? key;
|
||||
@ -340,15 +332,11 @@ class ImageViewerRouteArgs {
|
||||
|
||||
final ValueNotifier<bool> isZoomedListener;
|
||||
|
||||
final void Function() onLoadingCompleted;
|
||||
|
||||
final void Function() onLoadingStart;
|
||||
|
||||
final bool threeStageLoading;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ImageViewerRouteArgs{key: $key, heroTag: $heroTag, asset: $asset, authToken: $authToken, isZoomedFunction: $isZoomedFunction, isZoomedListener: $isZoomedListener, onLoadingCompleted: $onLoadingCompleted, onLoadingStart: $onLoadingStart, threeStageLoading: $threeStageLoading}';
|
||||
return 'ImageViewerRouteArgs{key: $key, heroTag: $heroTag, asset: $asset, authToken: $authToken, isZoomedFunction: $isZoomedFunction, isZoomedListener: $isZoomedListener, threeStageLoading: $threeStageLoading}';
|
||||
}
|
||||
}
|
||||
|
||||
|
Binary file not shown.
@ -7,14 +7,14 @@ packages:
|
||||
name: _fe_analyzer_shared
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "38.0.0"
|
||||
version: "47.0.0"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.4.1"
|
||||
version: "4.7.0"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -42,14 +42,14 @@ packages:
|
||||
name: auto_route
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.1"
|
||||
version: "5.0.1"
|
||||
auto_route_generator:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: auto_route_generator
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
version: "5.0.2"
|
||||
badges:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -77,7 +77,7 @@ packages:
|
||||
name: build_config
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "1.1.0"
|
||||
build_daemon:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -98,7 +98,7 @@ packages:
|
||||
name: build_runner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.10"
|
||||
version: "2.2.1"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -162,13 +162,6 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -322,7 +315,7 @@ packages:
|
||||
source: hosted
|
||||
version: "0.6.8"
|
||||
flutter_cache_manager:
|
||||
dependency: "direct main"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_cache_manager
|
||||
url: "https://pub.dartlang.org"
|
||||
@ -461,7 +454,7 @@ packages:
|
||||
name: hive_generator
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
version: "1.1.3"
|
||||
hooks_riverpod:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -503,7 +496,7 @@ packages:
|
||||
name: image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
version: "3.2.0"
|
||||
image_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -783,7 +776,7 @@ packages:
|
||||
name: photo_manager
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0+2"
|
||||
version: "2.2.1"
|
||||
photo_view:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -1139,20 +1132,6 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.1"
|
||||
universal_html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: universal_html
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.8"
|
||||
universal_io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: universal_io
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.4"
|
||||
url_launcher:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -1334,7 +1313,7 @@ packages:
|
||||
name: xml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.4.1"
|
||||
version: "6.1.0"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -11,7 +11,7 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
photo_manager: ^2.0.6
|
||||
photo_manager: ^2.2.1
|
||||
flutter_hooks: ^0.18.0
|
||||
hooks_riverpod: ^2.0.0-dev.0
|
||||
hive: ^2.2.1
|
||||
@ -20,7 +20,7 @@ dependencies:
|
||||
cached_network_image: ^3.2.2
|
||||
percent_indicator: ^4.2.2
|
||||
intl: ^0.17.0
|
||||
auto_route: ^4.0.1
|
||||
auto_route: ^5.0.1
|
||||
exif: ^3.1.1
|
||||
transparent_image: ^2.0.0
|
||||
flutter_launcher_icons: "^0.9.2"
|
||||
@ -43,7 +43,6 @@ dependencies:
|
||||
easy_localization: ^3.0.1
|
||||
share_plus: ^4.0.10
|
||||
flutter_displaymode: ^0.4.0
|
||||
flutter_cache_manager: 3.3.0
|
||||
|
||||
path: ^1.8.1
|
||||
path_provider: ^2.0.11
|
||||
@ -59,8 +58,8 @@ dev_dependencies:
|
||||
sdk: flutter
|
||||
flutter_lints: ^2.0.1
|
||||
hive_generator: ^1.1.2
|
||||
build_runner: ^2.1.7
|
||||
auto_route_generator: ^4.0.0
|
||||
build_runner: ^2.2.1
|
||||
auto_route_generator: ^5.0.2
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
Loading…
Reference in New Issue
Block a user