diff --git a/mobile/lib/modules/asset_viewer/ui/remote_photo_view.dart b/mobile/lib/modules/asset_viewer/ui/remote_photo_view.dart index b52ef90026..6e6ecb45da 100644 --- a/mobile/lib/modules/asset_viewer/ui/remote_photo_view.dart +++ b/mobile/lib/modules/asset_viewer/ui/remote_photo_view.dart @@ -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 { widget.isZoomedFunction(); } - void _fireStartLoadingEvent() { - widget.onLoadingStart(); - } - - void _fireFinishedLoadingEvent() { - widget.onLoadingCompleted(); - } - CachedNetworkImageProvider _authorizedImageProvider( String url, String cacheKey, @@ -94,12 +85,6 @@ class _RemotePhotoViewState extends State { if (!mounted) return; - if (newStatus != _RemoteImageStatus.full) { - _fireStartLoadingEvent(); - } else { - _fireFinishedLoadingEvent(); - } - setState(() { _status = newStatus; _imageProvider = provider; @@ -147,21 +132,23 @@ class _RemotePhotoViewState extends State { @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; diff --git a/mobile/lib/modules/asset_viewer/ui/top_control_app_bar.dart b/mobile/lib/modules/asset_viewer/ui/top_control_app_bar.dart index 6fc722e0dc..3c23d9fe8b 100644 --- a/mobile/lib/modules/asset_viewer/ui/top_control_app_bar.dart +++ b/mobile/lib/modules/asset_viewer/ui/top_control_app_bar.dart @@ -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(); diff --git a/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart b/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart index 5b805a48d9..ab7bde1b7a 100644 --- a/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart +++ b/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart @@ -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, diff --git a/mobile/lib/modules/asset_viewer/views/image_viewer_page.dart b/mobile/lib/modules/asset_viewer/views/image_viewer_page.dart index 95a71b1ec8..34d7d1e019 100644 --- a/mobile/lib/modules/asset_viewer/views/image_viewer_page.dart +++ b/mobile/lib/modules/asset_viewer/views/image_viewer_page.dart @@ -18,8 +18,6 @@ class ImageViewerPage extends HookConsumerWidget { final String authToken; final ValueNotifier 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, ), ), ), diff --git a/mobile/lib/modules/backup/models/available_album.model.dart b/mobile/lib/modules/backup/models/available_album.model.dart index 2ddbe1c70b..7469581bf2 100644 --- a/mobile/lib/modules/backup/models/available_album.model.dart +++ b/mobile/lib/modules/backup/models/available_album.model.dart @@ -26,7 +26,7 @@ class AvailableAlbum { String get name => albumEntity.name; - int get assetCount => albumEntity.assetCount; + Future get assetCount => albumEntity.assetCountAsync; String get id => albumEntity.id; diff --git a/mobile/lib/modules/backup/providers/backup.provider.dart b/mobile/lib/modules/backup/providers/backup.provider.dart index e4a43d5a2f..7c628aedcf 100644 --- a/mobile/lib/modules/backup/providers/backup.provider.dart +++ b/mobile/lib/modules/backup/providers/backup.provider.dart @@ -183,17 +183,21 @@ class BackupNotifier extends StateNotifier { 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 { Set 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 { 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(); } } diff --git a/mobile/lib/modules/backup/ui/album_info_card.dart b/mobile/lib/modules/backup/ui/album_info_card.dart index 9350206fb4..51b48f8fe2 100644 --- a/mobile/lib/modules/backup/ui/album_info_card.dart +++ b/mobile/lib/modules/backup/ui/album_info_card.dart @@ -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, ), ) ], diff --git a/mobile/lib/modules/home/ui/thumbnail_image.dart b/mobile/lib/modules/home/ui/thumbnail_image.dart index cc0bc0e868..2b8853222c 100644 --- a/mobile/lib/modules/home/ui/thumbnail_image.dart +++ b/mobile/lib/modules/home/ui/thumbnail_image.dart @@ -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) diff --git a/mobile/lib/routing/router.gr.dart b/mobile/lib/routing/router.gr.dart index dd8faecd0a..4d2132e612 100644 --- a/mobile/lib/routing/router.gr.dart +++ b/mobile/lib/routing/router.gr.dart @@ -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 { required String authToken, required void Function() isZoomedFunction, required ValueNotifier 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 { 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 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}'; } } diff --git a/mobile/openapi/lib/model/asset_response_dto.dart b/mobile/openapi/lib/model/asset_response_dto.dart index 8d76bbe748..21dcce7595 100644 --- a/mobile/openapi/lib/model/asset_response_dto.dart +++ b/mobile/openapi/lib/model/asset_response_dto.dart @@ -177,10 +177,8 @@ class AssetResponseDto { // Note 2: this code is stripped in release mode! // assert(() { // requiredKeys.forEach((key) { - // assert(json.containsKey(key), - // 'Required key "AssetResponseDto[$key]" is missing from JSON.'); - // assert(json[key] != null, - // 'Required key "AssetResponseDto[$key]" has a null value in JSON.'); + // assert(json.containsKey(key), 'Required key "AssetResponseDto[$key]" is missing from JSON.'); + // assert(json[key] != null, 'Required key "AssetResponseDto[$key]" has a null value in JSON.'); // }); // return true; // }()); diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 6ec6780403..b5feac2f85 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -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: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index e59a2d7df5..6923b5a316 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -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