Commit 70fd5331d1d73ab79fe2a582e08db677b76157e7

Authored by weixin_45529955
1 parent 18fc1d32

安卓、iOS不动,鸿蒙端用image_picker_ohos 代替 wechat_asset_picker

Showing 79 changed files with 4711 additions and 52 deletions

Too many changes to show.

To preserve performance only 79 of 79+ files are displayed.

@@ -34,6 +34,12 @@ import './dispose.dart'; @@ -34,6 +34,12 @@ import './dispose.dart';
34 // import 'package:photo_manager/photo_manager.dart'; 34 // import 'package:photo_manager/photo_manager.dart';
35 import 'package:flutter_native_image/flutter_native_image.dart'; 35 import 'package:flutter_native_image/flutter_native_image.dart';
36 // import 'package:flutter_image_compress/flutter_image_compress.dart'; 36 // import 'package:flutter_image_compress/flutter_image_compress.dart';
  37 +import 'package:image_picker_ohos/image_picker_ohos.dart';
  38 +import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
  39 +
  40 +class MediaDN {
  41 + File? file;
  42 +}
37 43
38 typedef void OnPickImageCallback( 44 typedef void OnPickImageCallback(
39 double maxWidth, double maxHeight, int quality); 45 double maxWidth, double maxHeight, int quality);
@@ -84,6 +90,8 @@ class _ImgPickerWidgetState extends DisposableState<ImgPickerWidget> { @@ -84,6 +90,8 @@ class _ImgPickerWidgetState extends DisposableState<ImgPickerWidget> {
84 final Storage storage = Storage(); 90 final Storage storage = Storage();
85 // 控制器,可以用于取消任务、获取上述的状态,进度等信息 91 // 控制器,可以用于取消任务、获取上述的状态,进度等信息
86 // PutController putController = PutController(); 92 // PutController putController = PutController();
  93 +
  94 + final ImagePickerPlatform _picker = new ImagePickerOhos();
87 // 当前的任务状态 95 // 当前的任务状态
88 96
89 @override 97 @override
@@ -176,6 +184,182 @@ class _ImgPickerWidgetState extends DisposableState<ImgPickerWidget> { @@ -176,6 +184,182 @@ class _ImgPickerWidgetState extends DisposableState<ImgPickerWidget> {
176 } 184 }
177 } 185 }
178 186
  187 + // void _showPickedSnackBar(BuildContext context, List<XFile> files) {
  188 + // ScaffoldMessenger.of(context).showSnackBar(SnackBar(
  189 + // content: Text('Picked: ${files.map((XFile it) => it.name).join(',')}'),
  190 + // duration: const Duration(seconds: 2),
  191 + // ));
  192 + // }
  193 +
  194 + // Future<void> _displayPickImageDialog(
  195 + // BuildContext context, OnPickImageCallback onPick) async {
  196 + // return showDialog(
  197 + // context: context,
  198 + // builder: (BuildContext context) {
  199 + // return AlertDialog(
  200 + // title: const Text('Add optional parameters'),
  201 + // content: Column(
  202 + // children: <Widget>[
  203 + // TextField(
  204 + // controller: maxWidthController,
  205 + // keyboardType:
  206 + // const TextInputType.numberWithOptions(decimal: true),
  207 + // decoration: const InputDecoration(
  208 + // hintText: 'Enter maxWidth if desired'),
  209 + // ),
  210 + // TextField(
  211 + // controller: maxHeightController,
  212 + // keyboardType:
  213 + // const TextInputType.numberWithOptions(decimal: true),
  214 + // decoration: const InputDecoration(
  215 + // hintText: 'Enter maxHeight if desired'),
  216 + // ),
  217 + // TextField(
  218 + // controller: qualityController,
  219 + // keyboardType: TextInputType.number,
  220 + // decoration: const InputDecoration(
  221 + // hintText: 'Enter quality if desired'),
  222 + // ),
  223 + // ],
  224 + // ),
  225 + // actions: <Widget>[
  226 + // TextButton(
  227 + // child: const Text('CANCEL'),
  228 + // onPressed: () {
  229 + // Navigator.of(context).pop();
  230 + // },
  231 + // ),
  232 + // TextButton(
  233 + // child: const Text('PICK'),
  234 + // onPressed: () {
  235 + // final double? width = maxWidthController.text.isNotEmpty
  236 + // ? double.parse(maxWidthController.text)
  237 + // : null;
  238 + // final double? height = maxHeightController.text.isNotEmpty
  239 + // ? double.parse(maxHeightController.text)
  240 + // : null;
  241 + // final int? quality = qualityController.text.isNotEmpty
  242 + // ? int.parse(qualityController.text)
  243 + // : null;
  244 + // onPick(width, height, quality);
  245 + // Navigator.of(context).pop();
  246 + // }),
  247 + // ],
  248 + // );
  249 + // });
  250 + // }
  251 +
  252 + T? _firstOrNull<T>(List<T> list) {
  253 + return list.isEmpty ? null : list.first;
  254 + }
  255 +
  256 + Future<List<XFile>> _onImageButtonPressed(
  257 + ImageSource source, {
  258 + required BuildContext context,
  259 + bool isMultiImage = false,
  260 + bool isMedia = false,
  261 + bool isVideo = false,
  262 + }) async {
  263 + // if (_controller != null) {
  264 + // await _controller!.setVolume(0.0);
  265 + // }
  266 + if (context.mounted) {
  267 + if (isVideo) {
  268 + List<XFile> temp = [];
  269 + final XFile? file = await _picker.getVideo(
  270 + source: source, maxDuration: const Duration(seconds: 10));
  271 + if (file != null && context.mounted) {
  272 + // _showPickedSnackBar(context, <XFile>[file]);
  273 + temp.add(file as XFile);
  274 + }
  275 + return temp;
  276 + } else if (isMultiImage) {
  277 + double? maxWidth = 300.00;
  278 + double? maxHeight = 500;
  279 + int? quality = 90;
  280 +
  281 + try {
  282 + final ImageOptions imageOptions = ImageOptions(
  283 + maxWidth: maxWidth,
  284 + maxHeight: maxHeight,
  285 + imageQuality: quality,
  286 + );
  287 + final List<XFile> pickedFileList = isMedia
  288 + ? await _picker.getMedia(
  289 + options: MediaOptions(
  290 + allowMultiple: isMultiImage, imageOptions: imageOptions),
  291 + )
  292 + : await _picker.getMultiImageWithOptions(
  293 + options: MultiImagePickerOptions(
  294 + imageOptions: imageOptions,
  295 + ),
  296 + );
  297 +
  298 + if (pickedFileList.isNotEmpty && context.mounted) {
  299 + return pickedFileList;
  300 + } else {
  301 + return [];
  302 + }
  303 + } catch (e) {
  304 + print(e.toString());
  305 + }
  306 + } else if (isMedia) {
  307 + // double? maxWidth = 300.00;
  308 + // double? maxHeight = 500;
  309 + // int? quality = 90;
  310 +
  311 + try {
  312 + final List<XFile> pickedFileList = <XFile>[];
  313 + final XFile? media = _firstOrNull(await _picker.getMedia(
  314 + options: MediaOptions(
  315 + allowMultiple: isMultiImage,
  316 + // imageOptions: ImageOptions(
  317 + // maxWidth: maxWidth,
  318 + // maxHeight: maxHeight,
  319 + // imageQuality: quality,
  320 + // )
  321 + ),
  322 + ));
  323 +
  324 + if (media != null) {
  325 + pickedFileList.add(media);
  326 + print(pickedFileList);
  327 + return pickedFileList;
  328 + }
  329 + } catch (e) {
  330 + print(e.toString());
  331 + }
  332 + } else {
  333 + double? maxWidth = 300.00;
  334 + double? maxHeight = 500;
  335 + int? quality = 90;
  336 +
  337 + try {
  338 + final XFile? pickedFile = await _picker.getImageFromSource(
  339 + source: source,
  340 + options: ImagePickerOptions(
  341 + maxWidth: maxWidth,
  342 + maxHeight: maxHeight,
  343 + imageQuality: quality,
  344 + ),
  345 + );
  346 + List<XFile> temp = [];
  347 + if (pickedFile != null && context.mounted) {
  348 + temp.add(pickedFile as XFile);
  349 + }
  350 +
  351 + print(pickedFile);
  352 + return temp;
  353 +
  354 + // <XFile>[pickedFile]
  355 + } catch (e) {
  356 + print(e);
  357 + }
  358 + }
  359 + }
  360 + return [];
  361 + }
  362 +
179 ///多图片选择 363 ///多图片选择
180 void pickAsset(RequestType type, {List<AssetPathEntity>? pathList}) async { 364 void pickAsset(RequestType type, {List<AssetPathEntity>? pathList}) async {
181 List<UploadImgModel>? temp = []; 365 List<UploadImgModel>? temp = [];
@@ -194,61 +378,40 @@ class _ImgPickerWidgetState extends DisposableState<ImgPickerWidget> { @@ -194,61 +378,40 @@ class _ImgPickerWidgetState extends DisposableState<ImgPickerWidget> {
194 } else if (widget.uploadType == UploadType.RemarkImagesType) { 378 } else if (widget.uploadType == UploadType.RemarkImagesType) {
195 temp = widget.imageList; 379 temp = widget.imageList;
196 } 380 }
197 - List<AssetEntity>? imgList = await AssetPicker.pickAssets(context,  
198 - pickerConfig: AssetPickerConfig(  
199 - maxAssets: widget.maxImageNumber - temp!.length,  
200 - // selectedAssets: assets,  
201 - requestType: type,  
202 - themeColor: MyColours.color_199095));  
203 -  
204 - /// context is required, other params is optional.  
205 - // List<AssetEntity> imgList = await PhotoPicker.pickAsset(  
206 - // // BuildContext required  
207 - // context: context,  
208 -  
209 - // /// The following are optional parameters.  
210 - // themeColor: MyColours.color_199095,  
211 - // // the title color and bottom color  
212 - // textColor: Colors.white,  
213 - // // text color  
214 - // padding: 1.0,  
215 - // // item padding  
216 - // dividerColor: Colors.grey,  
217 - // // divider color  
218 - // disableColor: Colors.grey.shade300,  
219 - // // the check box disable color  
220 - // itemRadio: 0.88,  
221 - // // the content item radio  
222 - // maxSelected: widget.maxImageNumber - temp.length,  
223 - // // max picker image count  
224 - // // provider: I18nProvider.english,  
225 - // provider: I18nProvider.chinese,  
226 - // // i18n provider ,default is chinese. , you can custom I18nProvider or use ENProvider()  
227 - // rowCount: 3,  
228 - // // item row count  
229 - // thumbSize: 150,  
230 - // // preview thumb size , default is 64  
231 - // sortDelegate: SortDelegate.common,  
232 - // // default is common ,or you make custom delegate to sort your gallery  
233 - // checkBoxBuilderDelegate: DefaultCheckBoxBuilderDelegate(  
234 - // activeColor: MyColours.color_353535,  
235 - // unselectedColor: Colors.white,  
236 - // checkColor: MyColours.color_199095,  
237 - // ),  
238 - // // default is DefaultCheckBoxBuilderDelegate ,or you make custom delegate to create checkbox  
239 - // // loadingDelegate: this,  
240 - // // if you want to build custom loading widget,extends LoadingDelegate, [see example/lib/main.dart]  
241 - // badgeDelegate: const DurationBadgeDelegate(),  
242 - // // badgeDelegate to show badge widget  
243 - // pickType: type,  
244 - // photoPathList: pathList,  
245 - // );  
246 - if (imgList == null || imgList.isEmpty) { 381 +
  382 + List<MediaDN>? imgList = [];
  383 + if (Platform.isAndroid || Platform.isIOS) {
  384 + List<AssetEntity>? imagListTemp = await AssetPicker.pickAssets(context,
  385 + pickerConfig: AssetPickerConfig(
  386 + maxAssets: widget.maxImageNumber - temp!.length,
  387 + // selectedAssets: assets,
  388 + requestType: type,
  389 + themeColor: MyColours.color_199095));
  390 + imagListTemp?.forEach((elenemt) async {
  391 + MediaDN mediaDN = MediaDN();
  392 + mediaDN.file = await elenemt.file;
  393 + imgList.add(mediaDN);
  394 + });
  395 + } else if (Platform.isOhos) {
  396 + List<XFile> imagListTemp = await _onImageButtonPressed(
  397 + ImageSource.gallery,
  398 + context: context,
  399 + isMultiImage: true,
  400 + isVideo: false);
  401 +
  402 + imagListTemp.forEach((elenemt) async {
  403 + MediaDN mediaDN = MediaDN();
  404 + mediaDN.file = File(elenemt.path);
  405 + imgList.add(mediaDN);
  406 + });
  407 + }
  408 +
  409 + if (imgList.length == 0 || imgList.isEmpty) {
247 print("No pick item."); 410 print("No pick item.");
248 return; 411 return;
249 } else { 412 } else {
250 for (int i = 0; i < imgList.length; i++) { 413 for (int i = 0; i < imgList.length; i++) {
251 - var file = (await imgList[i].file)!; 414 + var file = (imgList[i].file)!;
252 //从相册选取照片后进行裁剪压缩 415 //从相册选取照片后进行裁剪压缩
253 File yourFile = file; 416 File yourFile = file;
254 Uint8List afterImg = await yourFile.readAsBytes(); 417 Uint8List afterImg = await yourFile.readAsBytes();
@@ -283,7 +446,7 @@ class _ImgPickerWidgetState extends DisposableState<ImgPickerWidget> { @@ -283,7 +446,7 @@ class _ImgPickerWidgetState extends DisposableState<ImgPickerWidget> {
283 if (need) { 446 if (need) {
284 file = File(path); 447 file = File(path);
285 } 448 }
286 - UploadImageUtil().startUpload(context, File(path), temp.length - 1, 449 + UploadImageUtil().startUpload(context, File(path), temp!.length - 1,
287 false, widget.model!, widget.uploadType, 450 false, widget.model!, widget.uploadType,
288 countAll: imgList.length, 451 countAll: imgList.length,
289 callback: widget.callback, 452 callback: widget.callback,
  1 +<!-- Copyright 2019 The FlutterCandies author. All rights reserved.
  2 +Use of this source code is governed by an Apache license
  3 +that can be found in the LICENSE file. -->
  4 +
  5 +# Changelog
  6 +
  7 +> [!IMPORTANT]
  8 +> See the [Migration Guide](guides/migration_guide.md) for the details of breaking changes between versions.
  9 +
  10 +## Unreleased
  11 +
  12 +*None.*
  13 +
  14 +## 9.8.0
  15 +
  16 +> [!NOTE]
  17 +> Be aware of potential minor theme changes since the base theme has taken place in the picker's theme.
  18 +
  19 +**Improvements**
  20 +
  21 +- Improve themes by inheriting the base theme rather than standalone constructors.
  22 +
  23 +**Fixes**
  24 +
  25 +- Enabling using the package on Flutter 3.35.
  26 +
  27 +## 9.7.0
  28 +
  29 +**Improvements**
  30 +
  31 +- Allows specifying the fallback text delegate through `assetPickerTextDelegateFromLocale`.
  32 +
  33 +## 9.6.0
  34 +
  35 +**New features**
  36 +
  37 +- Expose more route settings.
  38 + Users will now be able to control the route settings for the picker and viewer.
  39 +- Add Persian (Farsi) language support. (Thanks to @Ho3einTahan)
  40 +
  41 +**Improvements**
  42 +
  43 +- Improve how `MediaQuery` is being listened.
  44 +- Stop enabling drag to select when `maxAssets == 1`.
  45 +- Extract `DefaultAssetPickerProvider.init`.
  46 +
  47 +**Fixes**
  48 +
  49 +- Fix semantics with the close button.
  50 +- Fix `selectPredicate` not being called when selecting the video asset under the WeChat Moment mode.
  51 +- Manually dispose memory leak objects.
  52 +
  53 +## 9.5.1
  54 +
  55 +**Improvements**
  56 +
  57 +- Allow `extended_image` v10.
  58 +
  59 +## 9.5.0
  60 +
  61 +**New features**
  62 +
  63 +- Support drag to select.
  64 +
  65 +**Fixes**
  66 +
  67 +- Fixes semantics issues.
  68 +
  69 +## 9.4.2
  70 +
  71 +**Improvements**
  72 +
  73 +- Add Traditional Chinese language text delegate. (Thanks to @Gasol)
  74 +- Improves the default sort conditions on Android.
  75 +
  76 +## 9.4.1
  77 +
  78 +**Improvements**
  79 +
  80 +- Improves the default sort conditions.
  81 +
  82 +**Fixes**
  83 +
  84 +- Fixes selecting when reached the max asset limit in the preview.
  85 +
  86 +## 9.4.0
  87 +
  88 +**Improvements**
  89 +
  90 +- Allows `extended_image: ^9.0.0`.
  91 +
  92 +**Fixes**
  93 +
  94 +- Allows assets changing when no path previously.
  95 +
  96 +## 9.3.3
  97 +
  98 +**Fixes**
  99 +
  100 +- Recovers the compatibility with Flutter 3.16.
  101 +
  102 +## 9.3.2
  103 +
  104 +**Improvements**
  105 +
  106 +- Adapt the file type getter from the image provider to get a precise file type in grid.
  107 +- Adds the identifier for grid item's semantics.
  108 +- Improves preview page back button.
  109 +
  110 +## 9.3.1
  111 +
  112 +**Improvements**
  113 +
  114 +- Do not mute the Live Photo during the preview.
  115 +
  116 +**Fixes**
  117 +
  118 +- Fix the GIF indicator's layout.
  119 +- Fix the directionality with the reverted grid item.
  120 +
  121 +## 9.3.0
  122 +
  123 +**New features**
  124 +
  125 +- Add explicit Live Photos indicator for assets.
  126 +
  127 +**Improvements**
  128 +
  129 +- Make Live Photos gesture consistent when scaling and panning.
  130 +- Integrate `LocallyAvailableBuilder` with thumbnail options to improve the thumbnail loading speed.
  131 +- Use `visibility_detector` and scroll observer to improve media playing experiences.
  132 +
  133 +**Fixes**
  134 +
  135 +- Fix the bottom actions bar display conditions.
  136 +
  137 +## 9.2.2
  138 +
  139 +- Uses correct `isOriginal` for the `LocallyAvailableBuilder`.
  140 +
  141 +## 9.2.1
  142 +
  143 +- Improve changes when limited on iOS.
  144 +- Use `LocallyAvailableBuilder` in the grid to provide better user awareness.
  145 +
  146 +## 9.2.0
  147 +
  148 +**New features**
  149 +
  150 +- Introduce `AssetsChangeCallback` and `AssetsChangeRefreshPredicate`
  151 + to help users act according to asset changes.
  152 +- Add `shouldAutoplayPreview` to the picker config.
  153 +
  154 +**Fixes**
  155 +
  156 +- Raise detailed negative range error.
  157 +- Fix viewer confirm button predication.
  158 +- Enlarge GIF gradients.
  159 +- Fix potential paths assets count unexpected merging behaviors.
  160 +
  161 +## 9.1.0
  162 +
  163 +**Improvements**
  164 +
  165 +- Support limited permission displays on Android.
  166 +- Improves the limited overlay padding on Android.
  167 +- Adds permission request lock for the picker state.
  168 +- Speeding up by splitting asset loading into separate steps.
  169 +- Speeding up using `AdvancedCustomFilter` rather than `FilterOptionGroup` by default.
  170 +
  171 +**Fixes**
  172 +
  173 +- Fix reverted index when previewing assets on Android.
  174 +- Requests with the correct options with the picker.
  175 +
  176 +## 9.0.4
  177 +
  178 +**Fixes**
  179 +
  180 +- Fix the app bar of the viewer that is not animating.
  181 +- Fix loading when no assets are in the path.
  182 +- Reset the has more to load flag between path switching.
  183 +
  184 +## 9.0.3
  185 +
  186 +**Fixes**
  187 +
  188 +- Fix index reverting in `viewAsset`.
  189 +
  190 +## 9.0.2
  191 +
  192 +**Fixes**
  193 +
  194 +- Fix the index with bottom items in the preview.
  195 +
  196 +## 9.0.1
  197 +
  198 +**Fixes**
  199 +
  200 +- Fix the current asset in the picker viewer.
  201 +
  202 +**Improvements**
  203 +
  204 +- Improve code formatting.
  205 +
  206 +## 9.0.0
  207 +
  208 +**Breaking changes**
  209 +
  210 +- Migrate to Flutter 3.16, and drop supports for previous Flutter versions.
  211 +- Bump `photo_manager` to v3.x.
  212 +- Export `photo_manager_image_provider`.
  213 +- Integrate `PermissionRequestOption` for callers.
  214 +
  215 +**Improvements**
  216 +
  217 +- Adapt `ThemeData` usages.
  218 +- Use `wechat_picker_library`.
  219 +- Make the first asset count not blocking loads.
  220 +
  221 +**Fixes**
  222 +
  223 +- Fix unhandled child semantics with the app bar title.
  224 +- Fix styles around the app bar and other widgets.
  225 +- Fix previewing selected assets' behavior.
  226 +- Use `PermissionRequestOption` as much as possible.
  227 +- Raise more errors for non-synced paths.
  228 +- Fix the experience with `shouldRevertGrid`.
  229 +
  230 +## 8.8.0
  231 +
  232 +**New features**
  233 +
  234 +- Add Korean language support. (Thanks to @LIMMIHEE)
  235 +
  236 +**Improvements**
  237 +
  238 +- Use `viewAsset` in the preview button.
  239 +
  240 +**Fixes**
  241 +
  242 +- Fix disposed provider throwing error when fetching assets. (#493)
  243 +
  244 +## 8.7.1
  245 +
  246 +**Improvements**
  247 +
  248 +- Improve README docs and add topics for pub.
  249 +
  250 +## 8.7.0
  251 +
  252 +**Breaking changes**
  253 +
  254 +- Migrate to Flutter 3.13, and drop supports for previous Flutter versions.
  255 +
  256 +## 8.6.3
  257 +
  258 +**Improvements**
  259 +
  260 +- Improve `AssetPickerProvider.paths`.
  261 +
  262 +## 8.6.2
  263 +
  264 +**Improvements**
  265 +
  266 +- Add `appBarPreferredSize` in the picker delegate to help with padding calculations.
  267 +- Improve the performance with `MediaQuery` callers.
  268 +
  269 +## 8.6.1
  270 +
  271 +**Improvements**
  272 +
  273 +- Remove `needTitle` for image filter options.
  274 +
  275 +**Fixes**
  276 +
  277 +- Fix hit test when previewing videos.
  278 +
  279 +## 8.6.0
  280 +
  281 +**Breaking changes**
  282 +
  283 +- Use `TargetPlatform` for the `isAppleOS` method in delegates, which relies on a `BuildContext`.
  284 +
  285 +**New features**
  286 +
  287 +- Sync all UI details from WeChat 8.3.x. (#458)
  288 +- Add Turkish language text delegate. (Thanks to @cevheri).
  289 +- Allow to confirm 0 assets if there are selected assets previously. (#461)
  290 +
  291 +**Improvements**
  292 +
  293 +- Silent part of thumbnail request exceptions.
  294 +
  295 +**Fixes**
  296 +
  297 +- Fix semantics interactions for video preview. (#458)
  298 +- Be able to update the items builder page. (#417)
  299 +
  300 +## 8.5.0
  301 +
  302 +**Breaking changes**
  303 +
  304 +- Migrate to Flutter 3.10, and drop supports for previous Flutter versions.
  305 +
  306 +## 8.4.3
  307 +
  308 +**New features**
  309 +
  310 +- Add Vietnamese language text delegate. (Thanks to @nploi).
  311 +
  312 +**Improvements**
  313 +
  314 +- Expand `FilterOptionGroup` to `PMFilter`. (#436)
  315 +
  316 +## 8.4.2
  317 +
  318 +**Fixes**
  319 +
  320 +- Avoid clearing selected assets when disposing the provider. (#428)
  321 +
  322 +## 8.4.1
  323 +
  324 +**Fixes**
  325 +
  326 +- Call `AssetPickerProvider.dispose` when disposing the builder delegate. (#421)
  327 +
  328 +## 8.4.0
  329 +
  330 +**Breaking changes**
  331 +
  332 +- Migrate to Flutter 3.7, and drop supports for previous Flutter versions.
  333 +
  334 +## 8.3.2+1
  335 +
  336 +**Improvements**
  337 +
  338 +- Add more assertions. (#411)
  339 +
  340 +## 8.3.2
  341 +
  342 +**Fixes**
  343 +
  344 +- Use `Completer` and more accurate conditions to avoid duplicate load assets
  345 + when `AssetPickerConfig.pageSize` is smaller than a complete page. (#407)
  346 +
  347 +## 8.3.1+1
  348 +
  349 +**Improvements**
  350 +
  351 +- Fix images and descriptions in `README`s.
  352 +
  353 +## 8.3.1
  354 +
  355 +**New features**
  356 +
  357 +- Add `didUpdateViewer` and `initAnimations` in the `AssetPickerViewerBuilderDelegate`. (#403)
  358 +- Add insta_assets_picker as a custom delegate example. (#403)
  359 +
  360 +## 8.3.0
  361 +
  362 +**New features**
  363 +
  364 +- Add `index` argument to `selectAsset` in the `AssetPickerBuilderDelegate`. (#399)
  365 +
  366 +**Improvements**
  367 +
  368 +- Improve UI details in the `AssetPickerAppBar`. (#400)
  369 +
  370 +## 8.2.0
  371 +
  372 +**New features**
  373 +
  374 +- Allow overrides `viewAsset` in the `AssetPickerBuilderDelegate`. (#391)
  375 +
  376 +**Fixes**
  377 +
  378 +- Correct behaviors when the access is limited on iOS. (#392)
  379 +
  380 +## 8.1.4
  381 +
  382 +**Fixes**
  383 +
  384 +- Fix conditions with the confirm button on iOS. (#376)
  385 +
  386 +## 8.1.3
  387 +
  388 +**Improvements**
  389 +
  390 +- Bump `photo_manager` to explicitly remove the requirements of `requiredLegacyExternalStorage`.
  391 +
  392 +## 8.1.2
  393 +
  394 +**Fixes**
  395 +
  396 +- Fix conditions with the confirm button. (#371)
  397 +
  398 +## 8.1.1
  399 +
  400 +**Fixes**
  401 +
  402 +- Fix conditions with the confirm button. (#367)
  403 +
  404 +## 8.1.0
  405 +
  406 +**New features**
  407 +
  408 +- Upgrade `photo_manager` for Android 13. (#365)
  409 +
  410 +**Improvements**
  411 +
  412 +- Improve `BuildContext` usages to obtain the correct directionality for the assets grid. (#359)
  413 +- Provide a better condition to the confirm button
  414 + to make sure it displays correctly in all cases on iOS/macOS. (#359)
  415 +- Improve `bottomActionBar` in `DefaultAssetPickerBuilderDelegate`. (#359)
  416 +
  417 +**Fixes**
  418 +
  419 +- Fix invalid path sort. (#364)
  420 +
  421 +## 8.0.2
  422 +
  423 +**Improvements**
  424 +
  425 +- Adapt Flutter 3.3. (#354)
  426 +
  427 +## 8.0.1
  428 +
  429 +**Fixes**
  430 +
  431 +- Fix not updated empty flag in `DefaultAssetPickerProvider`. (#353)
  432 +
  433 +## 8.0.0
  434 +
  435 +To know more about breaking changes, see [Migration Guide][].
  436 +
  437 +**New features**
  438 +
  439 +- Introduce `PathWrapper` in delegates to improve the overall loading speed. (#338)
  440 +- Allow using `Key` during picking. (#339)
  441 +- Add `initializeDelayDuration` for `DefaultAssetPickerProvider`. (#341)
  442 +- Prevent race conditions with paths. (#342)
  443 +- Expose `sortPathsByModifiedDate`. (#343)
  444 +
  445 +**Fixes**
  446 +
  447 +- Unify indicator usage to avoid accidental indicator switching. (#344)
  448 +
  449 +## 7.3.2
  450 +
  451 +**Improvements**
  452 +
  453 +- Improve `onChangingSelected` in `AssetPickerViewerBuilderDelegate`. (#332)
  454 +- Fix typo in `README.md`. (#333)
  455 +
  456 +**Fixes**
  457 +
  458 +- Fix behaviors when unselecting all assets in the viewer. (#335)
  459 +
  460 +## 7.3.1
  461 +
  462 +**Improvements**
  463 +
  464 +- Improve selection callers between picker and viewer. (#327)
  465 +
  466 +## 7.3.0
  467 +
  468 +**Breaking changes**
  469 +
  470 +- Migrate to Flutter 3, and drop supports for previous Flutter versions.
  471 +
  472 +## 7.2.0
  473 +
  474 +**New features**
  475 +
  476 +- Separate `AssetPickerDelegate` (#315),
  477 + which provides the ability to override methods within the `AssetPicker`.
  478 +
  479 +**Improvements**
  480 +
  481 +- Improve `specialItemBuilder`. (#314)
  482 +
  483 +## 7.1.2
  484 +
  485 +**Fixes**
  486 +
  487 +- Fix context usages for inherited theme data.
  488 +- Fix unlinked path name builder.
  489 +
  490 +**Improvements**
  491 +
  492 +- Update how paths get updated. (#312)
  493 +- Expose `DefaultAssetPickerProvider.forTest`.
  494 +
  495 +## 7.1.1
  496 +
  497 +**Fixes**
  498 +
  499 +- Fix `selectPredicate` with the viewer. (#307)
  500 +
  501 +## 7.1.0
  502 +
  503 +**New features**
  504 +
  505 +- Add `PathNameBuilder`. (#303)
  506 +- Add `LimitedPermissionOverlayPredicate`. (#287)
  507 +
  508 +## 7.0.5
  509 +
  510 +**Improvements**
  511 +
  512 +- Support compile on the Web. (#273)
  513 +
  514 +## 7.0.4
  515 +
  516 +**Improvements**
  517 +
  518 +- Make all text delegates const.
  519 +
  520 +## 7.0.3
  521 +
  522 +**Fixes**
  523 +
  524 +- Fix the broken semantics on iOS/macOS. (#272)
  525 +
  526 +## 7.0.2
  527 +
  528 +**Fixes**
  529 +
  530 +- Fix wrong conditions judging when obtaining path thumbnails.
  531 +
  532 +## 7.0.1
  533 +
  534 +**Improvements**
  535 +
  536 +- Support semantics with Japanese text delegates. (#266).
  537 +
  538 +**Fixes**
  539 +
  540 +- Obtain the path thumbnail only when the asset is an image or video.
  541 +
  542 +## 7.0.0
  543 +
  544 +To know more about breaking changes, see [Migration Guide][].
  545 +
  546 +**New features**
  547 +
  548 +- Support predictable special item display. (#264)
  549 +- Support Live-Photos display. (#251)
  550 +- Expose `AssetPickerPageRoute` for customization. (#248)
  551 +- Add full semantics support. (#232, #235, #240, #242, #243, #245, #254)
  552 +
  553 +**Improvements**
  554 +
  555 +- Improve scaling with select indicators and numbers.
  556 +- Implement the default light theme. (#234)
  557 +
  558 +**Fixes**
  559 +
  560 +- Fix `LocallyAvailableBuilder` with more edge conditions. (#263)
  561 +- Fix potential "No elements" error with thumbnails.
  562 +
  563 +## 6.3.1
  564 +
  565 +- Improve image type determined when resolving image data.
  566 + This mostly resolved the occasional HEIC loading issue when
  567 + apps are running under the release mode.
  568 +
  569 +## 6.3.0
  570 +
  571 +- Support for Flutter 2.8.0, also drop supports for Flutter below 2.8.0.
  572 +
  573 +## 6.2.4
  574 +
  575 +- Improve audio item layout.
  576 +- Improve workflows.
  577 +- Indicate the path getter more precisely.
  578 +- Improve Arabic text delegate.
  579 +
  580 +## 6.2.3
  581 +
  582 +- Pass through `selectPredicate` to `AssetPickerViewer`. (#211)
  583 +- Bump the `sdk` constraints (since 6.2.1).
  584 +
  585 +## 6.2.2
  586 +
  587 +- Use `.contentUri` for video preview only on Android.
  588 +
  589 +## 6.2.1
  590 +
  591 +- Migrate to `extended_image` 5.x.
  592 +- Use `.contentUri` constructor for `VideoPlayerController`.
  593 +
  594 +## 6.2.0
  595 +
  596 +- Introduce `shouldRevertGrid` to determine whether the assets grid should be reverted.
  597 +- Upgrade `photo_manager` to resolve issues against `AssetEntity`s comparison.
  598 +
  599 +## 6.1.2
  600 +
  601 +- Fix the limited resources refresh issue.
  602 +- Update callers to avoid deprecated usage.
  603 +
  604 +## 6.1.1
  605 +
  606 +- Handle iCloud video more gracefully.
  607 +
  608 +## 6.1.0
  609 +
  610 +- Introduce `selectPredicate` to predicate asset when picking.
  611 +
  612 +## 6.0.6
  613 +
  614 +- Use the correct index reference with `selectedBackdrop`. (#195)
  615 +
  616 +## 6.0.5
  617 +
  618 +- Upgrade dependencies.
  619 +
  620 +## 6.0.4
  621 +
  622 +- Add French language text delegate. (Thanks to @didiosn)
  623 +- Export "Nothing here." as a field to text delegate. (#190)
  624 +- Fix selected backdrop not synced all the time.
  625 +- Improve the instructions for the example.
  626 +
  627 +## 6.0.3
  628 +
  629 +- Fix path entity nullable issues with the asset grid.
  630 +- Fix assets displaying conditions missing with the iOS layout.
  631 +
  632 +## 6.0.2
  633 +
  634 +- Expose `shouldReversePreview` for `AssetPickerViewerBuilderDelegate`.
  635 +
  636 +## 6.0.1
  637 +
  638 +- Improve total count calculation with `AssetPathEntity`. (#187)
  639 +- Obtain `AssetPathEntity.isAll` fix from `photo_manager`.
  640 +- Documents update.
  641 +
  642 +## 6.0.0
  643 +
  644 +**New features**
  645 +
  646 +- Sync all UI details from WeChat 8.0.x.
  647 +- Integrate iCloud progress overview in previews.
  648 +- Change the permission from the app settings when it's limited.
  649 +- Request more assets on iOS when the permission is limited.
  650 +- Fit the assets' grid's layout as the iOS `Photos` app (reverted and started from the bottom).
  651 +- Add Arabic language text delegate.
  652 +- Allow using `AssetPicker` and `AssetPickerViewer` directly with delegates.
  653 +- Add `keepScrollOffset` feature for the `AssetPickerBuilderDelegate`.
  654 +
  655 +**Improvements**
  656 +
  657 +- Items that are being banned from select (reached max assets or type conflict)
  658 + will have a stronger color cover to indicate.
  659 +- The video preview in the [SpecialPickerType.wechatMoment] is completely different from other previews.
  660 +- Grid items have removed the fade builder for more straight feedback after it gets loaded.
  661 +- Better interaction when jumping between previewing assets.
  662 +- Path entities list layout structure performance & structure improved.
  663 +- More precise thumbnail option for iOS.
  664 +- Improve text scale handling. (#177)
  665 +- Reduce font size for a couple of texts.
  666 +
  667 +To know more about breaking changes, see [Migration Guide][].
  668 +
  669 +## 5.5.8
  670 +
  671 +- Fix the viewer's select button issue with WeChat Moment on Android.
  672 +
  673 +## 5.5.7
  674 +
  675 +- Make `switchPath` method in `AssetPickerProvider` async.
  676 +
  677 +## 5.5.6
  678 +
  679 +- Add Japanese language text delegate. (Thanks to @KosukeSaigusa)
  680 +- Fix video judge condition with WeChat Moment mode.
  681 +- Fix the wrong position for the confirm button on iOS with WeChat Moment mode.
  682 +
  683 +## 5.5.5
  684 +
  685 +- Migrate permissions check to the new API in `photo_manager`.
  686 +
  687 +## 5.5.4
  688 +
  689 +- Fix assets reduced under the WeChat Moment mode when previewing.
  690 +
  691 +## 5.5.3+1
  692 +
  693 +- Fix static analysis issue.
  694 +
  695 +## 5.5.3
  696 +
  697 +- Use `SystemUiOverlayStyle` from the provided theme first.
  698 +
  699 +## 5.5.2
  700 +
  701 +- Add German language text delegate. (Thanks to @Letalus)
  702 +- Add Russian language text delegate. (Thanks to @greymag)
  703 +
  704 +## 5.5.1
  705 +
  706 +- Implement `RenderToggleable` to support other channels of flutter (2.1.x - 2.3.x). (Thanks to @Letalus)
  707 +
  708 +## 5.5.0
  709 +
  710 +- Add `findChildIndexBuilder` to indicate grid find reusable `RenderObject`.
  711 +- Fix the padding issue for the assets' grid.
  712 +
  713 +## 5.4.3
  714 +
  715 +- Fix the missing `ScrollController` in the scroll view.
  716 +
  717 +## 5.4.2
  718 +
  719 +- Split `AssetGridItemBuidler` to solve the rebuild issue.
  720 +- Fix the GIF indicator stretched issue.
  721 +
  722 +## 5.4.1
  723 +
  724 +- Export `AssetPickerPageRoute`.
  725 +
  726 +## 5.4.0+1
  727 +
  728 +- Fix the format that pub.dev suggests.
  729 +
  730 +## 5.4.0
  731 +
  732 +- Fully support RTL languages.
  733 +- Add control for root navigator.
  734 +- Improve `AssetEntityImageProvider`'s constructor and decode.
  735 +- Grab the iOS/macOS thumbnail's size fix from `photo_manager`.
  736 +
  737 +## 5.3.0
  738 +
  739 +- Add `gridThumbSize` to control thumbnails in the select grid.
  740 +- Applies a further fix to the WeChat Moment video preview.
  741 +- Fix unlimited assets choose in preview mode.
  742 +
  743 +## 5.2.1
  744 +
  745 +- Fix the WeChat Moment preview issue.
  746 +
  747 +## 5.2.0
  748 +
  749 +- Add `SpecialPickerType.noPreview` to disable the preview when picking. (Thanks to @yanivshaked)
  750 +
  751 +## 5.1.4
  752 +
  753 +- Add Hebrew language text delegate. (Thanks to @yanivshaked)
  754 +- Fix the slide page route issue when integrated with the `get` package.
  755 +
  756 +## 5.1.3
  757 +
  758 +- Fix not synced issue when the picker is under single pick mode.
  759 +
  760 +## 5.1.2
  761 +
  762 +- Fix selected assets not syncing between thumbnail preview mode and grid view.
  763 +- Fix the wrong index displays in thumbnail preview mode.
  764 +- Dependencies upgrade roll.
  765 +
  766 +## 5.1.1
  767 +
  768 +- Integrate `lastModified` to sort path entities by default.
  769 +
  770 +## 5.1.0
  771 +
  772 +- Reset to the top for the asset grid view after switching paths.
  773 +- Add the ability to select assets in any position of the picker.
  774 +- Implement mime type for image type judgment.
  775 +- Fix the disappeared GIFs indicator.
  776 +
  777 +## 5.0.5
  778 +
  779 +- Fix force cast null type issue with WeChat moment special pick type.
  780 +- Improve the app bar's type definition.
  781 +
  782 +## 5.0.4
  783 +
  784 +- Fix path thumb data's display issue.
  785 +- Fix the default preview thumb size issue with the image preview builder.
  786 +
  787 +## 5.0.3
  788 +
  789 +- Remove required annotation for selected assets.
  790 +
  791 +## 5.0.2
  792 +
  793 +- Fix the wrong viewer provider state.
  794 +- Enhance page stream controller sink close.
  795 +- Fix `dartdoc` generate issue for pub.
  796 +
  797 +## 5.0.1
  798 +
  799 +- Fix the video indicator layout issue.
  800 +- Prevent video selection in WeChat moment mode for edge cases.
  801 +- Pickup fixes from `photo_manager`.
  802 +
  803 +## 5.0.0
  804 +
  805 +- Add the ability to show the special item when the device has no assets.
  806 +- Allow users to build their own picker with custom asset types. (See example for custom delegate.)
  807 +- Slightly reduce performance consumption with layout.
  808 +
  809 +**Breaking changes**
  810 +
  811 +- Migrate to non-nullable by default.
  812 +- `CustomItemBuilder` -> `SpecialItemBuilder`, `CustomItemPosition` -> `SpecialItemPosition`.
  813 +- Abstract `AssetPickerBuilderDelegate<A, P>`, `AssetPickerViewerBuilderDelegate<A, P>`,
  814 + `AssetPickerProvider<A, P>`, and minify the `AssetPickerViewerProvider<A>`. Support custom types by generic type.
  815 +- The `assets` param in `AssetPickerViewer.pushToViewer` is now `previewAssets`.
  816 +
  817 +## 4.2.2
  818 +
  819 +- Suppress deprecated usage for example.
  820 +- Improve code format with dart format.
  821 +- Raise the dependencies version.
  822 +
  823 +## 4.2.1
  824 +
  825 +- Fix arguments judging condition with preview thumb size.
  826 +- Remove common exports and split out constants.
  827 +
  828 +## 4.2.0
  829 +
  830 +- Add `previewThumbSize` for the viewer.
  831 +
  832 +## 4.1.0+4
  833 +
  834 +- Upgrade `extended_image`.
  835 +
  836 +## 4.1.0+3
  837 +
  838 +- Make widgets constant.
  839 +- Remove system UI overlays update.
  840 +- Migrate files to compatible with Flutter `1.20.0`.
  841 +- Sync analysis options.
  842 +
  843 +## 4.1.0+2
  844 +
  845 +- Ignore size constraints for image assets.
  846 +- Format code using `dartfmt`.
  847 +- Upgrade `photo_manager`.
  848 +
  849 +## 4.1.0+1
  850 +
  851 +- Adjust AppleOS layout.
  852 +
  853 +## 4.1.0
  854 +
  855 +- Add a backdrop widget in the picker, which makes the picker more like the one in WeChat.
  856 +
  857 +## 4.0.0
  858 +
  859 +- Drop `asset_audio_player`.
  860 +- Experimenting status bar hidden on iOS.
  861 +- Remove the video player listener before pausing.
  862 +
  863 +**Breaking changes**
  864 +
  865 +- `TextDelegate` -> `AssetsPickerTextDelegate`.
  866 +
  867 +## 3.0.0+1
  868 +
  869 +- Constraint dependencies version.
  870 +
  871 +## 3.0.0
  872 +
  873 +- Add `FilterOptionGroup`. (#41)
  874 +- Add `SpecialPickerType`. (#37)
  875 +- Add custom item build mode. (#39)
  876 +
  877 +## 2.2.1
  878 +
  879 +- Introduce `ColorScheme` for theme details. (#32)
  880 +- Enhance RTL compatibility.
  881 +- Enlarge select indicator's size. (#33)
  882 +
  883 +## 2.2.0+2
  884 +
  885 +- Remove path entity properties refresh.
  886 +
  887 +## 2.2.0+1
  888 +
  889 +- Fix the preview widget for audio assets in the picker viewer.
  890 +
  891 +## 2.2.0
  892 +
  893 +- A brand-new example.
  894 +- Add `SortPathDelegate`.
  895 +- Using `ZoomPageTransition` for viewers.
  896 +- Slightly add padding to the viewer's assets list view.
  897 +- Migrate elevation and color to material rendering.
  898 +- Request thumb only when the request type is not audio.
  899 +- Force request title for audio type asset.
  900 +- Expose `AssetType` enum.
  901 +- Fix the issue with the request type.
  902 +
  903 +## 2.1.0
  904 +
  905 +- Add present English text delegate.
  906 +- Refactored theme constructor and getter with theme capability. (#22)
  907 +- Update color scheme usage for the assets grid. (#23)
  908 +- Update picker viewer style for Apple OS.
  909 +- Fix the bottom bar disappearing on Apple OS when it's single asset mode.
  910 +
  911 +## 2.0.2
  912 +
  913 +- Fix audio paused accidentally when the app is launching on Android. (#18)
  914 +
  915 +## 2.0.1
  916 +
  917 +- Expose observe register methods.
  918 +
  919 +## 2.0.0
  920 +
  921 +- Support audio assets.
  922 +- Support single asset mode.
  923 +- Enlarge the preview button's detector area size.
  924 +- Fix wrong properties' usage causing infinite build when the page reaches the end.
  925 +
  926 +**Breaking changes**
  927 +
  928 +- `videoIndicatorBuilder` -> `durationIndicatorBuilder`.
  929 +
  930 +## 1.7.0
  931 +
  932 +- Hide detail display when the video starts to play.
  933 +- Switch to `ExtendedImageGesturePageView`. (#16)
  934 +- Add full theme support.
  935 +- Add macOS support.
  936 +- Add delay for the first init method to prevent stuck in page routing. (#13)
  937 +- Update widgets style on iOS. (#14)
  938 +- Fix the state of the example not updated after the result was returned without the input method activated.
  939 +
  940 +## 1.6.0
  941 +
  942 +- Support HEIC/HEIF image type.
  943 +
  944 +## 1.5.0+1
  945 +
  946 +- Upgrade `photo_manager` to `0.5.1`.
  947 +- Replace deprecate `TextTheme.title` API usage.
  948 +- Document (`dartdoc`) update.
  949 +
  950 +## 1.5.0
  951 +
  952 +- Bumping flutter SDK minimum version to `1.17.0`.
  953 +- Declare API stability and compatibility with 1.0.0
  954 + ( more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0 ).
  955 +
  956 +## 1.4.1
  957 +
  958 +- Remove the loading indicator for the image widget.
  959 +- Refactor the video page's initialization for ratio update.
  960 +- Using constants to store text delegate.
  961 +- Add error catching for main methods.
  962 +- Update text delegate management.
  963 +
  964 +## 1.4.0+1
  965 +
  966 +- Fix call on null with `currentlySelectedAssets`.
  967 +
  968 +## 1.4.0
  969 +
  970 +- Support paging assets load.
  971 +- Fix selected assets not synced with the picker provider.
  972 +- Bump `photo_manager` to `0.5.1-dev.5`
  973 +
  974 +## 1.3.2
  975 +
  976 +- Expose page transition curve and duration to a static method.
  977 +- Fix theme color not passed to a static method.
  978 +
  979 +## 1.3.1+1
  980 +
  981 +- Fix the `pageBuilder` null issue.
  982 +
  983 +## 1.3.1
  984 +
  985 +- Add upwards slide page transition.
  986 +- Add padding to the bottom action bar in the picker.
  987 +
  988 +## 1.3.0
  989 +
  990 +- Add iOS style.
  991 +- Add cancel field to text delegate.
  992 +- `Set` -> `List`.
  993 +
  994 +## 1.2.1
  995 +
  996 +- Fix the missing aspect ratio for the video player.
  997 +- Using common request type in example.
  998 +
  999 +## 1.2.0
  1000 +
  1001 +- Add text delegate support. (Also with i18n support using delegate).
  1002 +
  1003 +## 1.1.0
  1004 +
  1005 +- Support video assets. You can use `requestType` to select video or video+image.
  1006 +- Hide system ui overlays according to flag and system.
  1007 +- Update the GIF indicator and add a video indicator.
  1008 +
  1009 +## 1.0.0
  1010 +
  1011 +- Initial release.
  1012 +
  1013 +[Migration Guide]: guides/migration_guide.md
  1 + Apache License
  2 + Version 2.0, January 2004
  3 + http://www.apache.org/licenses/
  4 +
  5 + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
  6 +
  7 + 1. Definitions.
  8 +
  9 + "License" shall mean the terms and conditions for use, reproduction,
  10 + and distribution as defined by Sections 1 through 9 of this document.
  11 +
  12 + "Licensor" shall mean the copyright owner or entity authorized by
  13 + the copyright owner that is granting the License.
  14 +
  15 + "Legal Entity" shall mean the union of the acting entity and all
  16 + other entities that control, are controlled by, or are under common
  17 + control with that entity. For the purposes of this definition,
  18 + "control" means (i) the power, direct or indirect, to cause the
  19 + direction or management of such entity, whether by contract or
  20 + otherwise, or (ii) ownership of fifty percent (50%) or more of the
  21 + outstanding shares, or (iii) beneficial ownership of such entity.
  22 +
  23 + "You" (or "Your") shall mean an individual or Legal Entity
  24 + exercising permissions granted by this License.
  25 +
  26 + "Source" form shall mean the preferred form for making modifications,
  27 + including but not limited to software source code, documentation
  28 + source, and configuration files.
  29 +
  30 + "Object" form shall mean any form resulting from mechanical
  31 + transformation or translation of a Source form, including but
  32 + not limited to compiled object code, generated documentation,
  33 + and conversions to other media types.
  34 +
  35 + "Work" shall mean the work of authorship, whether in Source or
  36 + Object form, made available under the License, as indicated by a
  37 + copyright notice that is included in or attached to the work
  38 + (an example is provided in the Appendix below).
  39 +
  40 + "Derivative Works" shall mean any work, whether in Source or Object
  41 + form, that is based on (or derived from) the Work and for which the
  42 + editorial revisions, annotations, elaborations, or other modifications
  43 + represent, as a whole, an original work of authorship. For the purposes
  44 + of this License, Derivative Works shall not include works that remain
  45 + separable from, or merely link (or bind by name) to the interfaces of,
  46 + the Work and Derivative Works thereof.
  47 +
  48 + "Contribution" shall mean any work of authorship, including
  49 + the original version of the Work and any modifications or additions
  50 + to that Work or Derivative Works thereof, that is intentionally
  51 + submitted to Licensor for inclusion in the Work by the copyright owner
  52 + or by an individual or Legal Entity authorized to submit on behalf of
  53 + the copyright owner. For the purposes of this definition, "submitted"
  54 + means any form of electronic, verbal, or written communication sent
  55 + to the Licensor or its representatives, including but not limited to
  56 + communication on electronic mailing lists, source code control systems,
  57 + and issue tracking systems that are managed by, or on behalf of, the
  58 + Licensor for the purpose of discussing and improving the Work, but
  59 + excluding communication that is conspicuously marked or otherwise
  60 + designated in writing by the copyright owner as "Not a Contribution."
  61 +
  62 + "Contributor" shall mean Licensor and any individual or Legal Entity
  63 + on behalf of whom a Contribution has been received by Licensor and
  64 + subsequently incorporated within the Work.
  65 +
  66 + 2. Grant of Copyright License. Subject to the terms and conditions of
  67 + this License, each Contributor hereby grants to You a perpetual,
  68 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable
  69 + copyright license to reproduce, prepare Derivative Works of,
  70 + publicly display, publicly perform, sublicense, and distribute the
  71 + Work and such Derivative Works in Source or Object form.
  72 +
  73 + 3. Grant of Patent License. Subject to the terms and conditions of
  74 + this License, each Contributor hereby grants to You a perpetual,
  75 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable
  76 + (except as stated in this section) patent license to make, have made,
  77 + use, offer to sell, sell, import, and otherwise transfer the Work,
  78 + where such license applies only to those patent claims licensable
  79 + by such Contributor that are necessarily infringed by their
  80 + Contribution(s) alone or by combination of their Contribution(s)
  81 + with the Work to which such Contribution(s) was submitted. If You
  82 + institute patent litigation against any entity (including a
  83 + cross-claim or counterclaim in a lawsuit) alleging that the Work
  84 + or a Contribution incorporated within the Work constitutes direct
  85 + or contributory patent infringement, then any patent licenses
  86 + granted to You under this License for that Work shall terminate
  87 + as of the date such litigation is filed.
  88 +
  89 + 4. Redistribution. You may reproduce and distribute copies of the
  90 + Work or Derivative Works thereof in any medium, with or without
  91 + modifications, and in Source or Object form, provided that You
  92 + meet the following conditions:
  93 +
  94 + (a) You must give any other recipients of the Work or
  95 + Derivative Works a copy of this License; and
  96 +
  97 + (b) You must cause any modified files to carry prominent notices
  98 + stating that You changed the files; and
  99 +
  100 + (c) You must retain, in the Source form of any Derivative Works
  101 + that You distribute, all copyright, patent, trademark, and
  102 + attribution notices from the Source form of the Work,
  103 + excluding those notices that do not pertain to any part of
  104 + the Derivative Works; and
  105 +
  106 + (d) If the Work includes a "NOTICE" text file as part of its
  107 + distribution, then any Derivative Works that You distribute must
  108 + include a readable copy of the attribution notices contained
  109 + within such NOTICE file, excluding those notices that do not
  110 + pertain to any part of the Derivative Works, in at least one
  111 + of the following places: within a NOTICE text file distributed
  112 + as part of the Derivative Works; within the Source form or
  113 + documentation, if provided along with the Derivative Works; or,
  114 + within a display generated by the Derivative Works, if and
  115 + wherever such third-party notices normally appear. The contents
  116 + of the NOTICE file are for informational purposes only and
  117 + do not modify the License. You may add Your own attribution
  118 + notices within Derivative Works that You distribute, alongside
  119 + or as an addendum to the NOTICE text from the Work, provided
  120 + that such additional attribution notices cannot be construed
  121 + as modifying the License.
  122 +
  123 + You may add Your own copyright statement to Your modifications and
  124 + may provide additional or different license terms and conditions
  125 + for use, reproduction, or distribution of Your modifications, or
  126 + for any such Derivative Works as a whole, provided Your use,
  127 + reproduction, and distribution of the Work otherwise complies with
  128 + the conditions stated in this License.
  129 +
  130 + 5. Submission of Contributions. Unless You explicitly state otherwise,
  131 + any Contribution intentionally submitted for inclusion in the Work
  132 + by You to the Licensor shall be under the terms and conditions of
  133 + this License, without any additional terms or conditions.
  134 + Notwithstanding the above, nothing herein shall supersede or modify
  135 + the terms of any separate license agreement you may have executed
  136 + with Licensor regarding such Contributions.
  137 +
  138 + 6. Trademarks. This License does not grant permission to use the trade
  139 + names, trademarks, service marks, or product names of the Licensor,
  140 + except as required for reasonable and customary use in describing the
  141 + origin of the Work and reproducing the content of the NOTICE file.
  142 +
  143 + 7. Disclaimer of Warranty. Unless required by applicable law or
  144 + agreed to in writing, Licensor provides the Work (and each
  145 + Contributor provides its Contributions) on an "AS IS" BASIS,
  146 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  147 + implied, including, without limitation, any warranties or conditions
  148 + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
  149 + PARTICULAR PURPOSE. You are solely responsible for determining the
  150 + appropriateness of using or redistributing the Work and assume any
  151 + risks associated with Your exercise of permissions under this License.
  152 +
  153 + 8. Limitation of Liability. In no event and under no legal theory,
  154 + whether in tort (including negligence), contract, or otherwise,
  155 + unless required by applicable law (such as deliberate and grossly
  156 + negligent acts) or agreed to in writing, shall any Contributor be
  157 + liable to You for damages, including any direct, indirect, special,
  158 + incidental, or consequential damages of any character arising as a
  159 + result of this License or out of the use or inability to use the
  160 + Work (including but not limited to damages for loss of goodwill,
  161 + work stoppage, computer failure or malfunction, or any and all
  162 + other commercial damages or losses), even if such Contributor
  163 + has been advised of the possibility of such damages.
  164 +
  165 + 9. Accepting Warranty or Additional Liability. While redistributing
  166 + the Work or Derivative Works thereof, You may choose to offer,
  167 + and charge a fee for, acceptance of support, warranty, indemnity,
  168 + or other liability obligations and/or rights consistent with this
  169 + License. However, in accepting such obligations, You may act only
  170 + on Your own behalf and on Your sole responsibility, not on behalf
  171 + of any other Contributor, and only if You agree to indemnify,
  172 + defend, and hold each Contributor harmless for any liability
  173 + incurred by, or claims asserted against, such Contributor by reason
  174 + of your accepting any such warranty or additional liability.
  175 +
  176 + END OF TERMS AND CONDITIONS
  177 +
  178 + APPENDIX: How to apply the Apache License to your work.
  179 +
  180 + To apply the Apache License to your work, attach the following
  181 + boilerplate notice, with the fields enclosed by brackets "[]"
  182 + replaced with your own identifying information. (Don't include
  183 + the brackets!) The text should be enclosed in the appropriate
  184 + comment syntax for the file format. We also recommend that a
  185 + file or class name and description of purpose be included on the
  186 + same "printed page" as the copyright notice for easier
  187 + identification within third-party archives.
  188 +
  189 + Copyright [2019] [FlutterCandies]
  190 +
  191 + Licensed under the Apache License, Version 2.0 (the "License");
  192 + you may not use this file except in compliance with the License.
  193 + You may obtain a copy of the License at
  194 +
  195 + http://www.apache.org/licenses/LICENSE-2.0
  196 +
  197 + Unless required by applicable law or agreed to in writing, software
  198 + distributed under the License is distributed on an "AS IS" BASIS,
  199 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  200 + See the License for the specific language governing permissions and
  201 + limitations under the License.
  1 +<!-- Copyright 2019 The FlutterCandies author. All rights reserved.
  2 +Use of this source code is governed by an Apache license
  3 +that can be found in the LICENSE file. -->
  4 +
  5 +# Flutter WeChat Assets Picker
  6 +
  7 +[![pub package](https://img.shields.io/pub/v/wechat_assets_picker?label=%E7%A8%B3%E5%AE%9A%E7%89%88&logo=dart&style=flat-square)](https://pub.flutter-io.cn/packages/wechat_assets_picker)
  8 +[![pub package](https://img.shields.io/pub/v/wechat_assets_picker?color=9d00ff&include_prereleases&label=%E5%BC%80%E5%8F%91%E7%89%88&logo=dart&style=flat-square)](https://pub.flutter-io.cn/packages/wechat_assets_picker)
  9 +[![CodeFactor](https://img.shields.io/codefactor/grade/github/fluttercandies/flutter_wechat_assets_picker?label=%E4%BB%A3%E7%A0%81%E8%B4%A8%E9%87%8F&logo=codefactor&logoColor=%23ffffff&style=flat-square)](https://www.codefactor.io/repository/github/fluttercandies/flutter_wechat_assets_picker)
  10 +
  11 +[![Build status](https://img.shields.io/github/actions/workflow/status/fluttercandies/flutter_wechat_assets_picker/runnable.yml?branch=main&label=CI&logo=github&style=flat-square)](https://github.com/fluttercandies/flutter_wechat_assets_picker/actions/workflows/runnable.yml)
  12 +[![GitHub license](https://img.shields.io/github/license/fluttercandies/flutter_wechat_assets_picker?label=%E5%8D%8F%E8%AE%AE&style=flat-square)](https://github.com/fluttercandies/flutter_wechat_assets_picker/blob/main/LICENSE)
  13 +[![GitHub stars](https://img.shields.io/github/stars/fluttercandies/flutter_wechat_assets_picker?logo=github&style=flat-square)](https://github.com/fluttercandies/flutter_wechat_assets_picker/stargazers)
  14 +[![GitHub forks](https://img.shields.io/github/forks/fluttercandies/flutter_wechat_assets_picker?logo=github&style=flat-square)](https://github.com/fluttercandies/flutter_wechat_assets_picker/network)
  15 +
  16 +[![Awesome Flutter](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/Solido/awesome-flutter)
  17 +<a href="https://qm.qq.com/q/ZyJbSVjfSU"><img src="https://img.shields.io/badge/dynamic/yaml?url=https%3A%2F%2Fraw.githubusercontent.com%2Ffluttercandies%2F.github%2Frefs%2Fheads%2Fmain%2Fdata.yml&query=%24.qq_group_number&label=QQ%E7%BE%A4&logo=qq&style=flat&color=1DACE8" /></a>
  18 +
  19 +Language: [English](README.md) | 中文
  20 +
  21 +基于 **微信 UI** 的 Flutter **图片选择器(同时支持视频和音频)**。
  22 +
  23 +当前的界面设计基于的微信版本:**8.0.51**
  24 +界面更新将在微信版本更新后随时进行跟进。
  25 +
  26 +如果你需要拍照及录制视频,请先查看示例的详细用法,
  27 +并前往 [wechat_camera_picker][wechat_camera_picker pub]。
  28 +该插件是独立扩展,需要结合使用。
  29 +
  30 +查看 [迁移指南][] 了解如何从破坏性改动中迁移为可用代码。
  31 +
  32 +## 版本兼容
  33 +
  34 +该插件仅保证能与 **stable 渠道的 Flutter SDK** 配合使用。
  35 +我们不会为其他渠道的 Flutter SDK 做实时支持。
  36 +
  37 +| | 3.7 | 3.10 | 3.13 | 3.16 | 3.22 |
  38 +|--------|:---:|:----:|:----:|:----:|:----:|
  39 +| 9.5.0+ | ❌ | ❌ | ❌ | ❌ | ✅ |
  40 +| 8.9.0+ | ❌ | ❌ | ❌ | ✅ | ❌ |
  41 +| 8.7.0+ | ❌ | ❌ | ✅ | ❌ | ❌ |
  42 +| 8.5.0+ | ❌ | ✅ | ❌ | ❌ | ❌ |
  43 +| 8.4.0+ | ✅ | ❌ | ❌ | ❌ | ❌ |
  44 +
  45 +如果在 `flutter pub get` 时遇到了 `resolve conflict` 失败问题,
  46 +请使用 `dependency_overrides` 解决。
  47 +
  48 +## 主要使用的 package
  49 +
  50 +该插件基于这些优秀的 package 构建:
  51 +
  52 +| Name | Features |
  53 +|:-------------------------------------|:--------------|
  54 +| [photo_manager][photo_manager pub] | 资源的基础抽象和管理。 |
  55 +| [extended_image][extended_image pub] | 以熟悉的操作预览所有资源。 |
  56 +| [provider][provider pub] | 协助选择器管理器内部状态。 |
  57 +| [video_player][video_player pub] | 播放对应的视频和音频。 |
  58 +
  59 +这些 package 在该插件中的实现已相对稳定。
  60 +如果你在使用中发现于它们相关的问题,
  61 +请先在本插件的问题跟踪中报告相关问题。
  62 +
  63 +<details>
  64 + <summary>目录列表</summary>
  65 +
  66 +<!-- TOC -->
  67 +* [Flutter WeChat Assets Picker](#flutter-wechat-assets-picker)
  68 + * [版本兼容](#版本兼容)
  69 + * [主要使用的 package](#主要使用的-package)
  70 + * [特性 ✨](#特性-)
  71 + * [特别提醒 📝](#特别提醒-)
  72 + * [项目展柜 🖼️](#项目展柜-)
  73 + * [截图 📸](#截图-)
  74 + * [开始前的注意事项 ‼️](#开始前的注意事项-)
  75 + * [准备工作 🍭](#准备工作-)
  76 + * [Flutter](#flutter)
  77 + * [Android](#android)
  78 + * [权限](#权限)
  79 + * [iOS](#ios)
  80 + * [macOS](#macos)
  81 + * [使用方法 📖](#使用方法-)
  82 + * [国际化](#国际化)
  83 + * [简单的使用方法](#简单的使用方法)
  84 + * [更详细的使用方法](#更详细的使用方法)
  85 + * [展示选中的资源](#展示选中的资源)
  86 + * [注册资源变化回调](#注册资源变化回调)
  87 + * [在表单数据中上传 `AssetEntity`](#在表单数据中上传-assetentity)
  88 + * [使用 `http`](#使用-http)
  89 + * [使用 `dio`](#使用-dio)
  90 + * [自定义选择器](#自定义选择器)
  91 + * [常见问题 ❔](#常见问题-)
  92 + * [修改默认相册名称(将 `Recent` 改为其他)](#修改默认相册名称将-recent-改为其他)
  93 + * [Execution failed for task ':photo_manager:compileDebugKotlin'](#execution-failed-for-task-photo_managercompiledebugkotlin)
  94 + * [从 `File` 或 `Uint8List` 创建 `AssetEntity` 的方法](#从-file-或-uint8list-创建-assetentity-的方法)
  95 + * [控制台提示 'Failed to find GeneratedAppGlideModule'](#控制台提示-failed-to-find-generatedappglidemodule)
  96 + * [致谢](#致谢)
  97 +<!-- TOC -->
  98 +</details>
  99 +
  100 +## 特性 ✨
  101 +
  102 +- ♿ 完整的无障碍支持,包括 **TalkBack** 和 **VoiceOver**
  103 +- ♻️ 支持基于代理重载的全量自定义
  104 +- 🎏 完全可自定义的基于 `ThemeData` 的主题
  105 +- 💚 复刻微信风格(甚至优化了更多的细节)
  106 +- ⚡️ 根据配置调节的性能优化
  107 +- 📷 图片资源支持
  108 + - 🔬 HEIF 格式图片支持 <a href="#特别提醒-"><sup>(1)</sup></a>
  109 +- 🎥 视频资源支持
  110 +- 🎶 音频资源支持 <a href="#notes-"><sup>(2)</sup></a>
  111 +- 1️⃣ 单选模式模式
  112 +- 💱 国际化 (i18n) 支持
  113 + - ⏪ RTL 语言支持
  114 +- ➕ 特殊 widget 构建支持
  115 +- 🗂 自定义路径排序支持
  116 +- 📝 自定义文本构建支持
  117 +- ⏳ 自定义筛选规则支持
  118 +- 💻 支持 MacOS
  119 +
  120 +### 特别提醒 📝
  121 +
  122 +1. HEIF (HEIC) 图片支持获取和转换,但是它们的显示依托于 Flutter 的图片解析。
  123 + 在此 issue 中 [flutter/flutter#20522](https://github.com/flutter/flutter/issues/20522) 有所说明。
  124 + 若要用于显示,请使用 `entity.file` 或 `AssetEntityImage` 进行处理。
  125 +2. 由于 iOS 和 macOS 的系统限制,在获取音频时只能获取应用沙盒环境内的音频。
  126 +
  127 +## 项目展柜 🖼️
  128 +
  129 +| name | pub | github |
  130 +|:--------------------|:---------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------|
  131 +| insta_assets_picker | [![pub package](https://img.shields.io/pub/v/insta_assets_picker)](https://pub.flutter-io.cn/packages/insta_assets_picker) | [![star](https://img.shields.io/github/stars/LeGoffMael/insta_assets_picker?style=social)](https://github.com/LeGoffMael/insta_assets_picker) |
  132 +
  133 +## 截图 📸
  134 +
  135 +| ![1](screenshots/README_1.webp) | ![2](screenshots/README_2.webp) | ![3](screenshots/README_3.webp) |
  136 +|-----------------------------------|-----------------------------------|-----------------------------------|
  137 +| ![4](screenshots/README_4.webp) | ![5](screenshots/README_5.webp) | ![6](screenshots/README_6.webp) |
  138 +| ![7](screenshots/README_7.webp) | ![8](screenshots/README_8.webp) | ![9](screenshots/README_9.webp) |
  139 +| ![10](screenshots/README_10.webp) | ![11](screenshots/README_11.webp) | ![12](screenshots/README_12.webp) |
  140 +
  141 +## 开始前的注意事项 ‼️
  142 +
  143 +在开始一切之前,请明确以下两点:
  144 +- 由于理解差异和篇幅限制,并不是所有的内容都会明确地在文档中指出。
  145 + 当你遇到没有找到需求和无法理解的概念时,请先运行项目的示例 example,
  146 + 它可以解决 90% 的常见需求。
  147 +- 该库与 [photo_manager][photo_manager pub] 有强关联性,
  148 + 大部分方法的行为是由 photo_manager 进行控制的,
  149 + 所以请尽可能地确保你了解以下两个类的概念:
  150 + - 资源(图片/视频/音频) [`AssetEntity`](https://pub.flutter-io.cn/documentation/photo_manager/latest/photo_manager/AssetEntity-class.html)
  151 + - 资源合集(相册或集合概念) [`AssetPathEntity`](https://pub.flutter-io.cn/documentation/photo_manager/latest/photo_manager/AssetPathEntity-class.html)
  152 +
  153 +当你有与相关的 API 和行为的疑问时,你可以查看
  154 +[photo_manager API 文档][] 了解更多细节。
  155 +
  156 +众多使用场景都已包含在示例中。
  157 +在你提出任何问题之前,请仔细并完整地查看和使用示例。
  158 +
  159 +## 准备工作 🍭
  160 +
  161 +### Flutter
  162 +
  163 +执行 `flutter pub add wechat_assets_picker`,
  164 +或者将 `wechat_assets_picker` 手动添加至 `pubspec.yaml` 引用。
  165 +
  166 +```yaml
  167 +dependencies:
  168 + wechat_assets_picker: ^latest_version
  169 +```
  170 +
  171 +最新的 **稳定** 版本是:
  172 +[![pub package](https://img.shields.io/pub/v/wechat_assets_picker?logo=dart&label=stable&style=flat-square)](https://pub.flutter-io.cn/packages/wechat_assets_picker)
  173 +
  174 +最新的 **开发** 版本是:
  175 +[![pub package](https://img.shields.io/pub/v/wechat_assets_picker?color=9d00ff&include_prereleases&label=dev&logo=dart&style=flat-square)](https://pub.flutter-io.cn/packages/wechat_assets_picker)
  176 +
  177 +在你的代码中导入:
  178 +
  179 +```dart
  180 +import 'package:wechat_assets_picker/wechat_assets_picker.dart';
  181 +```
  182 +
  183 +### Android
  184 +
  185 +在使用这个 package 时,请确保
  186 +`compileSdkVersion` 和 `targetSdkVersion` 升级到 `33`。
  187 +否则,在 Android 13 设备上将有可能无法加载任何资源。
  188 +
  189 +#### 权限
  190 +
  191 +| Name | 必需 | 已声明 | 最高 API 版本 | 其他 |
  192 +|--------------------------|-----|-----|-----------|-------------|
  193 +| `READ_EXTERNAL_STORAGE` | 是 | 是 | 32 | |
  194 +| `WRITE_EXTERNAL_STORAGE` | 否 | 否 | 29 | |
  195 +| `ACCESS_MEDIA_LOCATION` | 是* | 否 | N/A | 读取 EXIF 时必需 |
  196 +| `READ_MEDIA_IMAGES` | 是* | 是 | N/A | 读取图片时必需 |
  197 +| `READ_MEDIA_VIDEO` | 是* | 是 | N/A | 读取视频时必需 |
  198 +| `READ_MEDIA_AUDIO` | 是* | 是 | N/A | 读取音频时必需 |
  199 +
  200 +如果你的目标 SDK 版本大于 33,且你不需要获取图片、视频或者音频,
  201 +你可以考虑只声明需要的权限,具体如下:
  202 +
  203 +```xml
  204 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  205 + xmlns:tools="http://schemas.android.com/tools"
  206 + package="com.your.app">
  207 + <!--请求图片和视频权限-->
  208 + <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
  209 + <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
  210 + <!--如果不需要获取音频,移除或者注释 READ_MEDIA_AUDIO-->
  211 + <!--<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />-->
  212 +</manifest>
  213 +```
  214 +
  215 +### iOS
  216 +
  217 +1. 在 `ios/Podfile` 中指定最低构建版本至 **11.0**。
  218 + ```ruby
  219 + platform :ios, '11.0'
  220 + ```
  221 + 如果该行以 `#` (注释) 开头,请把 `#` 删除。
  222 +2. 将以下内容添加至 `Info.plist`。
  223 +```
  224 +<key>NSPhotoLibraryUsageDescription</key>
  225 +<string>你的相册权限描述</string>
  226 +```
  227 +
  228 +### macOS
  229 +
  230 +1. 在 `macos/Podfile` 中指定最低构建版本至 **10.15**。
  231 + ```Podfile
  232 + platform :osx, '10.15'
  233 + ```
  234 + 如果该行以 `#` (注释) 开头,请把 `#` 删除。
  235 +2. 使用 **Xcode** 打开 `macos/Runner.xcworkspace`。
  236 + 接着将 macOS 的最低构建版本提升至 **10.15**。
  237 +3. 与 [iOS](#iOS) 一样,添加相同的内容到 `Info.plist` 里。
  238 +
  239 +## 使用方法 📖
  240 +
  241 +### 国际化
  242 +
  243 +当你在选择资源的时候,package 会通过你的 `BuildContext`
  244 +读取 `Locale?`,返回对应语言的文字代理实现。
  245 +请确保你可以通过 `BuildContext` 获取到 `Locale`,否则将会 **默认展示中文文字**。
  246 +
  247 +内置的语言文字实现有:
  248 +* 简体中文 (默认)
  249 +* English
  250 +* העברית
  251 +* Deutsche
  252 +* Локализация
  253 +* 日本語
  254 +* مة العربية
  255 +* Délégué
  256 +* Tiếng Việt
  257 +* Türkçe Yerelleştirme
  258 +
  259 +如果你想使用自定义或固定的文字实现,请通过
  260 +`AssetPickerConfig.textDelegate` 传递调用。
  261 +
  262 +### 简单的使用方法
  263 +
  264 +```dart
  265 +final List<AssetEntity>? result = await AssetPicker.pickAssets(context);
  266 +```
  267 +
  268 +你可以使用 `AssetPickerConfig` 来调整选择时的行为。
  269 +
  270 +```dart
  271 +final List<AssetEntity>? result = await AssetPicker.pickAssets(
  272 + context,
  273 + pickerConfig: const AssetPickerConfig(),
  274 +);
  275 +```
  276 +
  277 +`AssetPickerConfig` 的成员说明:
  278 +
  279 +| 参数名 | 类型 | 描述 | 默认值 |
  280 +|-----------------------------------|--------------------------------------------------|------------------------------------------------------|-----------------------------|
  281 +| selectedAssets | `List<AssetEntity>?` | 已选的资源。确保不重复选择。 | `null` |
  282 +| maxAssets | `int` | 最多选择的图片数量 | 9 |
  283 +| pageSize | `int` | 分页加载时每页加载的资源数量。**必须为网格数的倍数。 | 80 |
  284 +| gridThumbnailSize | `ThumbnailSize` | 预览网格的缩略图大小 | `ThumbnailSize.square(200)` |
  285 +| pathThumbnailSize | `ThumbnailSize` | 路径选择器的缩略图大小 | `ThumbnailSize.square(80)` |
  286 +| previewThumbnailSize | `ThumbnailSize?` | 预览时图片的缩略图大小 | `null` |
  287 +| requestType | `RequestType` | 选择器选择资源的类型 | `RequestType.common` |
  288 +| specialPickerType | `SpecialPickerType?` | 提供一些特殊的选择器类型以整合非常规的选择行为 | `null` |
  289 +| keepScrollOffset | `bool` | 选择器是否可以从同样的位置开始选择 | `null` |
  290 +| sortPathDelegate | `SortPathDelegate<AssetPathEntity>?` | 资源路径的排序实现,可自定义路径排序方法 | `CommonSortPathDelegate` |
  291 +| sortPathsByModifiedDate | `bool` | 是否结合 `FilterOptionGroup.containsPathModified` 进行路径排序 | `false` |
  292 +| filterOptions | `PMFilter?` | 允许用户自定义资源过滤条件 | `null` |
  293 +| gridCount | `int` | 选择器网格数量 | 4 |
  294 +| themeColor | `Color?` | 选择器的主题色 | `Color(0xff00bc56)` |
  295 +| pickerTheme | `ThemeData?` | 选择器的主题提供,包括查看器 | `null` |
  296 +| textDelegate | `AssetPickerTextDelegate?` | 选择器的文本代理构建,用于自定义文本 | `AssetPickerTextDelegate()` |
  297 +| specialItemPosition | `SpecialItemPosition` | 允许用户在选择器中添加一个自定义item,并指定位置。 | `SpecialPosition.none` |
  298 +| specialItemBuilder | `SpecialItemBuilder?` | 自定义item的构造方法 | `null` |
  299 +| loadingIndicatorBuilder | `IndicatorBuilder?` | 加载器的实现 | `null` |
  300 +| selectPredicate | `AssetSelectPredicate` | 判断资源可否被选择 | `null` |
  301 +| shouldRevertGrid | `bool?` | 判断资源网格是否需要倒序排列 | `null` |
  302 +| limitedPermissionOverlayPredicate | `LimitedPermissionOverlayPredicate?` | 判断有限的权限情况下是否展示提示页面 | `null` |
  303 +| pathNameBuilder | `PathNameBuilder<AssetPathEntity>?` | 基于路径(相册)构建自定义名称的方法 | `null` |
  304 +| assetsChangeCallback | `AssetsChangeCallback<AssetPathEntity>?` | 当系统通知资源变化时将调用的回调 | `null` |
  305 +| assetsChangeRefreshPredicate | `AssetsChangeRefreshPredicate<AssetPathEntity>?` | 判断资源变化是否根据 call 和当前选中的路径进行更新 | `null` |
  306 +| shouldAutoplayPreview | `bool` | 预览是否应自动播放 | `false` |
  307 +| dragToSelect | `bool` | 是否开启拖拽选择 | `true` |
  308 +
  309 +- 当 `maxAssets` 等于 `1`(即单选模式),搭配
  310 + `SpecialPickerType.noPreview` 使用会在用户点选资源换时立刻选中并返回。
  311 +- `limitedPermissionOverlayPredicate` 不是持久化的,
  312 + 如果你需要在应用下次启动时不再显示权限受限的页面,请自主实现持久化的控制。
  313 +
  314 +### 更详细的使用方法
  315 +
  316 +我们已将常用的调用方法封装在 [example](example) 中。
  317 +你可以在 `example/lib/pages/multi_assets_page.dart` 和
  318 +`example/lib/pages/single_assets_page.dart`
  319 +找到 `List<PickMethod> pickMethods`,
  320 +它分别定义了多选和单选可用的选择模式。
  321 +在选择资源后,资源会暂存并展示在页面下方。
  322 +
  323 +#### 展示选中的资源
  324 +
  325 +`AssetEntityImage` 和 `AssetEntityImageProvider`
  326 +可以为 **图片 & 视频** 展示缩略图,以及展示 **图片的原图**。
  327 +它的使用方法与常见的 `Image` 和 `ImageProvider` 一致。
  328 +
  329 +```dart
  330 +AssetEntityImage(asset, isOriginal: false);
  331 +```
  332 +
  333 +或:
  334 +
  335 +```dart
  336 +/// AssetEntityImageProvider
  337 +Image(image: AssetEntityImageProvider(asset, isOriginal: false));
  338 +```
  339 +
  340 +#### 注册资源变化回调
  341 +
  342 +```dart
  343 +/// 注册回调
  344 +AssetPicker.registerObserve();
  345 +
  346 +/// 取消注册回调
  347 +AssetPicker.unregisterObserve();
  348 +```
  349 +
  350 +#### 在表单数据中上传 `AssetEntity`
  351 +
  352 +`AssetEntity` 包含有多种 I/O 相关的方法可以用于上传。
  353 +**请注意,I/O 相关的方法会消耗性能(通常是时间和内存),它们不应该被频繁调用。**
  354 +
  355 +##### 使用 `http`
  356 +
  357 +`http` package: https://pub.flutter-io.cn/packages/http
  358 +
  359 +`http` package 使用v
  360 +[`MultipartFile`](https://pub.flutter-io.cn/documentation/http/latest/http/MultipartFile-class.html)
  361 +来在请求中处理文件。
  362 +
  363 +示例代码如下:
  364 +```dart
  365 +import 'package:http/http.dart' as http;
  366 +
  367 +Future<void> upload() async {
  368 + final entity = await obtainYourEntity();
  369 + final uri = Uri.https('example.com', 'create');
  370 + final request = http.MultipartRequest('POST', uri)
  371 + ..fields['test_field'] = 'test_value'
  372 + ..files.add(await multipartFileFromAssetEntity(entity));
  373 + final response = await request.send();
  374 + if (response.statusCode == 200) {
  375 + print('Uploaded!');
  376 + }
  377 +}
  378 +
  379 +Future<http.MultipartFile> multipartFileFromAssetEntity(AssetEntity entity) async {
  380 + http.MultipartFile mf;
  381 + // Using the file path.
  382 + final file = await entity.file;
  383 + if (file == null) {
  384 + throw StateError('Unable to obtain file of the entity ${entity.id}.');
  385 + }
  386 + mf = await http.MultipartFile.fromPath('test_file', file.path);
  387 + // Using the bytes.
  388 + final bytes = await entity.originBytes;
  389 + if (bytes == null) {
  390 + throw StateError('Unable to obtain bytes of the entity ${entity.id}.');
  391 + }
  392 + mf = http.MultipartFile.fromBytes('test_file', bytes);
  393 + return mf;
  394 +}
  395 +```
  396 +
  397 +##### 使用 `dio`
  398 +
  399 +`dio` package: https://pub.flutter-io.cn/packages/dio
  400 +
  401 +`dio` package 同样使用了
  402 +[`MultipartFile`](https://pub.flutter-io.cn/documentation/dio/latest/dio/MultipartFile-class.html)
  403 +来在请求中处理文件。
  404 +
  405 +示例代码:
  406 +```dart
  407 +import 'package:dio/dio.dart' as dio;
  408 +
  409 +Future<void> upload() async {
  410 + final entity = await obtainYourEntity();
  411 + final uri = Uri.https('example.com', 'create');
  412 + final response = dio.Dio().requestUri(
  413 + uri,
  414 + data: dio.FormData.fromMap({
  415 + 'test_field': 'test_value',
  416 + 'test_file': await multipartFileFromAssetEntity(entity),
  417 + }),
  418 + );
  419 + print('Uploaded!');
  420 +}
  421 +
  422 +Future<dio.MultipartFile> multipartFileFromAssetEntity(AssetEntity entity) async {
  423 + dio.MultipartFile mf;
  424 + // Using the file path.
  425 + final file = await entity.file;
  426 + if (file == null) {
  427 + throw StateError('Unable to obtain file of the entity ${entity.id}.');
  428 + }
  429 + mf = await dio.MultipartFile.fromFile(file.path);
  430 + // Using the bytes.
  431 + final bytes = await entity.originBytes;
  432 + if (bytes == null) {
  433 + throw StateError('Unable to obtain bytes of the entity ${entity.id}.');
  434 + }
  435 + mf = dio.MultipartFile.fromBytes(bytes);
  436 + return mf;
  437 +}
  438 +```
  439 +
  440 +### 自定义选择器
  441 +
  442 +`AssetPickerBuilderDelegate`、`AssetPickerViewerBuilderDelegate`、
  443 +`AssetPickerProvider` 及 `AssetPickerViewerProvider` 均已暴露且可重载。
  444 +使用者可以使用自定义的泛型类型 `<A: 资源, P: 路径>`,
  445 +配合继承与重载,实现对应抽象类和类中的方法。
  446 +更多用法请查看示例中的 `Custom` 页面,
  447 +该页面包含一个以 `<File, Directory>` 为类型基础的选择器。
  448 +
  449 +想要了解如何完全自定义主题、widget 和布局,前往 [示例](example/lib/customs/pickers)
  450 +查看已有的自定义选择器的实现。
  451 +
  452 +如果你觉得你的实现有价值或能帮助到其他人,欢迎以 PR 的形式进行提交。
  453 +更多细节请阅读 [贡献自定义实现][]。
  454 +
  455 +## 常见问题 ❔
  456 +
  457 +### 修改默认相册名称(将 `Recent` 改为其他)
  458 +
  459 +在 Android 上 `Recent` 是总相册的默认名称,
  460 +总相册是一个实际不存在的概念,它只是原始媒体数据的记录集合。
  461 +
  462 +想要在 Android 上解决这个问题,你可以像这样使用 `pathNameBuilder`:
  463 +```dart
  464 +AssetPickerConfig(
  465 + pathNameBuilder: (AssetPathEntity path) => switch (path) {
  466 + final p when p.isAll => '最近',
  467 + // 你也可以将类似的逻辑应用在其他常见的相册上。
  468 + _ => path.name,
  469 + },
  470 +)
  471 +```
  472 +
  473 +其他相册或者其他平台 (iOS/macOS) 上的相册会根据系统语言和配置支持的语言来进行展示。
  474 +`pathNameBuilder` 可以用于任何的相册。
  475 +
  476 +### Execution failed for task ':photo_manager:compileDebugKotlin'
  477 +
  478 +查看 [photo_manager#561][] 了解详细的解决方法。
  479 +
  480 +### 从 `File` 或 `Uint8List` 创建 `AssetEntity` 的方法
  481 +
  482 +如果需要使用此库结合一些拍照需求,
  483 +可通过以下方法将 `File` 或 `Uint8List` 转为 `AssetEntity`。
  484 +
  485 +```dart
  486 +final File file = your_file; // 你的 File 对象
  487 +final String path = file.path;
  488 +final AssetEntity fileEntity = await PhotoManager.editor.saveImageWithPath(
  489 + path,
  490 + title: basename(path),
  491 +); // 存入手机并生成 AssetEntity
  492 +
  493 +final Uint8List data = your_data; // 你的 Uint8List 对象
  494 +final AssetEntity imageEntity = await PhotoManager.editor.saveImage(
  495 + file.path,
  496 + title: '带有后缀的名称.jpg',
  497 +); // 存入手机并生成 AssetEntity
  498 +```
  499 +
  500 +**注意:如果不想保留文件,请尽量用 `File` 承载中间操作,**
  501 +否则在调用 `AssetEntity` 的删除时,系统可能会触发弹窗:
  502 +
  503 +```dart
  504 +final List<String> result = await PhotoManager.editor.deleteWithIds(
  505 + <String>[entity.id],
  506 +);
  507 +```
  508 +
  509 +你可以阅读 [photo_manager#from-raw-data][]
  510 +和 [photo_manager#delete-entities][]
  511 +了解更多细节。
  512 +
  513 +### 控制台提示 'Failed to find GeneratedAppGlideModule'
  514 +
  515 +```
  516 +W/Glide (21133): Failed to find GeneratedAppGlideModule.
  517 + You should include an annotationProcessor compile dependency on com.github.bumptech.glide:compiler
  518 + in you application ana a @GlideModule annotated AppGlideModule implementation
  519 + or LibraryGlideModules will be silently ignored.
  520 +```
  521 +
  522 +`Glide` 通过注解来保证单例,防止单例或版本之间的冲突,
  523 +而因为 `photo_manager` 使用了 `Glide` 提供部分图片功能,
  524 +所以使用它的项目必须实现自己的 `AppGlideModule`。
  525 +请移步 [Glide Generated API 文档][] 了解如何实现。
  526 +
  527 +## 致谢
  528 +
  529 +> IntelliJ IDEA 的每个方面都旨在最大化开发者生产力。结合智能编码辅助与符合人体工程学的设计,让开发不仅高效,更成为一种享受。
  530 +
  531 +感谢 [JetBrains](https://www.jetbrains.com/?from=fluttercandies)
  532 +为开源项目提供免费的
  533 +[IntelliJ IDEA](https://www.jetbrains.com/idea/?from=fluttercandies)
  534 +等 IDE 的授权。
  535 +
  536 +[<img src="https://github.com/fluttercandies/flutter_wechat_assets_picker/raw/main/.github/jetbrains-variant.png" width="200"/>](https://www.jetbrains.com/?from=fluttercandies)
  537 +
  538 +
  539 +[photo_manager pub]: https://pub.flutter-io.cn/packages/photo_manager
  540 +[extended_image pub]: https://pub.flutter-io.cn/packages/extended_image
  541 +[provider pub]: https://pub.flutter-io.cn/packages/provider
  542 +[video_player pub]: https://pub.flutter-io.cn/packages/video_player
  543 +[wechat_camera_picker pub]: https://pub.flutter-io.cn/packages/wechat_camera_picker
  544 +[迁移指南]: https://github.com/fluttercandies/flutter_wechat_assets_picker/blob/main/guides/migration_guide.md
  545 +[photo_manager API 文档]: https://pub.flutter-io.cn/documentation/photo_manager/latest/
  546 +[Glide Generated API 文档]: https://muyangmin.github.io/glide-docs-cn/doc/generatedapi.html
  547 +[贡献自定义实现]: https://github.com/fluttercandies/flutter_wechat_assets_picker/blob/main/example/lib/customs/CONTRIBUTING.md
  548 +[photo_manager#561]: https://github.com/fluttercandies/flutter_photo_manager/issues/561
  549 +[photo_manager#from-raw-data]: https://github.com/fluttercandies/flutter_photo_manager#from-raw-data
  550 +[photo_manager#delete-entities]: https://github.com/fluttercandies/flutter_photo_manager#delete-entities
  1 +<!-- Copyright 2019 The FlutterCandies author. All rights reserved.
  2 +Use of this source code is governed by an Apache license
  3 +that can be found in the LICENSE file. -->
  4 +
  5 +# Flutter WeChat Assets Picker
  6 +
  7 +[![pub package](https://img.shields.io/pub/v/wechat_assets_picker?logo=dart&label=stable&style=flat-square)](https://pub.dev/packages/wechat_assets_picker)
  8 +[![pub package](https://img.shields.io/pub/v/wechat_assets_picker?color=9d00ff&include_prereleases&label=dev&logo=dart&style=flat-square)](https://pub.dev/packages/wechat_assets_picker)
  9 +[![CodeFactor](https://img.shields.io/codefactor/grade/github/fluttercandies/flutter_wechat_assets_picker?logo=codefactor&logoColor=%23ffffff&style=flat-square)](https://www.codefactor.io/repository/github/fluttercandies/flutter_wechat_assets_picker)
  10 +
  11 +[![Build status](https://img.shields.io/github/actions/workflow/status/fluttercandies/flutter_wechat_assets_picker/runnable.yml?branch=main&label=CI&logo=github&style=flat-square)](https://github.com/fluttercandies/flutter_wechat_assets_picker/actions/workflows/runnable.yml)
  12 +[![GitHub license](https://img.shields.io/github/license/fluttercandies/flutter_wechat_assets_picker?style=flat-square)](https://github.com/fluttercandies/flutter_wechat_assets_picker/blob/main/LICENSE)
  13 +[![GitHub stars](https://img.shields.io/github/stars/fluttercandies/flutter_wechat_assets_picker?logo=github&style=flat-square)](https://github.com/fluttercandies/flutter_wechat_assets_picker/stargazers)
  14 +[![GitHub forks](https://img.shields.io/github/forks/fluttercandies/flutter_wechat_assets_picker?logo=github&style=flat-square)](https://github.com/fluttercandies/flutter_wechat_assets_picker/network)
  15 +
  16 +[![Awesome Flutter](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/Solido/awesome-flutter)
  17 +<a href="https://qm.qq.com/q/ZyJbSVjfSU"><img src="https://img.shields.io/badge/dynamic/yaml?url=https%3A%2F%2Fraw.githubusercontent.com%2Ffluttercandies%2F.github%2Frefs%2Fheads%2Fmain%2Fdata.yml&query=%24.qq_group_number&label=QQ%E7%BE%A4&logo=qq&style=flat&color=1DACE8" /></a>
  18 +
  19 +Language: English | [中文](README-ZH.md)
  20 +
  21 +An **image picker (also with videos and audios)**
  22 +for Flutter projects based on the WeChat's UI.
  23 +
  24 +Current WeChat version that UI based on: **8.0.51**
  25 +UI designs will be updated following the WeChat update in anytime.
  26 +
  27 +To take a photo or a video for assets,
  28 +please check the detailed usage in the example,
  29 +and head over to [wechat_camera_picker][wechat_camera_picker pub].
  30 +The package is a standalone extension that can to be used with combination.
  31 +
  32 +See the [Migration Guide][] to learn how to migrate between breaking changes.
  33 +
  34 +## Versions compatibility
  35 +
  36 +The package only guarantees to be working on **the stable version of Flutter**.
  37 +We won't update it in real-time to align with other channels of Flutter.
  38 +
  39 +| | 3.7 | 3.10 | 3.13 | 3.16 | 3.22 |
  40 +|--------|:---:|:----:|:----:|:----:|:----:|
  41 +| 9.5.0+ | ❌ | ❌ | ❌ | ❌ | ✅ |
  42 +| 8.9.0+ | ❌ | ❌ | ❌ | ✅ | ❌ |
  43 +| 8.7.0+ | ❌ | ❌ | ✅ | ❌ | ❌ |
  44 +| 8.5.0+ | ❌ | ✅ | ❌ | ❌ | ❌ |
  45 +| 8.4.0+ | ✅ | ❌ | ❌ | ❌ | ❌ |
  46 +
  47 +If you got a `resolve conflict` error when running `flutter pub get`,
  48 +please use `dependency_overrides` to fix it.
  49 +
  50 +## Package credits
  51 +
  52 +The package is built from these wonderful packages.
  53 +
  54 +| Name | Features |
  55 +|:-------------------------------------|:-----------------------------------------------------|
  56 +| [photo_manager][photo_manager pub] | The basic abstractions and management for assets. |
  57 +| [extended_image][extended_image pub] | Preview assets with expected behaviors. |
  58 +| [provider][provider pub] | Helps to manage the interaction state of the picker. |
  59 +| [video_player][video_player pub] | Plays videos and audios correspondingly. |
  60 +
  61 +Their implementation should be relatively stable in the package.
  62 +If you've found any issues related to them when using the picker,
  63 +submit issues to our issue tracker first.
  64 +
  65 +<details>
  66 + <summary>Table of content</summary>
  67 +
  68 +<!-- TOC -->
  69 +* [Flutter WeChat Assets Picker](#flutter-wechat-assets-picker)
  70 + * [Versions compatibility](#versions-compatibility)
  71 + * [Package credits](#package-credits)
  72 + * [Features ✨](#features-)
  73 + * [Notes 📝](#notes-)
  74 + * [Projects using this plugin 🖼️](#projects-using-this-plugin-)
  75 + * [Screenshots 📸](#screenshots-)
  76 + * [READ THIS FIRST ‼️](#read-this-first-)
  77 + * [Preparing for use 🍭](#preparing-for-use-)
  78 + * [Flutter](#flutter)
  79 + * [Android](#android)
  80 + * [Permissions](#permissions)
  81 + * [iOS](#ios)
  82 + * [macOS](#macos)
  83 + * [Usage 📖](#usage-)
  84 + * [Localizations](#localizations)
  85 + * [Simple usage](#simple-usage)
  86 + * [Detailed usage](#detailed-usage)
  87 + * [Display selected assets](#display-selected-assets)
  88 + * [Register assets change observe callback](#register-assets-change-observe-callback)
  89 + * [Upload an `AssetEntity` with a form data](#upload-an-assetentity-with-a-form-data)
  90 + * [With `http`](#with-http)
  91 + * [With `dio`](#with-dio)
  92 + * [Custom pickers](#custom-pickers)
  93 + * [Frequently asked question ❔](#frequently-asked-question-)
  94 + * [Changing the default album name (`Recent` to others)](#changing-the-default-album-name-recent-to-others)
  95 + * [Execution failed for task ':photo_manager:compileDebugKotlin'](#execution-failed-for-task-photo_managercompiledebugkotlin)
  96 + * [Create `AssetEntity` from `File` or `Uint8List` (rawData)](#create-assetentity-from-file-or-uint8list-rawdata)
  97 + * [Glide warning 'Failed to find GeneratedAppGlideModule'](#glide-warning-failed-to-find-generatedappglidemodule)
  98 + * [Contributors ✨](#contributors-)
  99 + * [Credits](#credits)
  100 +<!-- TOC -->
  101 +</details>
  102 +
  103 +## Features ✨
  104 +
  105 +- ♿ Complete a11y support with _TalkBack_ and _VoiceOver_
  106 +- ♻️ Fully customizable with delegates override
  107 +- 🎏 Fully customizable theme based on `ThemeData`
  108 +- 💚 Completely WeChat style (even more)
  109 +- ⚡️ Adjustable performance with different configurations
  110 +- 📷 Image support
  111 + - 🔬 HEIF Image type support <a href="#notes-"><sup>(1)</sup></a>
  112 +- 🎥 Video support
  113 +- 🎶 Audio support <a href="#notes-"><sup>(2)</sup></a>
  114 +- 1️⃣ Single picking mode
  115 +- 💱 Internationalization (i18n) support
  116 + - ⏪ RTL language support
  117 +- ➕ Special item builder support
  118 +- 🗂 Custom sort path delegate support
  119 +- 📝 Custom text delegate support
  120 +- ⏳ Custom filter options support
  121 +- 💻 macOS support
  122 +
  123 +### Notes 📝
  124 +
  125 +1. HEIF (HEIC) images are support to obtain and conversion,
  126 + but the display with them are based on Flutter's image decoder.
  127 + See [flutter/flutter#20522](https://github.com/flutter/flutter/issues/20522).
  128 + Use `entity.file` or `AssetEntityImage` for them when displays.
  129 +2. Due to limitations on iOS and macOS, audio can only be fetched within the sandbox.
  130 +
  131 +## Projects using this plugin 🖼️
  132 +
  133 +| name | pub | github |
  134 +|:--------------------|:-----------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------|
  135 +| insta_assets_picker | [![pub package](https://img.shields.io/pub/v/insta_assets_picker)](https://pub.dev/packages/insta_assets_picker) | [![star](https://img.shields.io/github/stars/LeGoffMael/insta_assets_picker?style=social)](https://github.com/LeGoffMael/insta_assets_picker) |
  136 +
  137 +## Screenshots 📸
  138 +
  139 +| ![1](screenshots/README_1.webp) | ![2](screenshots/README_2.webp) | ![3](screenshots/README_3.webp) |
  140 +|-----------------------------------|-----------------------------------|-----------------------------------|
  141 +| ![4](screenshots/README_4.webp) | ![5](screenshots/README_5.webp) | ![6](screenshots/README_6.webp) |
  142 +| ![7](screenshots/README_7.webp) | ![8](screenshots/README_8.webp) | ![9](screenshots/README_9.webp) |
  143 +| ![10](screenshots/README_10.webp) | ![11](screenshots/README_11.webp) | ![12](screenshots/README_12.webp) |
  144 +
  145 +## READ THIS FIRST ‼️
  146 +
  147 +Be aware of below notices before you started anything:
  148 +- Due to understanding differences and the limitation of a single document,
  149 + documents will not cover all the contents.
  150 + If you find nothing related to your expected features and cannot understand about concepts,
  151 + run the example project and check every options first.
  152 + It has covered 90% of regular requests with the package.
  153 +- The package deeply integrates with the [photo_manager][photo_manager pub] plugin,
  154 + make sure you understand these two concepts as much as possible:
  155 + - Asset (photos/videos/audio) - [`AssetEntity`](https://pub.dev/documentation/photo_manager/latest/photo_manager/AssetEntity-class.html)
  156 + - Assets collection (albums/libraries) - [`AssetPathEntity`](https://pub.dev/documentation/photo_manager/latest/photo_manager/AssetPathEntity-class.html)
  157 +
  158 +When you have questions about related APIs and behaviors,
  159 +check [photo_manager's API docs][] for more details.
  160 +
  161 +Most usages are detailed covered by the [example](example).
  162 +Please walk through the [example](example) carefully
  163 +before you have any questions.
  164 +
  165 +## Preparing for use 🍭
  166 +
  167 +### Flutter
  168 +
  169 +Run `flutter pub add wechat_assets_picker`,
  170 +or add `wechat_assets_picker` to `pubspec.yaml` dependencies manually.
  171 +```yaml
  172 +dependencies:
  173 + wechat_assets_picker: ^latest_version
  174 +```
  175 +
  176 +The latest **stable** version is:
  177 +[![pub package](https://img.shields.io/pub/v/wechat_assets_picker?logo=dart&label=stable&style=flat-square)](https://pub.dev/packages/wechat_assets_picker)
  178 +
  179 +The latest **dev** version is:
  180 +[![pub package](https://img.shields.io/pub/v/wechat_assets_picker?color=9d00ff&include_prereleases&label=dev&logo=dart&style=flat-square)](https://pub.dev/packages/wechat_assets_picker)
  181 +
  182 +Then import the package in your code:
  183 +```dart
  184 +import 'package:wechat_assets_picker/wechat_assets_picker.dart';
  185 +```
  186 +
  187 +### Android
  188 +
  189 +When using the package, please upgrade
  190 +`targetSdkVersion` and `compileSdkVersion` to `33`.
  191 +Otherwise, no assets can be fetched on Android 13.
  192 +
  193 +#### Permissions
  194 +
  195 +| Name | Required | Declared | Max API Level | Others |
  196 +|--------------------------|----------|----------|---------------|------------------------------|
  197 +| `READ_EXTERNAL_STORAGE` | YES | YES | 32 | |
  198 +| `WRITE_EXTERNAL_STORAGE` | NO | NO | 29 | |
  199 +| `ACCESS_MEDIA_LOCATION` | YES* | NO | N/A | Required when reading EXIF |
  200 +| `READ_MEDIA_IMAGES` | YES* | YES | N/A | Required when reading images |
  201 +| `READ_MEDIA_VIDEO` | YES* | YES | N/A | Required when reading videos |
  202 +| `READ_MEDIA_AUDIO` | YES* | YES | N/A | Required when reading audios |
  203 +
  204 +If you're targeting Android SDK 33+,
  205 +and you don't need to load photos, videos or audios,
  206 +consider declare only relevant permission in your apps, more specifically:
  207 +
  208 +```xml
  209 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  210 + xmlns:tools="http://schemas.android.com/tools"
  211 + package="com.your.app">
  212 + <!--Requesting access to images and videos.-->
  213 + <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
  214 + <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
  215 + <!--When your app has no need to access audio, remove it or comment it out.-->
  216 + <!--<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />-->
  217 +</manifest>
  218 +```
  219 +
  220 +### iOS
  221 +
  222 +1. Platform version has to be at least *11.0*.
  223 + Modify `ios/Podfile` and update accordingly.
  224 + ```Podfile
  225 + platform :ios, '11.0'
  226 + ```
  227 + Remove the `#` heading if the line starts with it.
  228 +2. Add the following content to `Info.plist`.
  229 +```
  230 +<key>NSPhotoLibraryUsageDescription</key>
  231 +<string>Replace with your permission description.</string>
  232 +```
  233 +
  234 +### macOS
  235 +
  236 +1. Platform version has to be at least *10.15*.
  237 + Modify `macos/Podfile` and update accordingly.
  238 + ```ruby
  239 + platform :osx, '10.15'
  240 + ```
  241 + Remove the `#` heading if the line starts with it.
  242 +2. Set the minimum deployment target of the macOS to *10.15*.
  243 + Use XCode to open `macos/Runner.xcworkspace` .
  244 +3. Follow the [iOS](#iOS) instructions and modify `Info.plist` accordingly.
  245 +
  246 +## Usage 📖
  247 +
  248 +### Localizations
  249 +
  250 +When you're picking assets, the package will obtain the `Locale?`
  251 +from your `BuildContext`, and return the corresponding text delegate
  252 +of the current language.
  253 +Make sure you have a valid `Locale` in your widget tree that can be accessed
  254 +from the `BuildContext`. **Otherwise, the default Chinese delegate will be used.**
  255 +
  256 +Embedded text delegates languages are:
  257 +* 简体中文 (default)
  258 +* English
  259 +* העברית
  260 +* Deutsche
  261 +* Локализация
  262 +* 日本語
  263 +* مة العربية
  264 +* Délégué
  265 +* Tiếng Việt
  266 +* Türkçe Yerelleştirme
  267 +
  268 +If you want to use a custom/fixed text delegate, pass it through the
  269 +`AssetPickerConfig.textDelegate`.
  270 +
  271 +### Simple usage
  272 +
  273 +```dart
  274 +final List<AssetEntity>? result = await AssetPicker.pickAssets(context);
  275 +```
  276 +
  277 +Use `AssetPickerConfig` for more picking behaviors.
  278 +
  279 +```dart
  280 +final List<AssetEntity>? result = await AssetPicker.pickAssets(
  281 + context,
  282 + pickerConfig: const AssetPickerConfig(),
  283 +);
  284 +```
  285 +
  286 +Fields in `AssetPickerConfig`:
  287 +
  288 +| Name | Type | Description | Default |
  289 +|-----------------------------------|--------------------------------------------------|------------------------------------------------------------------------------------------------|-----------------------------|
  290 +| selectedAssets | `List<AssetEntity>?` | Selected assets. Prevent duplicate selection. | `null` |
  291 +| maxAssets | `int` | Maximum asset that the picker can pick. | 9 |
  292 +| pageSize | `int?` | Number of assets per page. **Must be a multiple of `gridCount`**. | 80 |
  293 +| gridThumbnailSize | `ThumbnailSize` | Thumbnail size for the grid's item. | `ThumbnailSize.square(200)` |
  294 +| pathThumbnailSize | `ThumbnailSize` | Thumbnail size for the path selector. | `ThumbnailSize.square(80)` |
  295 +| previewThumbnailSize | `ThumbnailSize?` | Preview thumbnail size in the viewer. | `null` |
  296 +| requestType | `RequestType` | Request type for picker. | `RequestType.common` |
  297 +| specialPickerType | `SpecialPickerType?` | Provides the option to integrate a custom picker type. | `null` |
  298 +| keepScrollOffset | `bool` | Whether the picker should save the scroll offset between pushes and pops. | `null` |
  299 +| sortPathDelegate | `SortPathDelegate<AssetPathEntity>?` | Path entities sort delegate for the picker, sort paths as you want. | `CommonSortPathDelegate` |
  300 +| sortPathsByModifiedDate | `bool` | Whether to allow sort delegates to sort paths with `FilterOptionGroup.containsPathModified`. | `false` |
  301 +| filterOptions | `PMFilter?` | Allow users to customize assets filter options. | `null` |
  302 +| gridCount | `int` | Grid count in picker. | 4 |
  303 +| themeColor | `Color?` | Main theme color for the picker. | `Color(0xff00bc56)` |
  304 +| pickerTheme | `ThemeData?` | Theme data provider for the picker and the viewer. | `null` |
  305 +| textDelegate | `AssetPickerTextDelegate?` | Text delegate for the picker, for customize the texts. | `AssetPickerTextDelegate()` |
  306 +| specialItemPosition | `SpecialItemPosition` | Allow users set a special item in the picker with several positions. | `SpecialItemPosition.none` |
  307 +| specialItemBuilder | `SpecialItemBuilder?` | The widget builder for the special item. | `null` |
  308 +| loadingIndicatorBuilder | `IndicatorBuilder?` | Indicates the loading status for the builder. | `null` |
  309 +| selectPredicate | `AssetSelectPredicate` | Predicate whether an asset can be selected or unselected. | `null` |
  310 +| shouldRevertGrid | `bool?` | Whether the assets grid should revert. | `null` |
  311 +| limitedPermissionOverlayPredicate | `LimitedPermissionOverlayPredicate?` | Predicate whether the limited permission overlay should be displayed. | `null` |
  312 +| pathNameBuilder | `PathNameBuilder<AssetPathEntity>?` | Build customized path (album) name with the given path entity. | `null` |
  313 +| assetsChangeCallback | `AssetsChangeCallback<AssetPathEntity>?` | The callback that will be called when the system notifies assets changes. | `null` |
  314 +| assetsChangeRefreshPredicate | `AssetsChangeRefreshPredicate<AssetPathEntity>?` | Whether assets changing should call refresh with the given call and the current selected path. | `null` |
  315 +| shouldAutoPlayPreview | `bool` | Whether the preview should auto play. | `false` |
  316 +| dragToSelect | `bool` | Whether assets selection can be done with drag gestures. | `true` |
  317 +
  318 +- When `maxAssets` equals to `1` (a.k.a. single picking mode),
  319 + use `SpecialPickerType.noPreview` will immediately select asset
  320 + clicked (pressed) by the user and popped.
  321 +- `limitedPermissionOverlayPredicate` lives without persistence,
  322 + if you want to ignore the limited preview after restart,
  323 + you'll need to integrate with your own saving methods.
  324 +
  325 +### Detailed usage
  326 +
  327 +We've put multiple common usage
  328 +with the packages in the [example](example).
  329 +You can both found `List<PickMethod> pickMethods` in
  330 +[here](example/lib/pages/multi_assets_page.dart)
  331 +and [here](example/lib/pages/single_assets_page.dart),
  332 +which provide methods in multiple picking and single picking mode.
  333 +Assets will be stored temporary and displayed at the below of the page.
  334 +
  335 +#### Display selected assets
  336 +
  337 +The `AssetEntityImage` and `AssetEntityImageProvider`
  338 +can display the thumb image of _images & videos_,
  339 +and the original data of _image_.
  340 +Use it like a common `Image` and `ImageProvider`.
  341 +
  342 +```dart
  343 +AssetEntityImage(asset, isOriginal: false);
  344 +```
  345 +
  346 +Or:
  347 +
  348 +```dart
  349 +Image(image: AssetEntityImageProvider(asset, isOriginal: false));
  350 +```
  351 +
  352 +#### Register assets change observe callback
  353 +
  354 +```dart
  355 +// Register callback.
  356 +AssetPicker.registerObserve();
  357 +
  358 +// Unregister callback.
  359 +AssetPicker.unregisterObserve();
  360 +```
  361 +
  362 +#### Upload an `AssetEntity` with a form data
  363 +
  364 +There are multiple ways to upload an `AssetEntity` with I/O related methods.
  365 +**Be aware, I/O related methods will consume performance
  366 +(typically time and memory), they should not be called frequently.**
  367 +
  368 +##### With `http`
  369 +
  370 +`http` package: https://pub.dev/packages/http
  371 +
  372 +The `http` package uses
  373 +[`MultipartFile`](https://pub.dev/documentation/http/latest/http/MultipartFile-class.html)
  374 +to handle files in requests.
  375 +
  376 +Pseudo code:
  377 +```dart
  378 +import 'package:http/http.dart' as http;
  379 +
  380 +Future<void> upload() async {
  381 + final entity = await obtainYourEntity();
  382 + final uri = Uri.https('example.com', 'create');
  383 + final request = http.MultipartRequest('POST', uri)
  384 + ..fields['test_field'] = 'test_value'
  385 + ..files.add(await multipartFileFromAssetEntity(entity));
  386 + final response = await request.send();
  387 + if (response.statusCode == 200) {
  388 + print('Uploaded!');
  389 + }
  390 +}
  391 +
  392 +Future<http.MultipartFile> multipartFileFromAssetEntity(AssetEntity entity) async {
  393 + http.MultipartFile mf;
  394 + // Using the file path.
  395 + final file = await entity.file;
  396 + if (file == null) {
  397 + throw StateError('Unable to obtain file of the entity ${entity.id}.');
  398 + }
  399 + mf = await http.MultipartFile.fromPath('test_file', file.path);
  400 + // Using the bytes.
  401 + final bytes = await entity.originBytes;
  402 + if (bytes == null) {
  403 + throw StateError('Unable to obtain bytes of the entity ${entity.id}.');
  404 + }
  405 + mf = http.MultipartFile.fromBytes('test_file', bytes);
  406 + return mf;
  407 +}
  408 +```
  409 +
  410 +##### With `dio`
  411 +
  412 +`dio` package: https://pub.dev/packages/dio
  413 +
  414 +The `dio` package also uses
  415 +[`MultipartFile`](https://pub.dev/documentation/dio/latest/dio/MultipartFile-class.html)
  416 +to handle files in requests.
  417 +
  418 +Pseudo code:
  419 +```dart
  420 +import 'package:dio/dio.dart' as dio;
  421 +
  422 +Future<void> upload() async {
  423 + final entity = await obtainYourEntity();
  424 + final uri = Uri.https('example.com', 'create');
  425 + final response = dio.Dio().requestUri(
  426 + uri,
  427 + data: dio.FormData.fromMap({
  428 + 'test_field': 'test_value',
  429 + 'test_file': await multipartFileFromAssetEntity(entity),
  430 + }),
  431 + );
  432 + print('Uploaded!');
  433 +}
  434 +
  435 +Future<dio.MultipartFile> multipartFileFromAssetEntity(AssetEntity entity) async {
  436 + dio.MultipartFile mf;
  437 + // Using the file path.
  438 + final file = await entity.file;
  439 + if (file == null) {
  440 + throw StateError('Unable to obtain file of the entity ${entity.id}.');
  441 + }
  442 + mf = await dio.MultipartFile.fromFile(file.path);
  443 + // Using the bytes.
  444 + final bytes = await entity.originBytes;
  445 + if (bytes == null) {
  446 + throw StateError('Unable to obtain bytes of the entity ${entity.id}.');
  447 + }
  448 + mf = dio.MultipartFile.fromBytes(bytes);
  449 + return mf;
  450 +}
  451 +```
  452 +
  453 +### Custom pickers
  454 +
  455 +`AssetPickerBuilderDelegate`, `AssetPickerViewerBuilderDelegate`,
  456 +`AssetPickerProvider` and `AssetPickerViewerProvider`
  457 +are all exposed and overridable.
  458 +You can extend them and use your own
  459 +type with generic type `<A: Asset, P: Path>`,
  460 +then implement abstract methods.
  461 +
  462 +To know about how to fully customize themes, widgets or layouts.
  463 +See how to customize delegates in the custom pickers page in the
  464 +[example](example/lib/customs/pickers).
  465 +
  466 +You can submit PRs to create your own implementation
  467 +if you found your implementation might be useful for others.
  468 +See [Contribute custom implementations][] for more details.
  469 +
  470 +## Frequently asked question ❔
  471 +
  472 +### Changing the default album name (`Recent` to others)
  473 +
  474 +`Recent` is the fix album name for the ALL assets on Android
  475 +since the all assets' album is not an actual album, it only represents all media data records.
  476 +
  477 +To solve that on Android, use `pathNameBuilder`, for example:
  478 +```dart
  479 +AssetPickerConfig(
  480 + pathNameBuilder: (AssetPathEntity path) => switch (path) {
  481 + final p when p.isAll => '最近',
  482 + // You can apply similar conditions to other common paths.
  483 + _ => path.name,
  484 + },
  485 +)
  486 +```
  487 +
  488 +Other albums or albums on other platforms (iOS/macOS) will follow
  489 +the configured system localization and supported localizations.
  490 +`pathNameBuilder` is available for all albums.
  491 +
  492 +### Execution failed for task ':photo_manager:compileDebugKotlin'
  493 +
  494 +See [photo_manager#561][] for more details.
  495 +
  496 +### Create `AssetEntity` from `File` or `Uint8List` (rawData)
  497 +
  498 +In order to combine this package with camera shooting or something related,
  499 +there's a solution about how to create an `AssetEntity`
  500 +with `File` or `Uint8List` object.
  501 +
  502 +```dart
  503 +final File file = your_file; // Your `File` object
  504 +final String path = file.path;
  505 +final AssetEntity fileEntity = await PhotoManager.editor.saveImageWithPath(
  506 + path,
  507 + title: basename(path),
  508 +); // Saved in the device then create an AssetEntity
  509 +
  510 +final Uint8List data = your_data; // Your `Uint8List` object
  511 +final AssetEntity imageEntity = await PhotoManager.editor.saveImage(
  512 + file.path,
  513 + title: 'title_with_extension.jpg',
  514 +); // Saved in the device then create an AssetEntity
  515 +```
  516 +
  517 +**Notice: If you don't want to keep the file in your device,
  518 +use `File` for operations as much as possible.**
  519 +Deleting an `AssetEntity` might cause system popups show:
  520 +
  521 +```dart
  522 +final List<String> result = await PhotoManager.editor.deleteWithIds(
  523 + <String>[entity.id],
  524 +);
  525 +```
  526 +
  527 +See [photo_manager#from-raw-data][]
  528 +and [photo_manager#delete-entities][]
  529 +for more details.
  530 +
  531 +### Glide warning 'Failed to find GeneratedAppGlideModule'
  532 +
  533 +```
  534 +W/Glide (21133): Failed to find GeneratedAppGlideModule.
  535 + You should include an annotationProcessor compile dependency on com.github.bumptech.glide:compiler
  536 + in you application ana a @GlideModule annotated AppGlideModule implementation
  537 + or LibraryGlideModules will be silently ignored.
  538 +```
  539 +
  540 +`Glide` needs annotation to keep singleton,
  541 +prevent conflict between instances and versions,
  542 +so while the photo manager uses `Glide` to implement image features,
  543 +the project which import this should define its own `AppGlideModule`.
  544 +See [Glide Generated API docs][] for implementation.
  545 +
  546 +## Contributors ✨
  547 +
  548 +Many thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
  549 +<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
  550 +<!-- prettier-ignore-start -->
  551 +<!-- markdownlint-disable -->
  552 +<table>
  553 + <tbody>
  554 + <tr>
  555 + <td align="center" valign="top" width="14.28%"><a href="https://blog.alexv525.com"><img src="https://avatars1.githubusercontent.com/u/15884415?v=4?s=50" width="50px;" alt="Alex Li"/><br /><sub><b>Alex Li</b></sub></a><br /><a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/commits?author=AlexV525" title="Code">💻</a> <a href="#design-AlexV525" title="Design">🎨</a> <a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/commits?author=AlexV525" title="Documentation">📖</a> <a href="#example-AlexV525" title="Examples">💡</a> <a href="#ideas-AlexV525" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-AlexV525" title="Maintenance">🚧</a> <a href="#question-AlexV525" title="Answering Questions">💬</a> <a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/pulls?q=is%3Apr+reviewed-by%3AAlexV525" title="Reviewed Pull Requests">👀</a> <a href="#a11y-AlexV525" title="Accessibility">️️️️♿️</a> <a href="#translation-AlexV525" title="Translation">🌍</a></td>
  556 + <td align="center" valign="top" width="14.28%"><a href="https://www.kikt.top"><img src="https://avatars0.githubusercontent.com/u/14145407?v=4?s=50" width="50px;" alt="Caijinglong"/><br /><sub><b>Caijinglong</b></sub></a><br /><a href="#example-CaiJingLong" title="Examples">💡</a> <a href="#ideas-CaiJingLong" title="Ideas, Planning, & Feedback">🤔</a></td>
  557 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/SchnMar"><img src="https://avatars3.githubusercontent.com/u/12902321?v=4?s=50" width="50px;" alt="Marcel Schneider"/><br /><sub><b>Marcel Schneider</b></sub></a><br /><a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/issues?q=author%3ASchnMar" title="Bug reports">🐛</a> <a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/commits?author=SchnMar" title="Code">💻</a> <a href="#ideas-SchnMar" title="Ideas, Planning, & Feedback">🤔</a></td>
  558 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/ganlanshu0211"><img src="https://avatars0.githubusercontent.com/u/9670379?v=4?s=50" width="50px;" alt="ganlanshu0211"/><br /><sub><b>ganlanshu0211</b></sub></a><br /><a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/issues?q=author%3Aganlanshu0211" title="Bug reports">🐛</a> <a href="#ideas-ganlanshu0211" title="Ideas, Planning, & Feedback">🤔</a></td>
  559 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/JasonHezz"><img src="https://avatars3.githubusercontent.com/u/15358765?v=4?s=50" width="50px;" alt="JasonHezz"/><br /><sub><b>JasonHezz</b></sub></a><br /><a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/issues?q=author%3AJasonHezz" title="Bug reports">🐛</a> <a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/commits?author=JasonHezz" title="Code">💻</a></td>
  560 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/yanivshaked"><img src="https://avatars.githubusercontent.com/u/13107481?v=4?s=50" width="50px;" alt="Yaniv Shaked"/><br /><sub><b>Yaniv Shaked</b></sub></a><br /><a href="#translation-yanivshaked" title="Translation">🌍</a> <a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/commits?author=yanivshaked" title="Code">💻</a> <a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/issues?q=author%3Ayanivshaked" title="Bug reports">🐛</a> <a href="#maintenance-yanivshaked" title="Maintenance">🚧</a></td>
  561 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/avi-yadav"><img src="https://avatars.githubusercontent.com/u/7314430?v=4?s=50" width="50px;" alt="avi-yadav"/><br /><sub><b>avi-yadav</b></sub></a><br /><a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/commits?author=avi-yadav" title="Code">💻</a></td>
  562 + </tr>
  563 + <tr>
  564 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/Letalus"><img src="https://avatars.githubusercontent.com/u/41230136?v=4?s=50" width="50px;" alt="Letalus"/><br /><sub><b>Letalus</b></sub></a><br /><a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/issues?q=author%3ALetalus" title="Bug reports">🐛</a> <a href="#translation-Letalus" title="Translation">🌍</a></td>
  565 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/greymag"><img src="https://avatars.githubusercontent.com/u/1502131?v=4?s=50" width="50px;" alt="greymag"/><br /><sub><b>greymag</b></sub></a><br /><a href="#translation-greymag" title="Translation">🌍</a></td>
  566 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/NaikSoftware"><img src="https://avatars.githubusercontent.com/u/4218994?v=4?s=50" width="50px;" alt="Nickolay Savchenko"/><br /><sub><b>Nickolay Savchenko</b></sub></a><br /><a href="#design-NaikSoftware" title="Design">🎨</a></td>
  567 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/KosukeSaigusa"><img src="https://avatars.githubusercontent.com/u/13669049?v=4?s=50" width="50px;" alt="Kosuke Saigusa"/><br /><sub><b>Kosuke Saigusa</b></sub></a><br /><a href="#translation-KosukeSaigusa" title="Translation">🌍</a></td>
  568 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/Jon-Millent"><img src="https://avatars.githubusercontent.com/u/17584565?v=4?s=50" width="50px;" alt="三闻书店"/><br /><sub><b>三闻书店</b></sub></a><br /><a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/commits?author=Jon-Millent" title="Documentation">📖</a></td>
  569 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/didiosn"><img src="https://avatars.githubusercontent.com/u/15895051?v=4?s=50" width="50px;" alt="DidiosFaust"/><br /><sub><b>DidiosFaust</b></sub></a><br /><a href="#translation-didiosn" title="Translation">🌍</a></td>
  570 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/ConanXie"><img src="https://avatars.githubusercontent.com/u/10040846?v=4?s=50" width="50px;" alt="xiejie"/><br /><sub><b>xiejie</b></sub></a><br /><a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/issues?q=author%3AConanXie" title="Bug reports">🐛</a></td>
  571 + </tr>
  572 + <tr>
  573 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/maxzod"><img src="https://avatars.githubusercontent.com/u/47630729?v=4?s=50" width="50px;" alt="Ahmed Masoud "/><br /><sub><b>Ahmed Masoud </b></sub></a><br /><a href="#translation-maxzod" title="Translation">🌍</a></td>
  574 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/luomo-pro"><img src="https://avatars.githubusercontent.com/u/41097395?v=4?s=50" width="50px;" alt="luomo-pro"/><br /><sub><b>luomo-pro</b></sub></a><br /><a href="#a11y-luomo-pro" title="Accessibility">️️️️♿️</a> <a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/issues?q=author%3Aluomo-pro" title="Bug reports">🐛</a></td>
  575 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/paigupai"><img src="https://avatars.githubusercontent.com/u/44311361?v=4?s=50" width="50px;" alt="paigupai"/><br /><sub><b>paigupai</b></sub></a><br /><a href="#translation-paigupai" title="Translation">🌍</a></td>
  576 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/taqiabdulaziz"><img src="https://avatars.githubusercontent.com/u/30410316?v=4?s=50" width="50px;" alt="Muhammad Taqi Abdul Aziz"/><br /><sub><b>Muhammad Taqi Abdul Aziz</b></sub></a><br /><a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/commits?author=taqiabdulaziz" title="Documentation">📖</a></td>
  577 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/hellohejinyu"><img src="https://avatars.githubusercontent.com/u/8766034?v=4?s=50" width="50px;" alt="何锦余"/><br /><sub><b>何锦余</b></sub></a><br /><a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/issues?q=author%3Ahellohejinyu" title="Bug reports">🐛</a></td>
  578 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/leonpesdk"><img src="https://avatars.githubusercontent.com/u/57394644?v=4?s=50" width="50px;" alt="Leon Dudlik"/><br /><sub><b>Leon Dudlik</b></sub></a><br /><a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/issues?q=author%3Aleonpesdk" title="Bug reports">🐛</a></td>
  579 + <td align="center" valign="top" width="14.28%"><a href="https://www.legoffmael.fr"><img src="https://avatars.githubusercontent.com/u/22376981?v=4?s=50" width="50px;" alt="Maël"/><br /><sub><b>Maël</b></sub></a><br /><a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/commits?author=LeGoffMael" title="Code">💻</a> <a href="#maintenance-LeGoffMael" title="Maintenance">🚧</a></td>
  580 + </tr>
  581 + <tr>
  582 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/dddrop"><img src="https://avatars.githubusercontent.com/u/5361175?v=4?s=50" width="50px;" alt="dddrop"/><br /><sub><b>dddrop</b></sub></a><br /><a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/commits?author=dddrop" title="Code">💻</a></td>
  583 + <td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/loinp"><img src="https://avatars.githubusercontent.com/u/34020090?v=4?s=50" width="50px;" alt="Nguyen Phuc Loi"/><br /><sub><b>Nguyen Phuc Loi</b></sub></a><br /><a href="#translation-nploi" title="Translation">🌍</a></td>
  584 + <td align="center" valign="top" width="14.28%"><a href="https://sqlturk.wordpress.com/"><img src="https://avatars.githubusercontent.com/u/12383547?v=4?s=50" width="50px;" alt="Cevheri"/><br /><sub><b>Cevheri</b></sub></a><br /><a href="#translation-cevheri" title="Translation">🌍</a></td>
  585 + <td align="center" valign="top" width="14.28%"><a href="https://velog.io/@hee_mm_"><img src="https://avatars.githubusercontent.com/u/48482259?v=4?s=50" width="50px;" alt="mirimhee"/><br /><sub><b>mirimhee</b></sub></a><br /><a href="#translation-LIMMIHEE" title="Translation">🌍</a></td>
  586 + <td align="center" valign="top" width="14.28%"><a href="https://amoshk.top"><img src="https://avatars.githubusercontent.com/u/32262985?v=4?s=50" width="50px;" alt="Amos"/><br /><sub><b>Amos</b></sub></a><br /><a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/issues?q=author%3AAmosHuKe" title="Bug reports">🐛</a></td>
  587 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/Dimilkalathiya"><img src="https://avatars.githubusercontent.com/u/102401667?v=4?s=50" width="50px;" alt="Dimil Kalathiya"/><br /><sub><b>Dimil Kalathiya</b></sub></a><br /><a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/commits?author=Dimilkalathiya" title="Code">💻</a></td>
  588 + <td align="center" valign="top" width="14.28%"><a href="http://about.me/gasol"><img src="https://avatars.githubusercontent.com/u/108053?v=4?s=50" width="50px;" alt="Gasol Wu"/><br /><sub><b>Gasol Wu</b></sub></a><br /><a href="#translation-Gasol" title="Translation">🌍</a></td>
  589 + </tr>
  590 + <tr>
  591 + <td align="center" valign="top" width="14.28%"><a href="https://github.com/WeiJun0507"><img src="https://avatars.githubusercontent.com/u/66726409?v=4?s=50" width="50px;" alt="Wei Jun"/><br /><sub><b>Wei Jun</b></sub></a><br /><a href="#business-WeiJun0507" title="Business development">💼</a> <a href="https://github.com/fluttercandies/flutter_wechat_assets_picker/commits?author=WeiJun0507" title="Code">💻</a> <a href="#ideas-WeiJun0507" title="Ideas, Planning, & Feedback">🤔</a></td>
  592 + </tr>
  593 + </tbody>
  594 +</table>
  595 +
  596 +<!-- markdownlint-restore -->
  597 +<!-- prettier-ignore-end -->
  598 +
  599 +<!-- ALL-CONTRIBUTORS-LIST:END -->
  600 +This project follows the
  601 +[all-contributors](https://github.com/all-contributors/all-contributors) specification.
  602 +Contributions of any kind welcomed!!
  603 +
  604 +## Credits
  605 +
  606 +> Every aspect of IntelliJ IDEA has been designed to maximize developer productivity.
  607 +Together, intelligent coding assistance and ergonomic design make development not only productive but also enjoyable.
  608 +
  609 +Thanks to [JetBrains](https://www.jetbrains.com/?from=fluttercandies)
  610 +for allocating free open-source licenses for IDEs
  611 +such as [IntelliJ IDEA](https://www.jetbrains.com/idea/?from=fluttercandies).
  612 +
  613 +[<img src="https://github.com/fluttercandies/flutter_wechat_assets_picker/raw/main/.github/jetbrains-variant.png" width="200"/>](https://www.jetbrains.com/?from=fluttercandies)
  614 +
  615 +
  616 +[photo_manager pub]: https://pub.dev/packages/photo_manager
  617 +[extended_image pub]: https://pub.dev/packages/extended_image
  618 +[provider pub]: https://pub.dev/packages/provider
  619 +[video_player pub]: https://pub.dev/packages/video_player
  620 +[wechat_camera_picker pub]: https://pub.dev/packages/wechat_camera_picker
  621 +[Migration Guide]: https://github.com/fluttercandies/flutter_wechat_assets_picker/blob/main/guides/migration_guide.md
  622 +[photo_manager's API docs]: https://pub.dev/documentation/photo_manager/latest/
  623 +[Glide Generated API docs]: https://sjudd.github.io/glide/doc/generatedapi.html
  624 +[Contribute custom implementations]: https://github.com/fluttercandies/flutter_wechat_assets_picker/blob/main/example/lib/customs/CONTRIBUTING.md
  625 +[photo_manager#561]: https://github.com/fluttercandies/flutter_photo_manager/issues/561
  626 +[photo_manager#from-raw-data]: https://github.com/fluttercandies/flutter_photo_manager#from-raw-data
  627 +[photo_manager#delete-entities]: https://github.com/fluttercandies/flutter_photo_manager#delete-entities
  1 +include: package:flutter_lints/flutter.yaml
  2 +
  3 +analyzer:
  4 + errors:
  5 + deprecated_member_use: ignore
  6 + deprecated_member_use_from_same_package: ignore
  7 +
  8 +linter:
  9 + rules:
  10 + always_declare_return_types: true
  11 + always_put_control_body_on_new_line: true
  12 + avoid_print: true
  13 + avoid_renaming_method_parameters: true
  14 + avoid_unnecessary_containers: true
  15 + avoid_void_async: true
  16 + curly_braces_in_flow_control_structures: true
  17 + directives_ordering: true
  18 + flutter_style_todos: true
  19 + library_private_types_in_public_api: false
  20 + overridden_fields: false
  21 + prefer_const_constructors: true
  22 + prefer_const_constructors_in_immutables: false
  23 + prefer_final_fields: true
  24 + prefer_final_in_for_each: true
  25 + prefer_final_locals: true
  26 + prefer_single_quotes: true
  27 + require_trailing_commas: true
  28 + sort_child_properties_last: true
  29 + sort_constructors_first: true
  30 + sort_unnamed_constructors_first: true
  31 + unnecessary_await_in_return: true
  32 + unnecessary_breaks: true
  33 + unnecessary_late: true
  34 + unnecessary_parenthesis: true
  35 + use_build_context_synchronously: false
  36 + void_checks: true
  1 +<!-- Copyright 2019 The FlutterCandies author. All rights reserved.
  2 +Use of this source code is governed by an Apache license
  3 +that can be found in the LICENSE file. -->
  4 +
  5 +# WeChat Assets Picker example
  6 +
  7 +This is the example for the `wechat_assets_picker` package.
  8 +
  9 +We've put multiple common usage
  10 +with the packages in the example.
  11 +You can both found `List<PickMethod> pickMethods` in
  12 +[here](lib/pages/multi_assets_page.dart)
  13 +and [here](lib/pages/single_assets_page.dart),
  14 +which provide methods in multiple picking and single picking mode.
  15 +Assets will be stored temporary and displayed at the below of the page.
  1 +include: ../analysis_options.yaml
  2 +
  3 +analyzer:
  4 + exclude:
  5 + - lib/l10n/gen/*.dart
  6 +
  7 +linter:
  8 + rules:
  9 + use_build_context_synchronously: false
  1 +plugins {
  2 + id "com.android.application"
  3 + id "kotlin-android"
  4 + id "kotlin-kapt"
  5 + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
  6 + id "dev.flutter.flutter-gradle-plugin"
  7 +}
  8 +
  9 +def flutterVersionCode = null
  10 +def flutterVersionName = null
  11 +if (flutter.hasProperty('versionCode')) {
  12 + flutterVersionCode = flutter.versionCode
  13 +}
  14 +if (flutter.hasProperty('versionName')) {
  15 + flutterVersionName = flutter.versionName
  16 +}
  17 +
  18 +if (flutterVersionCode == null || flutterVersionName == null) {
  19 + def localProperties = new Properties()
  20 + rootProject.file('local.properties').withReader('UTF-8') { reader ->
  21 + localProperties.load(reader)
  22 + }
  23 +
  24 + if (flutterVersionCode == null) {
  25 + flutterVersionCode = localProperties.getProperty('flutter.versionCode')
  26 + }
  27 + if (flutterVersionName == null) {
  28 + flutterVersionName = localProperties.getProperty('flutter.versionName')
  29 + }
  30 +}
  31 +
  32 +android {
  33 + namespace "com.fluttercandies.wechatAssetsPickerExample"
  34 + compileSdk flutter.compileSdkVersion
  35 + ndkVersion flutter.ndkVersion
  36 +
  37 + defaultConfig {
  38 + applicationId = "com.fluttercandies.wechatAssetsPickerExample"
  39 + minSdk 21
  40 + targetSdk flutter.targetSdkVersion
  41 + versionCode flutterVersionCode.toInteger()
  42 + versionName flutterVersionName
  43 + }
  44 +
  45 + sourceSets {
  46 + main.java.srcDirs += 'src/main/kotlin'
  47 + }
  48 +
  49 + kotlinOptions {
  50 + jvmTarget = '17'
  51 + }
  52 +
  53 + compileOptions {
  54 + // Sets Java compatibility to Java 17
  55 + sourceCompatibility JavaVersion.VERSION_17
  56 + targetCompatibility JavaVersion.VERSION_17
  57 + }
  58 +
  59 + signingConfigs {
  60 + forAll {
  61 + storeFile file("${rootDir.absolutePath}/key.jks")
  62 + storePassword 'picker'
  63 + keyAlias 'picker'
  64 + keyPassword 'picker'
  65 + }
  66 + }
  67 +
  68 + buildTypes {
  69 + debug {
  70 + signingConfig signingConfigs.forAll
  71 + }
  72 + profile {
  73 + signingConfig signingConfigs.forAll
  74 + }
  75 + release {
  76 + signingConfig signingConfigs.forAll
  77 + }
  78 + }
  79 +}
  80 +
  81 +flutter {
  82 + source '../..'
  83 +}
  84 +
  85 +dependencies {
  86 + implementation 'com.github.bumptech.glide:glide:4.15.0'
  87 + kapt 'com.github.bumptech.glide:compiler:4.15.0'
  88 +}
  1 +<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  2 + <uses-permission android:name="android.permission.INTERNET" />
  3 + <uses-permission
  4 + android:name="android.permission.WRITE_EXTERNAL_STORAGE"
  5 + android:maxSdkVersion="28"/>
  6 +
  7 + <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
  8 + <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
  9 + <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
  10 + <uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
  11 +
  12 + <application
  13 + android:label="Wechat Assets Picker Example"
  14 + android:name="${applicationName}"
  15 + android:icon="@mipmap/ic_launcher"
  16 + android:allowBackup="false">
  17 + <activity
  18 + android:name=".MainActivity"
  19 + android:exported="true"
  20 + android:launchMode="singleTop"
  21 + android:theme="@style/LaunchTheme"
  22 + android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
  23 + android:hardwareAccelerated="true"
  24 + android:windowSoftInputMode="adjustResize">
  25 + <!-- Specifies an Android theme to apply to this Activity as soon as
  26 + the Android process has started. This theme is visible to the user
  27 + while the Flutter UI initializes. After that, this theme continues
  28 + to determine the Window background behind the Flutter UI. -->
  29 + <meta-data
  30 + android:name="io.flutter.embedding.android.NormalTheme"
  31 + android:resource="@style/NormalTheme"
  32 + />
  33 + <intent-filter>
  34 + <action android:name="android.intent.action.MAIN"/>
  35 + <category android:name="android.intent.category.LAUNCHER"/>
  36 + </intent-filter>
  37 + </activity>
  38 + <!-- Don't delete the meta-data below.
  39 + This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
  40 + <meta-data
  41 + android:name="flutterEmbedding"
  42 + android:value="2" />
  43 + </application>
  44 + <!-- Required to query activities that can process text, see:
  45 + https://developer.android.com/training/package-visibility?hl=en and
  46 + https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
  47 +
  48 + In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
  49 + <queries>
  50 + <intent>
  51 + <action android:name="android.intent.action.PROCESS_TEXT"/>
  52 + <data android:mimeType="text/plain"/>
  53 + </intent>
  54 + </queries>
  55 +</manifest>
  1 +package io.flutter.plugins;
  2 +
  3 +import androidx.annotation.Keep;
  4 +import androidx.annotation.NonNull;
  5 +import io.flutter.Log;
  6 +
  7 +import io.flutter.embedding.engine.FlutterEngine;
  8 +
  9 +/**
  10 + * Generated file. Do not edit.
  11 + * This file is generated by the Flutter tool based on the
  12 + * plugins that support the Android platform.
  13 + */
  14 +@Keep
  15 +public final class GeneratedPluginRegistrant {
  16 + private static final String TAG = "GeneratedPluginRegistrant";
  17 + public static void registerWith(@NonNull FlutterEngine flutterEngine) {
  18 + try {
  19 + flutterEngine.getPlugins().add(new io.flutter.plugins.camera.CameraPlugin());
  20 + } catch (Exception e) {
  21 + Log.e(TAG, "Error registering plugin camera_android, io.flutter.plugins.camera.CameraPlugin", e);
  22 + }
  23 + try {
  24 + flutterEngine.getPlugins().add(new io.flutter.plugins.flutter_plugin_android_lifecycle.FlutterAndroidLifecyclePlugin());
  25 + } catch (Exception e) {
  26 + Log.e(TAG, "Error registering plugin flutter_plugin_android_lifecycle, io.flutter.plugins.flutter_plugin_android_lifecycle.FlutterAndroidLifecyclePlugin", e);
  27 + }
  28 + try {
  29 + flutterEngine.getPlugins().add(new dev.fluttercommunity.plus.packageinfo.PackageInfoPlugin());
  30 + } catch (Exception e) {
  31 + Log.e(TAG, "Error registering plugin package_info_plus, dev.fluttercommunity.plus.packageinfo.PackageInfoPlugin", e);
  32 + }
  33 + try {
  34 + flutterEngine.getPlugins().add(new io.flutter.plugins.pathprovider.PathProviderPlugin());
  35 + } catch (Exception e) {
  36 + Log.e(TAG, "Error registering plugin path_provider_android, io.flutter.plugins.pathprovider.PathProviderPlugin", e);
  37 + }
  38 + try {
  39 + flutterEngine.getPlugins().add(new com.fluttercandies.photo_manager.PhotoManagerPlugin());
  40 + } catch (Exception e) {
  41 + Log.e(TAG, "Error registering plugin photo_manager, com.fluttercandies.photo_manager.PhotoManagerPlugin", e);
  42 + }
  43 + try {
  44 + flutterEngine.getPlugins().add(new dev.fluttercommunity.plus.sensors.SensorsPlugin());
  45 + } catch (Exception e) {
  46 + Log.e(TAG, "Error registering plugin sensors_plus, dev.fluttercommunity.plus.sensors.SensorsPlugin", e);
  47 + }
  48 + try {
  49 + flutterEngine.getPlugins().add(new io.flutter.plugins.videoplayer.VideoPlayerPlugin());
  50 + } catch (Exception e) {
  51 + Log.e(TAG, "Error registering plugin video_player_android, io.flutter.plugins.videoplayer.VideoPlayerPlugin", e);
  52 + }
  53 + }
  54 +}
  1 +package com.fluttercandies.wechatAssetsPickerExample;
  2 +
  3 +import com.bumptech.glide.annotation.GlideModule;
  4 +import com.bumptech.glide.module.AppGlideModule;
  5 +
  6 +@GlideModule
  7 +public class ExampleAppGlideModule extends AppGlideModule {
  8 +}
  1 +package com.fluttercandies.wechatAssetsPickerExample
  2 +
  3 +import io.flutter.embedding.android.FlutterActivity
  4 +
  5 +class MainActivity: FlutterActivity() {
  6 + // The default activity that extends flutter's activity.
  7 +}
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<!-- Modify this file to customize your launch splash screen -->
  3 +<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  4 + <item android:drawable="?android:colorBackground" />
  5 +
  6 + <!-- You can insert your own image assets here -->
  7 + <!-- <item>
  8 + <bitmap
  9 + android:gravity="center"
  10 + android:src="@mipmap/launch_image" />
  11 + </item> -->
  12 +</layer-list>
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<!-- Modify this file to customize your launch splash screen -->
  3 +<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  4 + <item android:drawable="@android:color/white" />
  5 +
  6 + <!-- You can insert your own image assets here -->
  7 + <!-- <item>
  8 + <bitmap
  9 + android:gravity="center"
  10 + android:src="@mipmap/launch_image" />
  11 + </item> -->
  12 +</layer-list>
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
  4 + <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
  5 + <!-- Show a splash screen on the activity. Automatically removed when
  6 + the Flutter engine draws its first frame -->
  7 + <item name="android:windowBackground">@drawable/launch_background</item>
  8 + </style>
  9 + <!-- Theme applied to the Android Window as soon as the process has started.
  10 + This theme determines the color of the Android Window while your
  11 + Flutter UI initializes, as well as behind your Flutter UI while its
  12 + running.
  13 +
  14 + This Theme is only used starting with V2 of Flutter's Android embedding. -->
  15 + <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
  16 + <item name="android:windowBackground">?android:colorBackground</item>
  17 + </style>
  18 +</resources>
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
  4 + <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
  5 + <!-- Show a splash screen on the activity. Automatically removed when
  6 + the Flutter engine draws its first frame -->
  7 + <item name="android:windowBackground">@drawable/launch_background</item>
  8 + </style>
  9 + <!-- Theme applied to the Android Window as soon as the process has started.
  10 + This theme determines the color of the Android Window while your
  11 + Flutter UI initializes, as well as behind your Flutter UI while its
  12 + running.
  13 +
  14 + This Theme is only used starting with V2 of Flutter's Android embedding. -->
  15 + <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
  16 + <item name="android:windowBackground">?android:colorBackground</item>
  17 + </style>
  18 +</resources>
  1 +allprojects {
  2 + repositories {
  3 + google()
  4 + mavenCentral()
  5 + }
  6 +}
  7 +
  8 +rootProject.buildDir = '../build'
  9 +subprojects {
  10 + project.buildDir = "${rootProject.buildDir}/${project.name}"
  11 +}
  12 +subprojects {
  13 + project.evaluationDependsOn(':app')
  14 +}
  15 +
  16 +tasks.register("clean", Delete) {
  17 + delete rootProject.buildDir
  18 +}
  1 +org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
  2 +android.useAndroidX=true
  3 +android.enableJetifier=true
  1 +distributionBase=GRADLE_USER_HOME
  2 +distributionPath=wrapper/dists
  3 +zipStoreBase=GRADLE_USER_HOME
  4 +zipStorePath=wrapper/dists
  5 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
  1 +sdk.dir=/Users/wangdongni/Library/Android/sdk
  2 +flutter.sdk=/Users/wangdongni/fvm/versions/custom_3.27.4-ohos-dev
  1 +pluginManagement {
  2 + def flutterSdkPath = {
  3 + def properties = new Properties()
  4 + file("local.properties").withInputStream { properties.load(it) }
  5 + def flutterSdkPath = properties.getProperty("flutter.sdk")
  6 + assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
  7 + return flutterSdkPath
  8 + }()
  9 +
  10 + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
  11 +
  12 + repositories {
  13 + google()
  14 + mavenCentral()
  15 + gradlePluginPortal()
  16 + }
  17 +}
  18 +
  19 +plugins {
  20 + id "dev.flutter.flutter-plugin-loader" version "1.0.0"
  21 + id "com.android.application" version "8.9.1" apply false
  22 + id "com.android.library" version "8.9.1" apply false
  23 + id "org.jetbrains.kotlin.android" version "2.1.20" apply false
  24 +}
  25 +
  26 +include ":app"
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>CFBundleDevelopmentRegion</key>
  6 + <string>en</string>
  7 + <key>CFBundleExecutable</key>
  8 + <string>App</string>
  9 + <key>CFBundleIdentifier</key>
  10 + <string>io.flutter.flutter.app</string>
  11 + <key>CFBundleInfoDictionaryVersion</key>
  12 + <string>6.0</string>
  13 + <key>CFBundleName</key>
  14 + <string>App</string>
  15 + <key>CFBundlePackageType</key>
  16 + <string>FMWK</string>
  17 + <key>CFBundleShortVersionString</key>
  18 + <string>1.0</string>
  19 + <key>CFBundleSignature</key>
  20 + <string>????</string>
  21 + <key>CFBundleVersion</key>
  22 + <string>1.0</string>
  23 + <key>MinimumOSVersion</key>
  24 + <string>12.0</string>
  25 +</dict>
  26 +</plist>
  1 +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
  2 +#include "Generated.xcconfig"
  1 +// This is a generated file; do not edit or check into version control.
  2 +FLUTTER_ROOT=/Users/wangdongni/fvm/versions/custom_3.27.4-ohos-dev
  3 +FLUTTER_APPLICATION_PATH=/Users/wangdongni/Desktop/Flutter-ReserveApp/library/wechat_assets_picker-9.8.0/example
  4 +COCOAPODS_PARALLEL_CODE_SIGN=true
  5 +FLUTTER_TARGET=lib/main.dart
  6 +FLUTTER_BUILD_DIR=build
  7 +FLUTTER_BUILD_NAME=9.8.0
  8 +FLUTTER_BUILD_NUMBER=69
  9 +EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
  10 +EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
  11 +DART_OBFUSCATION=false
  12 +TRACK_WIDGET_CREATION=true
  13 +TREE_SHAKE_ICONS=false
  14 +PACKAGE_CONFIG=.dart_tool/package_config.json
  1 +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
  2 +#include "Generated.xcconfig"
  1 +#!/bin/sh
  2 +# This is a generated file; do not edit or check into version control.
  3 +export "FLUTTER_ROOT=/Users/wangdongni/fvm/versions/custom_3.27.4-ohos-dev"
  4 +export "FLUTTER_APPLICATION_PATH=/Users/wangdongni/Desktop/Flutter-ReserveApp/library/wechat_assets_picker-9.8.0/example"
  5 +export "COCOAPODS_PARALLEL_CODE_SIGN=true"
  6 +export "FLUTTER_TARGET=lib/main.dart"
  7 +export "FLUTTER_BUILD_DIR=build"
  8 +export "FLUTTER_BUILD_NAME=9.8.0"
  9 +export "FLUTTER_BUILD_NUMBER=69"
  10 +export "DART_OBFUSCATION=false"
  11 +export "TRACK_WIDGET_CREATION=true"
  12 +export "TREE_SHAKE_ICONS=false"
  13 +export "PACKAGE_CONFIG=.dart_tool/package_config.json"
  1 +# Uncomment this line to define a global platform for your project
  2 +# platform :ios, '12.0'
  3 +
  4 +# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
  5 +ENV['COCOAPODS_DISABLE_STATS'] = 'true'
  6 +
  7 +project 'Runner', {
  8 + 'Debug' => :debug,
  9 + 'Profile' => :release,
  10 + 'Release' => :release,
  11 +}
  12 +
  13 +def flutter_root
  14 + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
  15 + unless File.exist?(generated_xcode_build_settings_path)
  16 + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
  17 + end
  18 +
  19 + File.foreach(generated_xcode_build_settings_path) do |line|
  20 + matches = line.match(/FLUTTER_ROOT\=(.*)/)
  21 + return matches[1].strip if matches
  22 + end
  23 + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
  24 +end
  25 +
  26 +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
  27 +
  28 +flutter_ios_podfile_setup
  29 +
  30 +target 'Runner' do
  31 + use_frameworks!
  32 + use_modular_headers!
  33 +
  34 + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
  35 +end
  36 +
  37 +post_install do |installer|
  38 + installer.pods_project.targets.each do |target|
  39 + flutter_additional_ios_build_settings(target)
  40 + end
  41 +end
  1 +// !$*UTF8*$!
  2 +{
  3 + archiveVersion = 1;
  4 + classes = {
  5 + };
  6 + objectVersion = 54;
  7 + objects = {
  8 +
  9 +/* Begin PBXBuildFile section */
  10 + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
  11 + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
  12 + 513FA762C8C9C7254396DC7C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65B67F314727E97056D6FB02 /* Pods_Runner.framework */; };
  13 + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
  14 + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
  15 + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
  16 + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
  17 +/* End PBXBuildFile section */
  18 +
  19 +/* Begin PBXCopyFilesBuildPhase section */
  20 + 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
  21 + isa = PBXCopyFilesBuildPhase;
  22 + buildActionMask = 2147483647;
  23 + dstPath = "";
  24 + dstSubfolderSpec = 10;
  25 + files = (
  26 + );
  27 + name = "Embed Frameworks";
  28 + runOnlyForDeploymentPostprocessing = 0;
  29 + };
  30 +/* End PBXCopyFilesBuildPhase section */
  31 +
  32 +/* Begin PBXFileReference section */
  33 + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
  34 + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
  35 + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
  36 + 65B67F314727E97056D6FB02 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
  37 + 6B0C8420452B45A5D1F1C0C7 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
  38 + 6C1693957F33351E0284D719 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
  39 + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
  40 + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
  41 + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
  42 + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
  43 + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
  44 + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
  45 + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
  46 + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
  47 + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
  48 + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
  49 + FF5A0AA64F3B1C88D3552E39 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
  50 +/* End PBXFileReference section */
  51 +
  52 +/* Begin PBXFrameworksBuildPhase section */
  53 + 97C146EB1CF9000F007C117D /* Frameworks */ = {
  54 + isa = PBXFrameworksBuildPhase;
  55 + buildActionMask = 2147483647;
  56 + files = (
  57 + 513FA762C8C9C7254396DC7C /* Pods_Runner.framework in Frameworks */,
  58 + );
  59 + runOnlyForDeploymentPostprocessing = 0;
  60 + };
  61 +/* End PBXFrameworksBuildPhase section */
  62 +
  63 +/* Begin PBXGroup section */
  64 + 075E26373E1C2C8E97B8BDA5 /* Frameworks */ = {
  65 + isa = PBXGroup;
  66 + children = (
  67 + 65B67F314727E97056D6FB02 /* Pods_Runner.framework */,
  68 + );
  69 + name = Frameworks;
  70 + sourceTree = "<group>";
  71 + };
  72 + 9482DB91E3C799F148919200 /* Pods */ = {
  73 + isa = PBXGroup;
  74 + children = (
  75 + 6C1693957F33351E0284D719 /* Pods-Runner.debug.xcconfig */,
  76 + FF5A0AA64F3B1C88D3552E39 /* Pods-Runner.release.xcconfig */,
  77 + 6B0C8420452B45A5D1F1C0C7 /* Pods-Runner.profile.xcconfig */,
  78 + );
  79 + path = Pods;
  80 + sourceTree = "<group>";
  81 + };
  82 + 9740EEB11CF90186004384FC /* Flutter */ = {
  83 + isa = PBXGroup;
  84 + children = (
  85 + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
  86 + 9740EEB21CF90195004384FC /* Debug.xcconfig */,
  87 + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
  88 + 9740EEB31CF90195004384FC /* Generated.xcconfig */,
  89 + );
  90 + name = Flutter;
  91 + sourceTree = "<group>";
  92 + };
  93 + 97C146E51CF9000F007C117D = {
  94 + isa = PBXGroup;
  95 + children = (
  96 + 9740EEB11CF90186004384FC /* Flutter */,
  97 + 97C146F01CF9000F007C117D /* Runner */,
  98 + 97C146EF1CF9000F007C117D /* Products */,
  99 + 9482DB91E3C799F148919200 /* Pods */,
  100 + 075E26373E1C2C8E97B8BDA5 /* Frameworks */,
  101 + );
  102 + sourceTree = "<group>";
  103 + };
  104 + 97C146EF1CF9000F007C117D /* Products */ = {
  105 + isa = PBXGroup;
  106 + children = (
  107 + 97C146EE1CF9000F007C117D /* Runner.app */,
  108 + );
  109 + name = Products;
  110 + sourceTree = "<group>";
  111 + };
  112 + 97C146F01CF9000F007C117D /* Runner */ = {
  113 + isa = PBXGroup;
  114 + children = (
  115 + 97C146FA1CF9000F007C117D /* Main.storyboard */,
  116 + 97C146FD1CF9000F007C117D /* Assets.xcassets */,
  117 + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
  118 + 97C147021CF9000F007C117D /* Info.plist */,
  119 + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
  120 + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
  121 + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
  122 + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
  123 + );
  124 + path = Runner;
  125 + sourceTree = "<group>";
  126 + };
  127 +/* End PBXGroup section */
  128 +
  129 +/* Begin PBXNativeTarget section */
  130 + 97C146ED1CF9000F007C117D /* Runner */ = {
  131 + isa = PBXNativeTarget;
  132 + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
  133 + buildPhases = (
  134 + 71ACE8DF3F7938AC5EF5C276 /* [CP] Check Pods Manifest.lock */,
  135 + 9740EEB61CF901F6004384FC /* Run Script */,
  136 + 97C146EA1CF9000F007C117D /* Sources */,
  137 + 97C146EB1CF9000F007C117D /* Frameworks */,
  138 + 97C146EC1CF9000F007C117D /* Resources */,
  139 + 9705A1C41CF9048500538489 /* Embed Frameworks */,
  140 + 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
  141 + 950F336F7D4BCE35DBE7FE4C /* [CP] Embed Pods Frameworks */,
  142 + );
  143 + buildRules = (
  144 + );
  145 + dependencies = (
  146 + );
  147 + name = Runner;
  148 + productName = Runner;
  149 + productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
  150 + productType = "com.apple.product-type.application";
  151 + };
  152 +/* End PBXNativeTarget section */
  153 +
  154 +/* Begin PBXProject section */
  155 + 97C146E61CF9000F007C117D /* Project object */ = {
  156 + isa = PBXProject;
  157 + attributes = {
  158 + BuildIndependentTargetsInParallel = YES;
  159 + LastUpgradeCheck = 1510;
  160 + ORGANIZATIONNAME = "";
  161 + TargetAttributes = {
  162 + 97C146ED1CF9000F007C117D = {
  163 + CreatedOnToolsVersion = 7.3.1;
  164 + LastSwiftMigration = 1100;
  165 + };
  166 + };
  167 + };
  168 + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
  169 + compatibilityVersion = "Xcode 9.3";
  170 + developmentRegion = en;
  171 + hasScannedForEncodings = 0;
  172 + knownRegions = (
  173 + en,
  174 + Base,
  175 + );
  176 + mainGroup = 97C146E51CF9000F007C117D;
  177 + productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
  178 + projectDirPath = "";
  179 + projectRoot = "";
  180 + targets = (
  181 + 97C146ED1CF9000F007C117D /* Runner */,
  182 + );
  183 + };
  184 +/* End PBXProject section */
  185 +
  186 +/* Begin PBXResourcesBuildPhase section */
  187 + 97C146EC1CF9000F007C117D /* Resources */ = {
  188 + isa = PBXResourcesBuildPhase;
  189 + buildActionMask = 2147483647;
  190 + files = (
  191 + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
  192 + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
  193 + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
  194 + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
  195 + );
  196 + runOnlyForDeploymentPostprocessing = 0;
  197 + };
  198 +/* End PBXResourcesBuildPhase section */
  199 +
  200 +/* Begin PBXShellScriptBuildPhase section */
  201 + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
  202 + isa = PBXShellScriptBuildPhase;
  203 + alwaysOutOfDate = 1;
  204 + buildActionMask = 2147483647;
  205 + files = (
  206 + );
  207 + inputPaths = (
  208 + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
  209 + );
  210 + name = "Thin Binary";
  211 + outputPaths = (
  212 + );
  213 + runOnlyForDeploymentPostprocessing = 0;
  214 + shellPath = /bin/sh;
  215 + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
  216 + };
  217 + 71ACE8DF3F7938AC5EF5C276 /* [CP] Check Pods Manifest.lock */ = {
  218 + isa = PBXShellScriptBuildPhase;
  219 + buildActionMask = 2147483647;
  220 + files = (
  221 + );
  222 + inputFileListPaths = (
  223 + );
  224 + inputPaths = (
  225 + "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
  226 + "${PODS_ROOT}/Manifest.lock",
  227 + );
  228 + name = "[CP] Check Pods Manifest.lock";
  229 + outputFileListPaths = (
  230 + );
  231 + outputPaths = (
  232 + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
  233 + );
  234 + runOnlyForDeploymentPostprocessing = 0;
  235 + shellPath = /bin/sh;
  236 + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
  237 + showEnvVarsInLog = 0;
  238 + };
  239 + 950F336F7D4BCE35DBE7FE4C /* [CP] Embed Pods Frameworks */ = {
  240 + isa = PBXShellScriptBuildPhase;
  241 + buildActionMask = 2147483647;
  242 + files = (
  243 + );
  244 + inputFileListPaths = (
  245 + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
  246 + );
  247 + name = "[CP] Embed Pods Frameworks";
  248 + outputFileListPaths = (
  249 + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
  250 + );
  251 + runOnlyForDeploymentPostprocessing = 0;
  252 + shellPath = /bin/sh;
  253 + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
  254 + showEnvVarsInLog = 0;
  255 + };
  256 + 9740EEB61CF901F6004384FC /* Run Script */ = {
  257 + isa = PBXShellScriptBuildPhase;
  258 + alwaysOutOfDate = 1;
  259 + buildActionMask = 2147483647;
  260 + files = (
  261 + );
  262 + inputPaths = (
  263 + );
  264 + name = "Run Script";
  265 + outputPaths = (
  266 + );
  267 + runOnlyForDeploymentPostprocessing = 0;
  268 + shellPath = /bin/sh;
  269 + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
  270 + };
  271 +/* End PBXShellScriptBuildPhase section */
  272 +
  273 +/* Begin PBXSourcesBuildPhase section */
  274 + 97C146EA1CF9000F007C117D /* Sources */ = {
  275 + isa = PBXSourcesBuildPhase;
  276 + buildActionMask = 2147483647;
  277 + files = (
  278 + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
  279 + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
  280 + );
  281 + runOnlyForDeploymentPostprocessing = 0;
  282 + };
  283 +/* End PBXSourcesBuildPhase section */
  284 +
  285 +/* Begin PBXVariantGroup section */
  286 + 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
  287 + isa = PBXVariantGroup;
  288 + children = (
  289 + 97C146FB1CF9000F007C117D /* Base */,
  290 + );
  291 + name = Main.storyboard;
  292 + sourceTree = "<group>";
  293 + };
  294 + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
  295 + isa = PBXVariantGroup;
  296 + children = (
  297 + 97C147001CF9000F007C117D /* Base */,
  298 + );
  299 + name = LaunchScreen.storyboard;
  300 + sourceTree = "<group>";
  301 + };
  302 +/* End PBXVariantGroup section */
  303 +
  304 +/* Begin XCBuildConfiguration section */
  305 + 249021D3217E4FDB00AE95B9 /* Profile */ = {
  306 + isa = XCBuildConfiguration;
  307 + buildSettings = {
  308 + ALWAYS_SEARCH_USER_PATHS = NO;
  309 + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
  310 + CLANG_ANALYZER_NONNULL = YES;
  311 + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
  312 + CLANG_CXX_LIBRARY = "libc++";
  313 + CLANG_ENABLE_MODULES = YES;
  314 + CLANG_ENABLE_OBJC_ARC = YES;
  315 + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
  316 + CLANG_WARN_BOOL_CONVERSION = YES;
  317 + CLANG_WARN_COMMA = YES;
  318 + CLANG_WARN_CONSTANT_CONVERSION = YES;
  319 + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
  320 + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
  321 + CLANG_WARN_EMPTY_BODY = YES;
  322 + CLANG_WARN_ENUM_CONVERSION = YES;
  323 + CLANG_WARN_INFINITE_RECURSION = YES;
  324 + CLANG_WARN_INT_CONVERSION = YES;
  325 + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
  326 + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
  327 + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
  328 + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
  329 + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
  330 + CLANG_WARN_STRICT_PROTOTYPES = YES;
  331 + CLANG_WARN_SUSPICIOUS_MOVE = YES;
  332 + CLANG_WARN_UNREACHABLE_CODE = YES;
  333 + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
  334 + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
  335 + COPY_PHASE_STRIP = NO;
  336 + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
  337 + ENABLE_NS_ASSERTIONS = NO;
  338 + ENABLE_STRICT_OBJC_MSGSEND = YES;
  339 + ENABLE_USER_SCRIPT_SANDBOXING = NO;
  340 + GCC_C_LANGUAGE_STANDARD = gnu99;
  341 + GCC_NO_COMMON_BLOCKS = YES;
  342 + GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
  343 + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
  344 + GCC_WARN_UNDECLARED_SELECTOR = YES;
  345 + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
  346 + GCC_WARN_UNUSED_FUNCTION = YES;
  347 + GCC_WARN_UNUSED_VARIABLE = YES;
  348 + IPHONEOS_DEPLOYMENT_TARGET = 12.0;
  349 + MTL_ENABLE_DEBUG_INFO = NO;
  350 + SDKROOT = iphoneos;
  351 + SUPPORTED_PLATFORMS = iphoneos;
  352 + TARGETED_DEVICE_FAMILY = "1,2";
  353 + VALIDATE_PRODUCT = YES;
  354 + };
  355 + name = Profile;
  356 + };
  357 + 249021D4217E4FDB00AE95B9 /* Profile */ = {
  358 + isa = XCBuildConfiguration;
  359 + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
  360 + buildSettings = {
  361 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
  362 + CLANG_ENABLE_MODULES = YES;
  363 + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
  364 + DEVELOPMENT_TEAM = 64MAFNBS88;
  365 + ENABLE_BITCODE = NO;
  366 + INFOPLIST_FILE = Runner/Info.plist;
  367 + LD_RUNPATH_SEARCH_PATHS = (
  368 + "$(inherited)",
  369 + "@executable_path/Frameworks",
  370 + );
  371 + PRODUCT_BUNDLE_IDENTIFIER = com.fluttercandies.wechatAssetsPickerDemo;
  372 + PRODUCT_NAME = "$(TARGET_NAME)";
  373 + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
  374 + SWIFT_VERSION = 5.0;
  375 + VERSIONING_SYSTEM = "apple-generic";
  376 + };
  377 + name = Profile;
  378 + };
  379 + 97C147031CF9000F007C117D /* Debug */ = {
  380 + isa = XCBuildConfiguration;
  381 + buildSettings = {
  382 + ALWAYS_SEARCH_USER_PATHS = NO;
  383 + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
  384 + CLANG_ANALYZER_NONNULL = YES;
  385 + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
  386 + CLANG_CXX_LIBRARY = "libc++";
  387 + CLANG_ENABLE_MODULES = YES;
  388 + CLANG_ENABLE_OBJC_ARC = YES;
  389 + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
  390 + CLANG_WARN_BOOL_CONVERSION = YES;
  391 + CLANG_WARN_COMMA = YES;
  392 + CLANG_WARN_CONSTANT_CONVERSION = YES;
  393 + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
  394 + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
  395 + CLANG_WARN_EMPTY_BODY = YES;
  396 + CLANG_WARN_ENUM_CONVERSION = YES;
  397 + CLANG_WARN_INFINITE_RECURSION = YES;
  398 + CLANG_WARN_INT_CONVERSION = YES;
  399 + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
  400 + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
  401 + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
  402 + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
  403 + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
  404 + CLANG_WARN_STRICT_PROTOTYPES = YES;
  405 + CLANG_WARN_SUSPICIOUS_MOVE = YES;
  406 + CLANG_WARN_UNREACHABLE_CODE = YES;
  407 + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
  408 + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
  409 + COPY_PHASE_STRIP = NO;
  410 + DEBUG_INFORMATION_FORMAT = dwarf;
  411 + ENABLE_STRICT_OBJC_MSGSEND = YES;
  412 + ENABLE_TESTABILITY = YES;
  413 + ENABLE_USER_SCRIPT_SANDBOXING = NO;
  414 + GCC_C_LANGUAGE_STANDARD = gnu99;
  415 + GCC_DYNAMIC_NO_PIC = NO;
  416 + GCC_NO_COMMON_BLOCKS = YES;
  417 + GCC_OPTIMIZATION_LEVEL = 0;
  418 + GCC_PREPROCESSOR_DEFINITIONS = (
  419 + "DEBUG=1",
  420 + "$(inherited)",
  421 + );
  422 + GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
  423 + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
  424 + GCC_WARN_UNDECLARED_SELECTOR = YES;
  425 + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
  426 + GCC_WARN_UNUSED_FUNCTION = YES;
  427 + GCC_WARN_UNUSED_VARIABLE = YES;
  428 + IPHONEOS_DEPLOYMENT_TARGET = 12.0;
  429 + MTL_ENABLE_DEBUG_INFO = YES;
  430 + ONLY_ACTIVE_ARCH = YES;
  431 + SDKROOT = iphoneos;
  432 + TARGETED_DEVICE_FAMILY = "1,2";
  433 + };
  434 + name = Debug;
  435 + };
  436 + 97C147041CF9000F007C117D /* Release */ = {
  437 + isa = XCBuildConfiguration;
  438 + buildSettings = {
  439 + ALWAYS_SEARCH_USER_PATHS = NO;
  440 + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
  441 + CLANG_ANALYZER_NONNULL = YES;
  442 + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
  443 + CLANG_CXX_LIBRARY = "libc++";
  444 + CLANG_ENABLE_MODULES = YES;
  445 + CLANG_ENABLE_OBJC_ARC = YES;
  446 + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
  447 + CLANG_WARN_BOOL_CONVERSION = YES;
  448 + CLANG_WARN_COMMA = YES;
  449 + CLANG_WARN_CONSTANT_CONVERSION = YES;
  450 + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
  451 + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
  452 + CLANG_WARN_EMPTY_BODY = YES;
  453 + CLANG_WARN_ENUM_CONVERSION = YES;
  454 + CLANG_WARN_INFINITE_RECURSION = YES;
  455 + CLANG_WARN_INT_CONVERSION = YES;
  456 + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
  457 + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
  458 + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
  459 + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
  460 + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
  461 + CLANG_WARN_STRICT_PROTOTYPES = YES;
  462 + CLANG_WARN_SUSPICIOUS_MOVE = YES;
  463 + CLANG_WARN_UNREACHABLE_CODE = YES;
  464 + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
  465 + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
  466 + COPY_PHASE_STRIP = NO;
  467 + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
  468 + ENABLE_NS_ASSERTIONS = NO;
  469 + ENABLE_STRICT_OBJC_MSGSEND = YES;
  470 + ENABLE_USER_SCRIPT_SANDBOXING = NO;
  471 + GCC_C_LANGUAGE_STANDARD = gnu99;
  472 + GCC_NO_COMMON_BLOCKS = YES;
  473 + GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
  474 + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
  475 + GCC_WARN_UNDECLARED_SELECTOR = YES;
  476 + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
  477 + GCC_WARN_UNUSED_FUNCTION = YES;
  478 + GCC_WARN_UNUSED_VARIABLE = YES;
  479 + IPHONEOS_DEPLOYMENT_TARGET = 12.0;
  480 + MTL_ENABLE_DEBUG_INFO = NO;
  481 + SDKROOT = iphoneos;
  482 + SUPPORTED_PLATFORMS = iphoneos;
  483 + SWIFT_COMPILATION_MODE = wholemodule;
  484 + SWIFT_OPTIMIZATION_LEVEL = "-O";
  485 + TARGETED_DEVICE_FAMILY = "1,2";
  486 + VALIDATE_PRODUCT = YES;
  487 + };
  488 + name = Release;
  489 + };
  490 + 97C147061CF9000F007C117D /* Debug */ = {
  491 + isa = XCBuildConfiguration;
  492 + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
  493 + buildSettings = {
  494 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
  495 + CLANG_ENABLE_MODULES = YES;
  496 + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
  497 + DEVELOPMENT_TEAM = 64MAFNBS88;
  498 + ENABLE_BITCODE = NO;
  499 + INFOPLIST_FILE = Runner/Info.plist;
  500 + LD_RUNPATH_SEARCH_PATHS = (
  501 + "$(inherited)",
  502 + "@executable_path/Frameworks",
  503 + );
  504 + PRODUCT_BUNDLE_IDENTIFIER = com.fluttercandies.wechatAssetsPickerDemo;
  505 + PRODUCT_NAME = "$(TARGET_NAME)";
  506 + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
  507 + SWIFT_OPTIMIZATION_LEVEL = "-Onone";
  508 + SWIFT_VERSION = 5.0;
  509 + VERSIONING_SYSTEM = "apple-generic";
  510 + };
  511 + name = Debug;
  512 + };
  513 + 97C147071CF9000F007C117D /* Release */ = {
  514 + isa = XCBuildConfiguration;
  515 + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
  516 + buildSettings = {
  517 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
  518 + CLANG_ENABLE_MODULES = YES;
  519 + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
  520 + DEVELOPMENT_TEAM = 64MAFNBS88;
  521 + ENABLE_BITCODE = NO;
  522 + INFOPLIST_FILE = Runner/Info.plist;
  523 + LD_RUNPATH_SEARCH_PATHS = (
  524 + "$(inherited)",
  525 + "@executable_path/Frameworks",
  526 + );
  527 + PRODUCT_BUNDLE_IDENTIFIER = com.fluttercandies.wechatAssetsPickerDemo;
  528 + PRODUCT_NAME = "$(TARGET_NAME)";
  529 + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
  530 + SWIFT_VERSION = 5.0;
  531 + VERSIONING_SYSTEM = "apple-generic";
  532 + };
  533 + name = Release;
  534 + };
  535 +/* End XCBuildConfiguration section */
  536 +
  537 +/* Begin XCConfigurationList section */
  538 + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
  539 + isa = XCConfigurationList;
  540 + buildConfigurations = (
  541 + 97C147031CF9000F007C117D /* Debug */,
  542 + 97C147041CF9000F007C117D /* Release */,
  543 + 249021D3217E4FDB00AE95B9 /* Profile */,
  544 + );
  545 + defaultConfigurationIsVisible = 0;
  546 + defaultConfigurationName = Release;
  547 + };
  548 + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
  549 + isa = XCConfigurationList;
  550 + buildConfigurations = (
  551 + 97C147061CF9000F007C117D /* Debug */,
  552 + 97C147071CF9000F007C117D /* Release */,
  553 + 249021D4217E4FDB00AE95B9 /* Profile */,
  554 + );
  555 + defaultConfigurationIsVisible = 0;
  556 + defaultConfigurationName = Release;
  557 + };
  558 +/* End XCConfigurationList section */
  559 + };
  560 + rootObject = 97C146E61CF9000F007C117D /* Project object */;
  561 +}
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<Workspace
  3 + version = "1.0">
  4 + <FileRef
  5 + location = "self:">
  6 + </FileRef>
  7 +</Workspace>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>IDEDidComputeMac32BitWarning</key>
  6 + <true/>
  7 +</dict>
  8 +</plist>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>PreviewsEnabled</key>
  6 + <false/>
  7 +</dict>
  8 +</plist>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<Scheme
  3 + LastUpgradeVersion = "1510"
  4 + version = "1.3">
  5 + <BuildAction
  6 + parallelizeBuildables = "YES"
  7 + buildImplicitDependencies = "YES">
  8 + <BuildActionEntries>
  9 + <BuildActionEntry
  10 + buildForTesting = "YES"
  11 + buildForRunning = "YES"
  12 + buildForProfiling = "YES"
  13 + buildForArchiving = "YES"
  14 + buildForAnalyzing = "YES">
  15 + <BuildableReference
  16 + BuildableIdentifier = "primary"
  17 + BlueprintIdentifier = "97C146ED1CF9000F007C117D"
  18 + BuildableName = "Runner.app"
  19 + BlueprintName = "Runner"
  20 + ReferencedContainer = "container:Runner.xcodeproj">
  21 + </BuildableReference>
  22 + </BuildActionEntry>
  23 + </BuildActionEntries>
  24 + </BuildAction>
  25 + <TestAction
  26 + buildConfiguration = "Debug"
  27 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
  28 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
  29 + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
  30 + shouldUseLaunchSchemeArgsEnv = "YES">
  31 + <MacroExpansion>
  32 + <BuildableReference
  33 + BuildableIdentifier = "primary"
  34 + BlueprintIdentifier = "97C146ED1CF9000F007C117D"
  35 + BuildableName = "Runner.app"
  36 + BlueprintName = "Runner"
  37 + ReferencedContainer = "container:Runner.xcodeproj">
  38 + </BuildableReference>
  39 + </MacroExpansion>
  40 + <Testables>
  41 + <TestableReference
  42 + skipped = "NO"
  43 + parallelizable = "YES">
  44 + <BuildableReference
  45 + BuildableIdentifier = "primary"
  46 + BlueprintIdentifier = "331C8080294A63A400263BE5"
  47 + BuildableName = "RunnerTests.xctest"
  48 + BlueprintName = "RunnerTests"
  49 + ReferencedContainer = "container:Runner.xcodeproj">
  50 + </BuildableReference>
  51 + </TestableReference>
  52 + </Testables>
  53 + </TestAction>
  54 + <LaunchAction
  55 + buildConfiguration = "Debug"
  56 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
  57 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
  58 + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
  59 + launchStyle = "0"
  60 + useCustomWorkingDirectory = "NO"
  61 + ignoresPersistentStateOnLaunch = "NO"
  62 + debugDocumentVersioning = "YES"
  63 + debugServiceExtension = "internal"
  64 + enableGPUValidationMode = "1"
  65 + allowLocationSimulation = "YES">
  66 + <BuildableProductRunnable
  67 + runnableDebuggingMode = "0">
  68 + <BuildableReference
  69 + BuildableIdentifier = "primary"
  70 + BlueprintIdentifier = "97C146ED1CF9000F007C117D"
  71 + BuildableName = "Runner.app"
  72 + BlueprintName = "Runner"
  73 + ReferencedContainer = "container:Runner.xcodeproj">
  74 + </BuildableReference>
  75 + </BuildableProductRunnable>
  76 + </LaunchAction>
  77 + <ProfileAction
  78 + buildConfiguration = "Profile"
  79 + shouldUseLaunchSchemeArgsEnv = "YES"
  80 + savedToolIdentifier = ""
  81 + useCustomWorkingDirectory = "NO"
  82 + debugDocumentVersioning = "YES">
  83 + <BuildableProductRunnable
  84 + runnableDebuggingMode = "0">
  85 + <BuildableReference
  86 + BuildableIdentifier = "primary"
  87 + BlueprintIdentifier = "97C146ED1CF9000F007C117D"
  88 + BuildableName = "Runner.app"
  89 + BlueprintName = "Runner"
  90 + ReferencedContainer = "container:Runner.xcodeproj">
  91 + </BuildableReference>
  92 + </BuildableProductRunnable>
  93 + </ProfileAction>
  94 + <AnalyzeAction
  95 + buildConfiguration = "Debug">
  96 + </AnalyzeAction>
  97 + <ArchiveAction
  98 + buildConfiguration = "Release"
  99 + revealArchiveInOrganizer = "YES">
  100 + </ArchiveAction>
  101 +</Scheme>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<Workspace
  3 + version = "1.0">
  4 + <FileRef
  5 + location = "group:Runner.xcodeproj">
  6 + </FileRef>
  7 + <FileRef
  8 + location = "group:Pods/Pods.xcodeproj">
  9 + </FileRef>
  10 +</Workspace>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>IDEDidComputeMac32BitWarning</key>
  6 + <true/>
  7 +</dict>
  8 +</plist>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>PreviewsEnabled</key>
  6 + <false/>
  7 +</dict>
  8 +</plist>
  1 +import UIKit
  2 +import Flutter
  3 +
  4 +@main
  5 +@objc class AppDelegate: FlutterAppDelegate {
  6 + override func application(
  7 + _ application: UIApplication,
  8 + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  9 + ) -> Bool {
  10 + GeneratedPluginRegistrant.register(with: self)
  11 + return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  12 + }
  13 +}
  1 +{
  2 + "images":[
  3 + {
  4 + "idiom":"iphone",
  5 + "size":"20x20",
  6 + "scale":"2x",
  7 + "filename":"Icon-App-20x20@2x.png"
  8 + },
  9 + {
  10 + "idiom":"iphone",
  11 + "size":"20x20",
  12 + "scale":"3x",
  13 + "filename":"Icon-App-20x20@3x.png"
  14 + },
  15 + {
  16 + "idiom":"iphone",
  17 + "size":"29x29",
  18 + "scale":"1x",
  19 + "filename":"Icon-App-29x29@1x.png"
  20 + },
  21 + {
  22 + "idiom":"iphone",
  23 + "size":"29x29",
  24 + "scale":"2x",
  25 + "filename":"Icon-App-29x29@2x.png"
  26 + },
  27 + {
  28 + "idiom":"iphone",
  29 + "size":"29x29",
  30 + "scale":"3x",
  31 + "filename":"Icon-App-29x29@3x.png"
  32 + },
  33 + {
  34 + "idiom":"iphone",
  35 + "size":"40x40",
  36 + "scale":"2x",
  37 + "filename":"Icon-App-40x40@2x.png"
  38 + },
  39 + {
  40 + "idiom":"iphone",
  41 + "size":"40x40",
  42 + "scale":"3x",
  43 + "filename":"Icon-App-40x40@3x.png"
  44 + },
  45 + {
  46 + "idiom":"iphone",
  47 + "size":"60x60",
  48 + "scale":"2x",
  49 + "filename":"Icon-App-60x60@2x.png"
  50 + },
  51 + {
  52 + "idiom":"iphone",
  53 + "size":"60x60",
  54 + "scale":"3x",
  55 + "filename":"Icon-App-60x60@3x.png"
  56 + },
  57 + {
  58 + "idiom":"iphone",
  59 + "size":"76x76",
  60 + "scale":"2x",
  61 + "filename":"Icon-App-76x76@2x.png"
  62 + },
  63 + {
  64 + "idiom":"ipad",
  65 + "size":"20x20",
  66 + "scale":"1x",
  67 + "filename":"Icon-App-20x20@1x.png"
  68 + },
  69 + {
  70 + "idiom":"ipad",
  71 + "size":"20x20",
  72 + "scale":"2x",
  73 + "filename":"Icon-App-20x20@2x.png"
  74 + },
  75 + {
  76 + "idiom":"ipad",
  77 + "size":"29x29",
  78 + "scale":"1x",
  79 + "filename":"Icon-App-29x29@1x.png"
  80 + },
  81 + {
  82 + "idiom":"ipad",
  83 + "size":"29x29",
  84 + "scale":"2x",
  85 + "filename":"Icon-App-29x29@2x.png"
  86 + },
  87 + {
  88 + "idiom":"ipad",
  89 + "size":"40x40",
  90 + "scale":"1x",
  91 + "filename":"Icon-App-40x40@1x.png"
  92 + },
  93 + {
  94 + "idiom":"ipad",
  95 + "size":"40x40",
  96 + "scale":"2x",
  97 + "filename":"Icon-App-40x40@2x.png"
  98 + },
  99 + {
  100 + "idiom":"ipad",
  101 + "size":"76x76",
  102 + "scale":"1x",
  103 + "filename":"Icon-App-76x76@1x.png"
  104 + },
  105 + {
  106 + "idiom":"ipad",
  107 + "size":"76x76",
  108 + "scale":"2x",
  109 + "filename":"Icon-App-76x76@2x.png"
  110 + },
  111 + {
  112 + "idiom":"ipad",
  113 + "size":"83.5x83.5",
  114 + "scale":"2x",
  115 + "filename":"Icon-App-83.5x83.5@2x.png"
  116 + },
  117 + {
  118 + "size" : "1024x1024",
  119 + "idiom" : "ios-marketing",
  120 + "scale" : "1x",
  121 + "filename" : "ItunesArtwork@2x.png"
  122 + }
  123 + ],
  124 + "info":{
  125 + "version":1,
  126 + "author":"makeappicon"
  127 + }
  128 +}
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "LaunchImage.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "filename" : "LaunchImage@2x.png",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "idiom" : "universal",
  15 + "filename" : "LaunchImage@3x.png",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "version" : 1,
  21 + "author" : "xcode"
  22 + }
  23 +}
  1 +# Launch Screen Assets
  2 +
  3 +You can customize the launch screen with your own desired assets by replacing the image files in this directory.
  4 +
  5 +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
  1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
  3 + <dependencies>
  4 + <deployment identifier="iOS"/>
  5 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
  6 + </dependencies>
  7 + <scenes>
  8 + <!--View Controller-->
  9 + <scene sceneID="EHf-IW-A2E">
  10 + <objects>
  11 + <viewController id="01J-lp-oVM" sceneMemberID="viewController">
  12 + <layoutGuides>
  13 + <viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
  14 + <viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
  15 + </layoutGuides>
  16 + <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
  17 + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
  18 + <subviews>
  19 + <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
  20 + </imageView>
  21 + </subviews>
  22 + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
  23 + <constraints>
  24 + <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
  25 + <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
  26 + </constraints>
  27 + </view>
  28 + </viewController>
  29 + <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
  30 + </objects>
  31 + <point key="canvasLocation" x="53" y="375"/>
  32 + </scene>
  33 + </scenes>
  34 + <resources>
  35 + <image name="LaunchImage" width="168" height="185"/>
  36 + </resources>
  37 +</document>
  1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
  3 + <dependencies>
  4 + <deployment identifier="iOS"/>
  5 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
  6 + </dependencies>
  7 + <scenes>
  8 + <!--Flutter View Controller-->
  9 + <scene sceneID="tne-QT-ifu">
  10 + <objects>
  11 + <viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
  12 + <layoutGuides>
  13 + <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
  14 + <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
  15 + </layoutGuides>
  16 + <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
  17 + <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
  18 + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
  19 + <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
  20 + </view>
  21 + </viewController>
  22 + <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
  23 + </objects>
  24 + </scene>
  25 + </scenes>
  26 +</document>
  1 +//
  2 +// Generated file. Do not edit.
  3 +//
  4 +
  5 +// clang-format off
  6 +
  7 +#ifndef GeneratedPluginRegistrant_h
  8 +#define GeneratedPluginRegistrant_h
  9 +
  10 +#import <Flutter/Flutter.h>
  11 +
  12 +NS_ASSUME_NONNULL_BEGIN
  13 +
  14 +@interface GeneratedPluginRegistrant : NSObject
  15 ++ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry;
  16 +@end
  17 +
  18 +NS_ASSUME_NONNULL_END
  19 +#endif /* GeneratedPluginRegistrant_h */
  1 +//
  2 +// Generated file. Do not edit.
  3 +//
  4 +
  5 +// clang-format off
  6 +
  7 +#import "GeneratedPluginRegistrant.h"
  8 +
  9 +#if __has_include(<camera_avfoundation/CameraPlugin.h>)
  10 +#import <camera_avfoundation/CameraPlugin.h>
  11 +#else
  12 +@import camera_avfoundation;
  13 +#endif
  14 +
  15 +#if __has_include(<package_info_plus/FPPPackageInfoPlusPlugin.h>)
  16 +#import <package_info_plus/FPPPackageInfoPlusPlugin.h>
  17 +#else
  18 +@import package_info_plus;
  19 +#endif
  20 +
  21 +#if __has_include(<path_provider_foundation/PathProviderPlugin.h>)
  22 +#import <path_provider_foundation/PathProviderPlugin.h>
  23 +#else
  24 +@import path_provider_foundation;
  25 +#endif
  26 +
  27 +#if __has_include(<photo_manager/PhotoManagerPlugin.h>)
  28 +#import <photo_manager/PhotoManagerPlugin.h>
  29 +#else
  30 +@import photo_manager;
  31 +#endif
  32 +
  33 +#if __has_include(<sensors_plus/FPPSensorsPlusPlugin.h>)
  34 +#import <sensors_plus/FPPSensorsPlusPlugin.h>
  35 +#else
  36 +@import sensors_plus;
  37 +#endif
  38 +
  39 +#if __has_include(<video_player_avfoundation/FVPVideoPlayerPlugin.h>)
  40 +#import <video_player_avfoundation/FVPVideoPlayerPlugin.h>
  41 +#else
  42 +@import video_player_avfoundation;
  43 +#endif
  44 +
  45 +@implementation GeneratedPluginRegistrant
  46 +
  47 ++ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
  48 + [CameraPlugin registerWithRegistrar:[registry registrarForPlugin:@"CameraPlugin"]];
  49 + [FPPPackageInfoPlusPlugin registerWithRegistrar:[registry registrarForPlugin:@"FPPPackageInfoPlusPlugin"]];
  50 + [PathProviderPlugin registerWithRegistrar:[registry registrarForPlugin:@"PathProviderPlugin"]];
  51 + [PhotoManagerPlugin registerWithRegistrar:[registry registrarForPlugin:@"PhotoManagerPlugin"]];
  52 + [FPPSensorsPlusPlugin registerWithRegistrar:[registry registrarForPlugin:@"FPPSensorsPlusPlugin"]];
  53 + [FVPVideoPlayerPlugin registerWithRegistrar:[registry registrarForPlugin:@"FVPVideoPlayerPlugin"]];
  54 +}
  55 +
  56 +@end
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>CADisableMinimumFrameDurationOnPhone</key>
  6 + <true/>
  7 + <key>CFBundleDevelopmentRegion</key>
  8 + <string>$(DEVELOPMENT_LANGUAGE)</string>
  9 + <key>CFBundleDisplayName</key>
  10 + <string>Wechat Assets Picker Example</string>
  11 + <key>CFBundleExecutable</key>
  12 + <string>$(EXECUTABLE_NAME)</string>
  13 + <key>CFBundleIdentifier</key>
  14 + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
  15 + <key>CFBundleInfoDictionaryVersion</key>
  16 + <string>6.0</string>
  17 + <key>CFBundleName</key>
  18 + <string>flutter_wechat_assets_picker_example</string>
  19 + <key>CFBundlePackageType</key>
  20 + <string>APPL</string>
  21 + <key>CFBundleShortVersionString</key>
  22 + <string>$(FLUTTER_BUILD_NAME)</string>
  23 + <key>CFBundleSignature</key>
  24 + <string>????</string>
  25 + <key>CFBundleVersion</key>
  26 + <string>$(FLUTTER_BUILD_NUMBER)</string>
  27 + <key>LSRequiresIPhoneOS</key>
  28 + <true/>
  29 + <key>NSCameraUsageDescription</key>
  30 + <string>Take a photo for display</string>
  31 + <key>NSMicrophoneUsageDescription</key>
  32 + <string>Take a video for display</string>
  33 + <key>NSPhotoLibraryUsageDescription</key>
  34 + <string>Read your photos for display</string>
  35 + <key>UIApplicationSupportsIndirectInputEvents</key>
  36 + <true/>
  37 + <key>UILaunchStoryboardName</key>
  38 + <string>LaunchScreen</string>
  39 + <key>UIMainStoryboardFile</key>
  40 + <string>Main</string>
  41 + <key>UISupportedInterfaceOrientations</key>
  42 + <array>
  43 + <string>UIInterfaceOrientationPortrait</string>
  44 + <string>UIInterfaceOrientationLandscapeLeft</string>
  45 + <string>UIInterfaceOrientationLandscapeRight</string>
  46 + </array>
  47 + <key>UISupportedInterfaceOrientations~ipad</key>
  48 + <array>
  49 + <string>UIInterfaceOrientationPortrait</string>
  50 + <string>UIInterfaceOrientationPortraitUpsideDown</string>
  51 + <string>UIInterfaceOrientationLandscapeLeft</string>
  52 + <string>UIInterfaceOrientationLandscapeRight</string>
  53 + </array>
  54 +</dict>
  55 +</plist>
  1 +arb-dir: lib/l10n
  2 +format: true
  3 +output-class: AppLocalizations
  4 +output-dir: lib/l10n/gen
  5 +output-localization-file: app_localizations.dart
  6 +template-arb-file: app_en.arb
  7 +synthetic-package: false
  8 +untranslated-messages-file: lib/l10n/gen/app_localizations_untranslated.json
  1 +// Copyright 2019 The FlutterCandies author. All rights reserved.
  2 +// Use of this source code is governed by an Apache license that can be found
  3 +// in the LICENSE file.
  4 +
  5 +import 'package:flutter/widgets.dart';
  6 +
  7 +@immutable
  8 +class CustomPickMethod {
  9 + const CustomPickMethod({
  10 + required this.icon,
  11 + required this.name,
  12 + required this.description,
  13 + required this.method,
  14 + });
  15 +
  16 + final String icon;
  17 + final String name;
  18 + final String description;
  19 + final void Function(BuildContext context) method;
  20 +}
  1 +// Copyright 2019 The FlutterCandies author. All rights reserved.
  2 +// Use of this source code is governed by an Apache license that can be found
  3 +// in the LICENSE file.
  4 +
  5 +import 'package:flutter/material.dart';
  6 +import 'package:wechat_assets_picker_demo/l10n/gen/app_localizations.dart';
  7 +
  8 +extension BuildContextExtension on BuildContext {
  9 + AppLocalizations get l10n => AppLocalizations.of(this)!;
  10 +}
  11 +
  12 +extension BrightnessExtension on Brightness {
  13 + bool get isDark => this == Brightness.dark;
  14 +
  15 + bool get isLight => this == Brightness.light;
  16 +
  17 + Brightness get reverse =>
  18 + this == Brightness.light ? Brightness.dark : Brightness.light;
  19 +}
  20 +
  21 +extension ColorExtension on Color {
  22 + MaterialColor get swatch => Colors.primaries.firstWhere(
  23 + (Color c) => c.value == value,
  24 + orElse: () => _swatch,
  25 + );
  26 +
  27 + Map<int, Color> get getMaterialColorValues => <int, Color>{
  28 + 50: _swatchShade(50),
  29 + 100: _swatchShade(100),
  30 + 200: _swatchShade(200),
  31 + 300: _swatchShade(300),
  32 + 400: _swatchShade(400),
  33 + 500: _swatchShade(500),
  34 + 600: _swatchShade(600),
  35 + 700: _swatchShade(700),
  36 + 800: _swatchShade(800),
  37 + 900: _swatchShade(900),
  38 + };
  39 +
  40 + MaterialColor get _swatch => MaterialColor(value, getMaterialColorValues);
  41 +
  42 + Color _swatchShade(int swatchValue) => HSLColor.fromColor(this)
  43 + .withLightness(1 - (swatchValue / 1000))
  44 + .toColor();
  45 +}
  1 +// Copyright 2019 The FlutterCandies author. All rights reserved.
  2 +// Use of this source code is governed by an Apache license that can be found
  3 +// in the LICENSE file.
  4 +
  5 +import 'package:flutter/material.dart';
  6 +import 'package:wechat_assets_picker/wechat_assets_picker.dart';
  7 +import 'package:wechat_camera_picker/wechat_camera_picker.dart';
  8 +
  9 +import 'extensions.dart';
  10 +
  11 +Future<AssetEntity?> _pickFromCamera(BuildContext c) {
  12 + return CameraPicker.pickFromCamera(
  13 + c,
  14 + pickerConfig: const CameraPickerConfig(enableRecording: true),
  15 + );
  16 +}
  17 +
  18 +/// Define a regular pick method.
  19 +class PickMethod {
  20 + const PickMethod({
  21 + required this.icon,
  22 + required this.name,
  23 + required this.description,
  24 + required this.method,
  25 + this.onLongPress,
  26 + });
  27 +
  28 + factory PickMethod.common(BuildContext context, int maxAssetsCount) {
  29 + return PickMethod(
  30 + icon: '📹',
  31 + name: context.l10n.pickMethodCommonName,
  32 + description: context.l10n.pickMethodCommonDescription,
  33 + method: (BuildContext context, List<AssetEntity> assets) {
  34 + return AssetPicker.pickAssets(
  35 + context,
  36 + pickerConfig: AssetPickerConfig(
  37 + maxAssets: maxAssetsCount,
  38 + selectedAssets: assets,
  39 + ),
  40 + );
  41 + },
  42 + );
  43 + }
  44 +
  45 + factory PickMethod.image(BuildContext context, int maxAssetsCount) {
  46 + return PickMethod(
  47 + icon: '🖼️',
  48 + name: context.l10n.pickMethodImageName,
  49 + description: context.l10n.pickMethodImageDescription,
  50 + method: (BuildContext context, List<AssetEntity> assets) {
  51 + return AssetPicker.pickAssets(
  52 + context,
  53 + pickerConfig: AssetPickerConfig(
  54 + maxAssets: maxAssetsCount,
  55 + selectedAssets: assets,
  56 + requestType: RequestType.image,
  57 + ),
  58 + );
  59 + },
  60 + );
  61 + }
  62 +
  63 + factory PickMethod.video(BuildContext context, int maxAssetsCount) {
  64 + return PickMethod(
  65 + icon: '🎞',
  66 + name: context.l10n.pickMethodVideoName,
  67 + description: context.l10n.pickMethodVideoDescription,
  68 + method: (BuildContext context, List<AssetEntity> assets) {
  69 + return AssetPicker.pickAssets(
  70 + context,
  71 + pickerConfig: AssetPickerConfig(
  72 + maxAssets: maxAssetsCount,
  73 + selectedAssets: assets,
  74 + requestType: RequestType.video,
  75 + ),
  76 + );
  77 + },
  78 + );
  79 + }
  80 +
  81 + factory PickMethod.audio(BuildContext context, int maxAssetsCount) {
  82 + return PickMethod(
  83 + icon: '🎶',
  84 + name: context.l10n.pickMethodAudioName,
  85 + description: context.l10n.pickMethodAudioDescription,
  86 + method: (BuildContext context, List<AssetEntity> assets) {
  87 + return AssetPicker.pickAssets(
  88 + context,
  89 + pickerConfig: AssetPickerConfig(
  90 + maxAssets: maxAssetsCount,
  91 + selectedAssets: assets,
  92 + requestType: RequestType.audio,
  93 + ),
  94 + );
  95 + },
  96 + );
  97 + }
  98 +
  99 + factory PickMethod.livePhoto(BuildContext context, int maxAssetsCount) {
  100 + return PickMethod(
  101 + icon: '🎬',
  102 + name: context.l10n.pickMethodLivePhotoName,
  103 + description: context.l10n.pickMethodLivePhotoDescription,
  104 + method: (BuildContext context, List<AssetEntity> assets) {
  105 + return AssetPicker.pickAssets(
  106 + context,
  107 + pickerConfig: AssetPickerConfig(
  108 + maxAssets: maxAssetsCount,
  109 + selectedAssets: assets,
  110 + requestType: RequestType.image,
  111 + filterOptions: CustomFilter.sql(
  112 + where: '${CustomColumns.base.mediaType} = 1'
  113 + ' AND '
  114 + '${CustomColumns.darwin.mediaSubtypes} & (1 << 3) = (1 << 3)',
  115 + ),
  116 + ),
  117 + );
  118 + },
  119 + );
  120 + }
  121 +
  122 + factory PickMethod.camera({
  123 + required BuildContext context,
  124 + required int maxAssetsCount,
  125 + required Function(BuildContext, AssetEntity) handleResult,
  126 + }) {
  127 + return PickMethod(
  128 + icon: '📷',
  129 + name: context.l10n.pickMethodCameraName,
  130 + description: context.l10n.pickMethodCameraDescription,
  131 + method: (BuildContext context, List<AssetEntity> assets) {
  132 + const AssetPickerTextDelegate textDelegate = AssetPickerTextDelegate();
  133 + return AssetPicker.pickAssets(
  134 + context,
  135 + pickerConfig: AssetPickerConfig(
  136 + maxAssets: maxAssetsCount,
  137 + selectedAssets: assets,
  138 + specialItemPosition: SpecialItemPosition.prepend,
  139 + specialItemBuilder: (
  140 + BuildContext context,
  141 + AssetPathEntity? path,
  142 + int length,
  143 + ) {
  144 + if (path?.isAll != true) {
  145 + return null;
  146 + }
  147 + return Semantics(
  148 + label: textDelegate.sActionUseCameraHint,
  149 + button: true,
  150 + onTapHint: textDelegate.sActionUseCameraHint,
  151 + child: GestureDetector(
  152 + behavior: HitTestBehavior.opaque,
  153 + onTap: () async {
  154 + Feedback.forTap(context);
  155 + final AssetEntity? result = await _pickFromCamera(context);
  156 + if (result != null) {
  157 + handleResult(context, result);
  158 + }
  159 + },
  160 + child: Container(
  161 + padding: const EdgeInsets.all(28.0),
  162 + color: Theme.of(context).dividerColor,
  163 + child: const FittedBox(
  164 + fit: BoxFit.fill,
  165 + child: Icon(Icons.camera_enhance),
  166 + ),
  167 + ),
  168 + ),
  169 + );
  170 + },
  171 + ),
  172 + );
  173 + },
  174 + );
  175 + }
  176 +
  177 + factory PickMethod.cameraAndStay(BuildContext context, int maxAssetsCount) {
  178 + return PickMethod(
  179 + icon: '📸',
  180 + name: context.l10n.pickMethodCameraAndStayName,
  181 + description: context.l10n.pickMethodCameraAndStayDescription,
  182 + method: (BuildContext context, List<AssetEntity> assets) {
  183 + const AssetPickerTextDelegate textDelegate = AssetPickerTextDelegate();
  184 + return AssetPicker.pickAssets(
  185 + context,
  186 + pickerConfig: AssetPickerConfig(
  187 + maxAssets: maxAssetsCount,
  188 + selectedAssets: assets,
  189 + specialItemPosition: SpecialItemPosition.prepend,
  190 + specialItemBuilder: (
  191 + BuildContext context,
  192 + AssetPathEntity? path,
  193 + int length,
  194 + ) {
  195 + if (path?.isAll != true) {
  196 + return null;
  197 + }
  198 + return Semantics(
  199 + label: textDelegate.sActionUseCameraHint,
  200 + button: true,
  201 + onTapHint: textDelegate.sActionUseCameraHint,
  202 + child: GestureDetector(
  203 + behavior: HitTestBehavior.opaque,
  204 + onTap: () async {
  205 + final AssetEntity? result = await _pickFromCamera(context);
  206 + if (result == null) {
  207 + return;
  208 + }
  209 + final picker = context.findAncestorWidgetOfExactType<
  210 + AssetPicker<AssetEntity, AssetPathEntity>>()!;
  211 + final builder =
  212 + picker.builder as DefaultAssetPickerBuilderDelegate;
  213 + final p = builder.provider;
  214 + await p.switchPath(
  215 + PathWrapper<AssetPathEntity>(
  216 + path:
  217 + await p.currentPath!.path.obtainForNewProperties(),
  218 + ),
  219 + );
  220 + p.selectAsset(result);
  221 + },
  222 + child: Container(
  223 + padding: const EdgeInsets.all(28.0),
  224 + color: Theme.of(context).dividerColor,
  225 + child: const FittedBox(
  226 + fit: BoxFit.fill,
  227 + child: Icon(Icons.camera_enhance),
  228 + ),
  229 + ),
  230 + ),
  231 + );
  232 + },
  233 + ),
  234 + );
  235 + },
  236 + );
  237 + }
  238 +
  239 + factory PickMethod.threeItemsGrid(BuildContext context, int maxAssetsCount) {
  240 + return PickMethod(
  241 + icon: '🔲',
  242 + name: context.l10n.pickMethodThreeItemsGridName,
  243 + description: context.l10n.pickMethodThreeItemsGridDescription,
  244 + method: (BuildContext context, List<AssetEntity> assets) {
  245 + return AssetPicker.pickAssets(
  246 + context,
  247 + pickerConfig: AssetPickerConfig(
  248 + gridCount: 3,
  249 + pageSize: 120,
  250 + maxAssets: maxAssetsCount,
  251 + selectedAssets: assets,
  252 + requestType: RequestType.all,
  253 + ),
  254 + );
  255 + },
  256 + );
  257 + }
  258 +
  259 + factory PickMethod.customFilterOptions(
  260 + BuildContext context,
  261 + int maxAssetsCount,
  262 + ) {
  263 + return PickMethod(
  264 + icon: '⏳',
  265 + name: context.l10n.pickMethodCustomFilterOptionsName,
  266 + description: context.l10n.pickMethodCustomFilterOptionsDescription,
  267 + method: (BuildContext context, List<AssetEntity> assets) {
  268 + return AssetPicker.pickAssets(
  269 + context,
  270 + pickerConfig: AssetPickerConfig(
  271 + maxAssets: maxAssetsCount,
  272 + selectedAssets: assets,
  273 + requestType: RequestType.video,
  274 + filterOptions: FilterOptionGroup(
  275 + videoOption: const FilterOption(
  276 + durationConstraint: DurationConstraint(
  277 + max: Duration(minutes: 1),
  278 + ),
  279 + ),
  280 + ),
  281 + ),
  282 + );
  283 + },
  284 + );
  285 + }
  286 +
  287 + factory PickMethod.prependItem(BuildContext context, int maxAssetsCount) {
  288 + return PickMethod(
  289 + icon: '➕',
  290 + name: context.l10n.pickMethodPrependItemName,
  291 + description: context.l10n.pickMethodPrependItemDescription,
  292 + method: (BuildContext context, List<AssetEntity> assets) {
  293 + return AssetPicker.pickAssets(
  294 + context,
  295 + pickerConfig: AssetPickerConfig(
  296 + maxAssets: maxAssetsCount,
  297 + selectedAssets: assets,
  298 + specialItemPosition: SpecialItemPosition.prepend,
  299 + specialItemBuilder: (
  300 + BuildContext context,
  301 + AssetPathEntity? path,
  302 + int length,
  303 + ) {
  304 + return const Center(
  305 + child: Text('Custom Widget', textAlign: TextAlign.center),
  306 + );
  307 + },
  308 + ),
  309 + );
  310 + },
  311 + );
  312 + }
  313 +
  314 + factory PickMethod.noPreview(BuildContext context, int maxAssetsCount) {
  315 + return PickMethod(
  316 + icon: '👁️‍🗨️',
  317 + name: context.l10n.pickMethodNoPreviewName,
  318 + description: context.l10n.pickMethodNoPreviewDescription,
  319 + method: (BuildContext context, List<AssetEntity> assets) {
  320 + return AssetPicker.pickAssets(
  321 + context,
  322 + pickerConfig: AssetPickerConfig(
  323 + maxAssets: maxAssetsCount,
  324 + selectedAssets: assets,
  325 + specialPickerType: SpecialPickerType.noPreview,
  326 + ),
  327 + );
  328 + },
  329 + );
  330 + }
  331 +
  332 + factory PickMethod.keepScrollOffset({
  333 + required BuildContext context,
  334 + required DefaultAssetPickerBuilderDelegate Function() delegate,
  335 + required Function(PermissionState state) onPermission,
  336 + GestureLongPressCallback? onLongPress,
  337 + }) {
  338 + return PickMethod(
  339 + icon: '💾',
  340 + name: context.l10n.pickMethodKeepScrollOffsetName,
  341 + description: context.l10n.pickMethodKeepScrollOffsetDescription,
  342 + method: (BuildContext context, List<AssetEntity> assets) async {
  343 + final PermissionState ps = await PhotoManager.requestPermissionExtend();
  344 + if (ps != PermissionState.authorized && ps != PermissionState.limited) {
  345 + throw StateError('Permission state error with $ps.');
  346 + }
  347 + onPermission(ps);
  348 + return AssetPicker.pickAssetsWithDelegate(
  349 + context,
  350 + delegate: delegate(),
  351 + );
  352 + },
  353 + onLongPress: onLongPress,
  354 + );
  355 + }
  356 +
  357 + factory PickMethod.changeLanguages(BuildContext context, int maxAssetsCount) {
  358 + return PickMethod(
  359 + icon: '🔤',
  360 + name: context.l10n.pickMethodChangeLanguagesName,
  361 + description: context.l10n.pickMethodChangeLanguagesDescription,
  362 + method: (BuildContext context, List<AssetEntity> assets) {
  363 + return AssetPicker.pickAssets(
  364 + context,
  365 + pickerConfig: AssetPickerConfig(
  366 + maxAssets: maxAssetsCount,
  367 + selectedAssets: assets,
  368 + textDelegate: const EnglishAssetPickerTextDelegate(),
  369 + ),
  370 + );
  371 + },
  372 + );
  373 + }
  374 +
  375 + factory PickMethod.preventGIFPicked(
  376 + BuildContext context,
  377 + int maxAssetsCount,
  378 + ) {
  379 + return PickMethod(
  380 + icon: '🈲',
  381 + name: context.l10n.pickMethodPreventGIFPickedName,
  382 + description: context.l10n.pickMethodPreventGIFPickedDescription,
  383 + method: (BuildContext context, List<AssetEntity> assets) {
  384 + return AssetPicker.pickAssets(
  385 + context,
  386 + pickerConfig: AssetPickerConfig(
  387 + maxAssets: maxAssetsCount,
  388 + selectedAssets: assets,
  389 + selectPredicate: (BuildContext c, AssetEntity a, bool isSelected) {
  390 + debugPrint('Asset title: ${a.title}');
  391 + return a.title?.endsWith('.gif') != true;
  392 + },
  393 + ),
  394 + );
  395 + },
  396 + );
  397 + }
  398 +
  399 + factory PickMethod.customizableTheme(
  400 + BuildContext context,
  401 + int maxAssetsCount,
  402 + ) {
  403 + return PickMethod(
  404 + icon: '🎨',
  405 + name: context.l10n.pickMethodCustomizableThemeName,
  406 + description: context.l10n.pickMethodCustomizableThemeDescription,
  407 + method: (BuildContext context, List<AssetEntity> assets) {
  408 + return AssetPicker.pickAssets(
  409 + context,
  410 + pickerConfig: AssetPickerConfig(
  411 + maxAssets: maxAssetsCount,
  412 + selectedAssets: assets,
  413 + pickerTheme: AssetPicker.themeData(
  414 + Colors.lightBlueAccent,
  415 + light: true,
  416 + ),
  417 + ),
  418 + );
  419 + },
  420 + );
  421 + }
  422 +
  423 + factory PickMethod.pathNameBuilder(BuildContext context, int maxAssetsCount) {
  424 + return PickMethod(
  425 + icon: '🈸',
  426 + name: context.l10n.pickMethodPathNameBuilderName,
  427 + description: context.l10n.pickMethodPathNameBuilderDescription,
  428 + method: (BuildContext context, List<AssetEntity> assets) {
  429 + return AssetPicker.pickAssets(
  430 + context,
  431 + pickerConfig: AssetPickerConfig(
  432 + maxAssets: maxAssetsCount,
  433 + selectedAssets: assets,
  434 + pathNameBuilder: (AssetPathEntity path) => '${path.name}🍭',
  435 + ),
  436 + );
  437 + },
  438 + );
  439 + }
  440 +
  441 + final String icon;
  442 + final String name;
  443 + final String description;
  444 +
  445 + /// The core function that defines how to use the picker.
  446 + final Future<List<AssetEntity>?> Function(
  447 + BuildContext context,
  448 + List<AssetEntity> selectedAssets,
  449 + ) method;
  450 +
  451 + final GestureLongPressCallback? onLongPress;
  452 +}
  1 +# Contribute custom implementations
  2 +
  3 +This folder allows people to contribute their delegates, use case, or even a brand-new picker.
  4 +
  5 +To add your works, make sure you follow this instruction.
  6 +
  7 +## Ensure that your picker is worth to contribute
  8 +
  9 +People usually have their own apps to build, and the thing like the picker is not always the same between apps.
  10 +However, some patterns can be consumed using arguments and fields override, without creating a new picker/delegate.
  11 +Please think twice before you confirmed it should be pushed as a new implementation example.
  12 +
  13 +## Contribute steps
  14 +
  15 +1. Fork this project.
  16 +2. Create a new branch named `custom-{write-your-implementation-name}`.
  17 +3. Create a new picker dart file named `{your_implementation_name}_asset_picker.dart` in the `pickers` folder.
  18 +4. Brought all your implementations into the file you've just created.
  19 +5. Add a `CustomPickMethod` at the `custom_picker_page.dart` file in `pickMethods`
  20 + in order to build an entrance to your picker.
  21 +6. Submit your PR with proper explanations with how your picker works.