From 4f1fcce32765fac163c1eef138747c56c24be5eb Mon Sep 17 00:00:00 2001 From: Alex Li Date: Thu, 15 Aug 2024 22:30:03 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Improve=20changes=20when?= =?UTF-8?q?=20limited=20on=20iOS=20(#615)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + .../asset_picker_builder_delegate.dart | 53 ++++++++++++------- lib/src/widget/asset_picker.dart | 2 +- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88089f25..e8658af7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ that can be found in the LICENSE file. --> ## Unreleased +- Improve changes when limited on iOS. - Use `LocallyAvailableBuilder` in the grid to provide better user awareness. ## 9.2.0 diff --git a/lib/src/delegates/asset_picker_builder_delegate.dart b/lib/src/delegates/asset_picker_builder_delegate.dart index c3461e8f..01acca79 100644 --- a/lib/src/delegates/asset_picker_builder_delegate.dart +++ b/lib/src/delegates/asset_picker_builder_delegate.dart @@ -4,7 +4,6 @@ import 'dart:async'; import 'dart:math' as math; -import 'dart:typed_data' as typed_data; import 'dart:ui' as ui; import 'package:flutter/gestures.dart'; @@ -200,20 +199,24 @@ abstract class AssetPickerBuilderDelegate { /// 权限受限栏的高度 double get permissionLimitedBarHeight => isPermissionLimited ? 75 : 0; + @Deprecated('Use permissionNotifier instead. This will be removed in 10.0.0') + ValueNotifier get permission => permissionNotifier; + /// Notifier for the current [PermissionState]. /// 当前 [PermissionState] 的监听 - late final ValueNotifier permission = - ValueNotifier( + late final permissionNotifier = ValueNotifier( initialPermission, ); - late final ValueNotifier permissionOverlayDisplay = ValueNotifier( - limitedPermissionOverlayPredicate?.call(permission.value) ?? - (permission.value == PermissionState.limited), + + late final permissionOverlayDisplay = ValueNotifier( + limitedPermissionOverlayPredicate?.call(permissionNotifier.value) ?? + (permissionNotifier.value == PermissionState.limited), ); /// Whether the permission is limited currently. /// 当前的权限是否为受限 - bool get isPermissionLimited => permission.value == PermissionState.limited; + bool get isPermissionLimited => + permissionNotifier.value == PermissionState.limited; bool effectiveShouldRevertGrid(BuildContext context) => shouldRevertGrid ?? isAppleOS(context); @@ -235,7 +238,7 @@ abstract class AssetPickerBuilderDelegate { Singleton.scrollPosition = null; gridScrollController.dispose(); isSwitchingPath.dispose(); - permission.dispose(); + permissionNotifier.dispose(); permissionOverlayDisplay.dispose(); } @@ -660,7 +663,7 @@ abstract class AssetPickerBuilderDelegate { ); return ValueListenableBuilder2( - firstNotifier: permission, + firstNotifier: permissionNotifier, secondNotifier: permissionOverlayDisplay, builder: (_, PermissionState ps, bool isDisplay, __) { if (ps.isAuth || !isDisplay) { @@ -850,11 +853,12 @@ class DefaultAssetPickerBuilderDelegate @override Future onAssetsChanged(MethodCall call, StateSetter setState) async { + final permission = permissionNotifier.value; + bool predicate() { - final p = permission.value; final path = provider.currentPath?.path; if (assetsChangeRefreshPredicate != null) { - return assetsChangeRefreshPredicate!(p, call, path); + return assetsChangeRefreshPredicate!(permission, call, path); } return path?.isAll == true; } @@ -863,17 +867,22 @@ class DefaultAssetPickerBuilderDelegate return; } - assetsChangeCallback?.call( - permission.value, - call, - provider.currentPath?.path, - ); + assetsChangeCallback?.call(permission, call, provider.currentPath?.path); final createIds = []; final updateIds = []; final deleteIds = []; + int newCount = 0; + int oldCount = 0; + // Typically for iOS. if (call.arguments case final Map arguments) { + if (arguments['newCount'] case final int count) { + newCount = count; + } + if (arguments['oldCount'] case final int count) { + oldCount = count; + } for (final e in (arguments['create'] as List?) ?? []) { if (e['id'] case final String id) { createIds.add(id); @@ -889,7 +898,12 @@ class DefaultAssetPickerBuilderDelegate deleteIds.add(id); } } - if (createIds.isEmpty && updateIds.isEmpty && deleteIds.isEmpty) { + if (createIds.isEmpty && + updateIds.isEmpty && + deleteIds.isEmpty && + // Updates with limited permission on iOS does not provide any IDs. + // Counting on length changes is not reliable. + (newCount == oldCount && permission != PermissionState.limited)) { return; } } @@ -943,6 +957,7 @@ class DefaultAssetPickerBuilderDelegate ..totalAssetsCount = assetCount ..getThumbnailFromPath(newPathWrapper); } + isSwitchingPath.value = false; }).then(lock.complete).catchError(lock.completeError).whenComplete(() { onAssetsChangedLock = null; }); @@ -1782,7 +1797,7 @@ class DefaultAssetPickerBuilderDelegate mainAxisSize: MainAxisSize.min, children: [ ValueListenableBuilder( - valueListenable: permission, + valueListenable: permissionNotifier, builder: (_, PermissionState ps, Widget? child) => Semantics( label: '${semanticsTextDelegate.viewingLimitedAssetsTip}, ' '${semanticsTextDelegate.changeAccessibleLimitedAssets}', @@ -1960,7 +1975,7 @@ class DefaultAssetPickerBuilderDelegate }) { final PathWrapper wrapper = list[index]; final AssetPathEntity pathEntity = wrapper.path; - final typed_data.Uint8List? data = wrapper.thumbnailData; + final Uint8List? data = wrapper.thumbnailData; Widget builder() { if (data != null) { diff --git a/lib/src/widget/asset_picker.dart b/lib/src/widget/asset_picker.dart index bac0b96a..9e04fca6 100644 --- a/lib/src/widget/asset_picker.dart +++ b/lib/src/widget/asset_picker.dart @@ -125,7 +125,7 @@ class AssetPickerState extends State> if (!mounted) { return; } - widget.builder.permission.value = ps; + widget.builder.permissionNotifier.value = ps; if (ps == PermissionState.limited && Platform.isAndroid) { _onAssetsUpdated(const MethodCall('')); }