diff --git a/example/lib/constants/picker_method.dart b/example/lib/constants/picker_method.dart index c4aa048d..a9e77197 100644 --- a/example/lib/constants/picker_method.dart +++ b/example/lib/constants/picker_method.dart @@ -137,8 +137,8 @@ class PickMethod { selectedAssets: assets, specialItems: [ SpecialItem( - itemPosition: SpecialItemPosition.prepend, - itemBuilder: ( + position: SpecialItemPosition.prepend, + builder: ( BuildContext context, AssetPathEntity? path, int length, @@ -194,8 +194,8 @@ class PickMethod { selectedAssets: assets, specialItems: [ SpecialItem( - itemPosition: SpecialItemPosition.prepend, - itemBuilder: ( + position: SpecialItemPosition.prepend, + builder: ( BuildContext context, AssetPathEntity? path, int length, @@ -309,8 +309,8 @@ class PickMethod { selectedAssets: assets, specialItems: [ SpecialItem( - itemPosition: SpecialItemPosition.prepend, - itemBuilder: ( + position: SpecialItemPosition.prepend, + builder: ( BuildContext context, AssetPathEntity? path, int length, @@ -344,8 +344,8 @@ class PickMethod { selectedAssets: assets, specialItems: [ SpecialItem( - itemPosition: SpecialItemPosition.prepend, - itemBuilder: ( + position: SpecialItemPosition.prepend, + builder: ( BuildContext context, AssetPathEntity? path, int length, @@ -357,8 +357,8 @@ class PickMethod { }, ), SpecialItem( - itemPosition: SpecialItemPosition.append, - itemBuilder: ( + position: SpecialItemPosition.append, + builder: ( BuildContext context, AssetPathEntity? path, int length, diff --git a/example/lib/customs/pickers/directory_file_asset_picker.dart b/example/lib/customs/pickers/directory_file_asset_picker.dart index 5beb33c3..d0f46fd3 100644 --- a/example/lib/customs/pickers/directory_file_asset_picker.dart +++ b/example/lib/customs/pickers/directory_file_asset_picker.dart @@ -703,8 +703,8 @@ class FileAssetPickerBuilder ) { int currentIndex = index; - if (prepandSpecialItems.isNotEmpty) { - currentIndex = index - prepandSpecialItems.length; + if (prependSpecialItems.isNotEmpty) { + currentIndex = index - prependSpecialItems.length; } final File asset = currentAssets.elementAt(currentIndex); diff --git a/example/lib/l10n/gen/app_localizations_zh.dart b/example/lib/l10n/gen/app_localizations_zh.dart index 68cea305..4bef94cb 100644 --- a/example/lib/l10n/gen/app_localizations_zh.dart +++ b/example/lib/l10n/gen/app_localizations_zh.dart @@ -94,11 +94,11 @@ class AppLocalizationsZh extends AppLocalizations { String get pickMethodPrependItemDescription => '网格的靠前位置会添加一个自定义的 widget。'; @override - String get pickMethodMultiSpecialItemsName => '多个特殊item'; + String get pickMethodMultiSpecialItemsName => '多个特殊 widget'; @override String get pickMethodMultiSpecialItemsDescription => - '网格的靠前或靠后位置会添加多个自定义的 widget。'; + '网格的靠前或靠后位置会可以多个自定义的 widget。'; @override String get pickMethodNoPreviewName => '禁止预览'; diff --git a/lib/src/constants/config.dart b/lib/src/constants/config.dart index 54d6864d..b22bfd2d 100644 --- a/lib/src/constants/config.dart +++ b/lib/src/constants/config.dart @@ -4,11 +4,11 @@ import 'package:flutter/material.dart'; import 'package:photo_manager/photo_manager.dart'; -import 'package:wechat_assets_picker/src/models/special_item.dart'; import '../constants/typedefs.dart'; import '../delegates/asset_picker_text_delegate.dart'; import '../delegates/sort_path_delegate.dart'; +import '../models/special_item.dart'; import 'constants.dart'; import 'enums.dart'; @@ -193,5 +193,5 @@ class AssetPickerConfig { /// List of special items. /// 自定义item列表 - final List specialItems; + final List> specialItems; } diff --git a/lib/src/constants/typedefs.dart b/lib/src/constants/typedefs.dart index 0ba94bc6..8fc40470 100644 --- a/lib/src/constants/typedefs.dart +++ b/lib/src/constants/typedefs.dart @@ -9,6 +9,8 @@ import 'package:flutter/widgets.dart'; import 'package:photo_manager/photo_manager.dart' show PermissionState; import 'package:provider/provider.dart'; +import './enums.dart'; + /// Mirroring [ChangeNotifierProvider]. typedef CNP = ChangeNotifierProvider; @@ -76,3 +78,8 @@ typedef AssetsChangeRefreshPredicate = bool Function( MethodCall call, Path? path, ); + +typedef SpecialItemModel = ({ + SpecialItemPosition position, + Widget item, +}); diff --git a/lib/src/delegates/asset_picker_builder_delegate.dart b/lib/src/delegates/asset_picker_builder_delegate.dart index 0b54570d..75daecc9 100644 --- a/lib/src/delegates/asset_picker_builder_delegate.dart +++ b/lib/src/delegates/asset_picker_builder_delegate.dart @@ -57,7 +57,12 @@ abstract class AssetPickerBuilderDelegate { ), themeColor = pickerTheme?.colorScheme.secondary ?? themeColor ?? - defaultThemeColorWeChat { + defaultThemeColorWeChat, + prependSpecialItems = specialItems + .where( + (item) => item.position == SpecialItemPosition.prepend, + ) + .toList() { Singleton.textDelegate = textDelegate ?? assetPickerTextDelegateFromLocale(locale); } @@ -86,7 +91,7 @@ abstract class AssetPickerBuilderDelegate { /// List of special items. /// 自定义item列表 - final List specialItems; + final List> specialItems; /// Indicates the loading status for the builder. /// 指示目前加载的状态 @@ -126,6 +131,10 @@ abstract class AssetPickerBuilderDelegate { final AssetsChangeRefreshPredicate? assetsChangeRefreshPredicate; + /// List of prepend special items. + /// 前置自定义item列表 + final List> prependSpecialItems; + /// [ThemeData] for the picker. /// 选择器使用的主题 ThemeData get theme => pickerTheme ?? AssetPicker.themeData(themeColor); @@ -220,14 +229,6 @@ abstract class AssetPickerBuilderDelegate { AssetPickerTextDelegate get semanticsTextDelegate => Singleton.textDelegate.semanticsTextDelegate; - Iterable get prepandSpecialItems => specialItems.where( - (model) => model.itemPosition == SpecialItemPosition.prepend, - ); - - Iterable get appendSpecialItems => specialItems.where( - (model) => model.itemPosition == SpecialItemPosition.append, - ); - /// Keep a `initState` method to sync with [State]. /// 保留一个 `initState` 方法与 [State] 同步。 @mustCallSuper @@ -759,7 +760,7 @@ class DefaultAssetPickerBuilderDelegate this.specialPickerType, this.keepScrollOffset = false, this.shouldAutoplayPreview = false, - this.specialItems = const [], + super.specialItems = const [], }) { // Add the listener if [keepScrollOffset] is true. if (keepScrollOffset) { @@ -818,11 +819,6 @@ class DefaultAssetPickerBuilderDelegate /// 预览是否自动播放 final bool shouldAutoplayPreview; - /// List of special items. - /// 自定义item列表 - @override - final List specialItems; - /// [Duration] when triggering path switching. /// 切换路径时的动画时长 Duration get switchingPathDuration => const Duration(milliseconds: 300); @@ -1236,29 +1232,23 @@ class DefaultAssetPickerBuilderDelegate builder: (context, wrapper, _) { // First, we need the count of the assets. int totalCount = wrapper?.assetCount ?? 0; - final List< - ({SpecialItemPosition specialItemPosition, Widget specialItem})> - specialItemModels = []; - // If user chose a special item's position, add 1 count. - if (specialItems.isNotEmpty) { - for (final item in specialItems) { - final specialItem = item.itemBuilder?.call( - context, - wrapper?.path, - totalCount, - isPermissionLimited, - ); - if (specialItem != null) { - specialItemModels.add( - ( - specialItemPosition: item.itemPosition, - specialItem: specialItem, - ), + + final List specialItemModels = specialItems + .map((item) { + return ( + position: item.position, + item: item.builder?.call( + context, + wrapper?.path, + totalCount, + isPermissionLimited, + ) ); - totalCount += 1; - } - } - } + }) + .whereType() + .toList(); + + totalCount += specialItemModels.length; if (totalCount == 0 && specialItemModels.isEmpty) { return loadingIndicator(context); @@ -1419,8 +1409,7 @@ class DefaultAssetPickerBuilderDelegate BuildContext context, int index, List currentAssets, { - List<({SpecialItemPosition specialItemPosition, Widget specialItem})> - specialItemModels = const [], + List specialItemModels = const [], }) { final DefaultAssetPickerProvider p = context.read(); @@ -1429,22 +1418,22 @@ class DefaultAssetPickerBuilderDelegate final AssetPathEntity? currentPathEntity = currentWrapper?.path; final prepandSpecialItemModels = specialItemModels.where( - (model) => model.specialItemPosition == SpecialItemPosition.prepend, + (model) => model.position == SpecialItemPosition.prepend, ); final appendSpecialItemModels = specialItemModels.where( - (model) => model.specialItemPosition == SpecialItemPosition.append, + (model) => model.position == SpecialItemPosition.append, ); if (specialItemModels.isNotEmpty) { if (prepandSpecialItemModels.isNotEmpty) { if (index < prepandSpecialItemModels.length) { - return specialItemModels[index].specialItem; + return specialItemModels[index].item; } } if (appendSpecialItemModels.isNotEmpty) { if (index >= length + prepandSpecialItemModels.length) { - return specialItemModels[index - length].specialItem; + return specialItemModels[index - length].item; } } } @@ -1488,8 +1477,8 @@ class DefaultAssetPickerBuilderDelegate } int semanticIndex(int index) { - if (prepandSpecialItems.isNotEmpty) { - return index - prepandSpecialItems.length + 1; + if (prependSpecialItems.isNotEmpty) { + return index - prependSpecialItems.length + 1; } return index; @@ -1584,8 +1573,8 @@ class DefaultAssetPickerBuilderDelegate }) { int index = assets.indexWhere((AssetEntity e) => e.id == id); - if (prepandSpecialItems.isNotEmpty) { - index += prepandSpecialItems.length; + if (prependSpecialItems.isNotEmpty) { + index += prependSpecialItems.length; } index += placeholderCount; return index; @@ -1596,8 +1585,7 @@ class DefaultAssetPickerBuilderDelegate required BuildContext context, required List assets, int placeholderCount = 0, - List<({SpecialItemPosition specialItemPosition, Widget specialItem})> - specialItemModels = const [], + List specialItemModels = const [], }) { final PathWrapper? currentWrapper = context .select?>(