Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

⚡️ Improve changes when limited on iOS #615

Merged
merged 3 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
53 changes: 34 additions & 19 deletions lib/src/delegates/asset_picker_builder_delegate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -200,20 +199,24 @@ abstract class AssetPickerBuilderDelegate<Asset, Path> {
/// 权限受限栏的高度
double get permissionLimitedBarHeight => isPermissionLimited ? 75 : 0;

@Deprecated('Use permissionNotifier instead. This will be removed in 10.0.0')
ValueNotifier<PermissionState> get permission => permissionNotifier;

/// Notifier for the current [PermissionState].
/// 当前 [PermissionState] 的监听
late final ValueNotifier<PermissionState> permission =
ValueNotifier<PermissionState>(
late final permissionNotifier = ValueNotifier<PermissionState>(
initialPermission,
);
late final ValueNotifier<bool> permissionOverlayDisplay = ValueNotifier<bool>(
limitedPermissionOverlayPredicate?.call(permission.value) ??
(permission.value == PermissionState.limited),

late final permissionOverlayDisplay = ValueNotifier<bool>(
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);
Expand All @@ -235,7 +238,7 @@ abstract class AssetPickerBuilderDelegate<Asset, Path> {
Singleton.scrollPosition = null;
gridScrollController.dispose();
isSwitchingPath.dispose();
permission.dispose();
permissionNotifier.dispose();
permissionOverlayDisplay.dispose();
}

Expand Down Expand Up @@ -660,7 +663,7 @@ abstract class AssetPickerBuilderDelegate<Asset, Path> {
);

return ValueListenableBuilder2<PermissionState, bool>(
firstNotifier: permission,
firstNotifier: permissionNotifier,
secondNotifier: permissionOverlayDisplay,
builder: (_, PermissionState ps, bool isDisplay, __) {
if (ps.isAuth || !isDisplay) {
Expand Down Expand Up @@ -850,11 +853,12 @@ class DefaultAssetPickerBuilderDelegate

@override
Future<void> 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;
}
Expand All @@ -863,17 +867,22 @@ class DefaultAssetPickerBuilderDelegate
return;
}

assetsChangeCallback?.call(
permission.value,
call,
provider.currentPath?.path,
);
assetsChangeCallback?.call(permission, call, provider.currentPath?.path);

final createIds = <String>[];
final updateIds = <String>[];
final deleteIds = <String>[];
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);
Expand All @@ -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;
}
}
Expand Down Expand Up @@ -943,6 +957,7 @@ class DefaultAssetPickerBuilderDelegate
..totalAssetsCount = assetCount
..getThumbnailFromPath(newPathWrapper);
}
isSwitchingPath.value = false;
}).then(lock.complete).catchError(lock.completeError).whenComplete(() {
onAssetsChangedLock = null;
});
Expand Down Expand Up @@ -1782,7 +1797,7 @@ class DefaultAssetPickerBuilderDelegate
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ValueListenableBuilder<PermissionState>(
valueListenable: permission,
valueListenable: permissionNotifier,
builder: (_, PermissionState ps, Widget? child) => Semantics(
label: '${semanticsTextDelegate.viewingLimitedAssetsTip}, '
'${semanticsTextDelegate.changeAccessibleLimitedAssets}',
Expand Down Expand Up @@ -1960,7 +1975,7 @@ class DefaultAssetPickerBuilderDelegate
}) {
final PathWrapper<AssetPathEntity> 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) {
Expand Down
2 changes: 1 addition & 1 deletion lib/src/widget/asset_picker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class AssetPickerState<Asset, Path> extends State<AssetPicker<Asset, Path>>
if (!mounted) {
return;
}
widget.builder.permission.value = ps;
widget.builder.permissionNotifier.value = ps;
if (ps == PermissionState.limited && Platform.isAndroid) {
_onAssetsUpdated(const MethodCall(''));
}
Expand Down
Loading