Commit b81d26cc08ee22a30587370e6c624351d52037ba

Authored by weixin_45529955
1 parent 70fd5331

多图选择适配鸿蒙,选择数量控制

Showing 83 changed files with 231 additions and 4241 deletions

Too many changes to show.

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

  1 +import 'dart:io';
  2 +
  3 +class MediaDN {
  4 + File? file;
  5 +}
@@ -5,7 +5,9 @@ import 'package:flutter/material.dart'; @@ -5,7 +5,9 @@ import 'package:flutter/material.dart';
5 import 'package:flutter/rendering.dart'; 5 import 'package:flutter/rendering.dart';
6 import 'package:flutter_native_image/flutter_native_image.dart'; 6 import 'package:flutter_native_image/flutter_native_image.dart';
7 import 'package:flutter_screenutil/flutter_screenutil.dart'; 7 import 'package:flutter_screenutil/flutter_screenutil.dart';
  8 +import 'package:one_key/models/mediaDN.dart';
8 import 'package:one_key/models/upload_img_model.dart'; 9 import 'package:one_key/models/upload_img_model.dart';
  10 +import 'package:one_key/pages/online_check/image_select_ohos_util.dart';
9 import 'package:one_key/pages/online_check/photo_view_wiget.dart'; 11 import 'package:one_key/pages/online_check/photo_view_wiget.dart';
10 import 'package:one_key/pages/online_check/progress.dart'; 12 import 'package:one_key/pages/online_check/progress.dart';
11 13
@@ -196,19 +198,43 @@ class _VideoPickerWidgetState extends DisposableState<VideoPickerWidget> { @@ -196,19 +198,43 @@ class _VideoPickerWidgetState extends DisposableState<VideoPickerWidget> {
196 // pickType: type, 198 // pickType: type,
197 // photoPathList: pathList, 199 // photoPathList: pathList,
198 // ); 200 // );
199 - List<AssetEntity>? imgList = await AssetPicker.pickAssets(context, 201 + List<MediaDN>? imgList = [];
  202 + if (Platform.isAndroid || Platform.isIOS) {
  203 + List<AssetEntity>? imagListTemp = await AssetPicker.pickAssets(context,
200 pickerConfig: AssetPickerConfig( 204 pickerConfig: AssetPickerConfig(
201 maxAssets: widget.maxImageNumber - 205 maxAssets: widget.maxImageNumber -
202 widget.model!.imageListDenvironment.length, 206 widget.model!.imageListDenvironment.length,
203 // selectedAssets: assets, 207 // selectedAssets: assets,
204 requestType: type, 208 requestType: type,
205 themeColor: MyColours.color_199095)); 209 themeColor: MyColours.color_199095));
206 - if (imgList == null || imgList.isEmpty) { 210 + imagListTemp?.forEach((elenemt) async {
  211 + MediaDN mediaDN = MediaDN();
  212 + mediaDN.file = await elenemt.file;
  213 + imgList.add(mediaDN);
  214 + });
  215 +
  216 + }else if(Platform.isOhos){
  217 + List<XFile> imagListTemp = await ImageSelectOhosUtil.onImageButtonPressed(
  218 + ImageSource.gallery,
  219 + context: context,
  220 + isMultiImage: true,
  221 + isVideo: false,
  222 + limit: widget.maxImageNumber -
  223 + widget.model!.imageListDenvironment.length,);
  224 +
  225 + imagListTemp.forEach((elenemt) async {
  226 + MediaDN mediaDN = MediaDN();
  227 + mediaDN.file = File(elenemt.path);
  228 + imgList.add(mediaDN);
  229 + });
  230 +
  231 + }
  232 + if (imgList.length == 0 || imgList.isEmpty) {
207 print("No pick item."); 233 print("No pick item.");
208 return; 234 return;
209 - } else { 235 + }else {
210 for (int i = 0; i < imgList.length; i++) { 236 for (int i = 0; i < imgList.length; i++) {
211 - var file = (await imgList[i].file)!; 237 + var file = ( imgList[i].file)!;
212 setState(() { 238 setState(() {
213 UploadImgModel imgModel = UploadImgModel(); 239 UploadImgModel imgModel = UploadImgModel();
214 imgModel.file = File(file.absolute.path); 240 imgModel.file = File(file.absolute.path);
  1 +import 'package:flutter/material.dart';
  2 +import 'package:image_picker_ohos/image_picker_ohos.dart';
  3 +import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
  4 +class ImageSelectOhosUtil{
  5 +
  6 + static Future<List<XFile>> onImageButtonPressed(ImageSource source,
  7 + {required BuildContext context,
  8 + bool isMultiImage = false,
  9 + bool isMedia = false,
  10 + bool isVideo = false,
  11 + int limit = 9}) async {
  12 + // if (_controller != null) {
  13 + // await _controller!.setVolume(0.0);
  14 + // }
  15 + final ImagePickerPlatform _picker = new ImagePickerOhos();
  16 + if (context.mounted) {
  17 + if (isVideo) {
  18 + List<XFile> temp = [];
  19 + final XFile? file = await _picker.getVideo(
  20 + source: source, maxDuration: const Duration(seconds: 10));
  21 + if (file != null && context.mounted) {
  22 + // _showPickedSnackBar(context, <XFile>[file]);
  23 + temp.add(file as XFile);
  24 + }
  25 + return temp;
  26 + } else if (isMultiImage) {
  27 + double? maxWidth = 300.00;
  28 + double? maxHeight = 500;
  29 + int? quality = 90;
  30 +
  31 + try {
  32 + final ImageOptions imageOptions = ImageOptions(
  33 + maxWidth: maxWidth,
  34 + maxHeight: maxHeight,
  35 + imageQuality: quality,
  36 + );
  37 + final List<XFile> pickedFileList = isMedia
  38 + ? await _picker.getMedia(
  39 + options: MediaOptions(
  40 + allowMultiple: isMultiImage,
  41 + imageOptions: imageOptions,
  42 + limit: limit),
  43 + )
  44 + : await _picker.getMultiImageWithOptions(
  45 + options: MultiImagePickerOptions(
  46 + imageOptions: imageOptions, limit: limit),
  47 + );
  48 +
  49 + if (pickedFileList.isNotEmpty && context.mounted) {
  50 + return pickedFileList;
  51 + } else {
  52 + return [];
  53 + }
  54 + } catch (e) {
  55 + print(e.toString());
  56 + }
  57 + } else if (isMedia) {
  58 + // double? maxWidth = 300.00;
  59 + // double? maxHeight = 500;
  60 + // int? quality = 90;
  61 +
  62 + try {
  63 + final List<XFile> pickedFileList = <XFile>[];
  64 + final XFile? media = firstOrNull(await _picker.getMedia(
  65 + options: MediaOptions(
  66 + allowMultiple: isMultiImage,
  67 + // imageOptions: ImageOptions(
  68 + // maxWidth: maxWidth,
  69 + // maxHeight: maxHeight,
  70 + // imageQuality: quality,
  71 + // )
  72 + ),
  73 + ));
  74 +
  75 + if (media != null) {
  76 + pickedFileList.add(media);
  77 + print(pickedFileList);
  78 + return pickedFileList;
  79 + }
  80 + } catch (e) {
  81 + print(e.toString());
  82 + }
  83 + } else {
  84 + double? maxWidth = 300.00;
  85 + double? maxHeight = 500;
  86 + int? quality = 90;
  87 +
  88 + try {
  89 + final XFile? pickedFile = await _picker.getImageFromSource(
  90 + source: source,
  91 + options: ImagePickerOptions(
  92 + maxWidth: maxWidth,
  93 + maxHeight: maxHeight,
  94 + imageQuality: quality,
  95 + ),
  96 + );
  97 + List<XFile> temp = [];
  98 + if (pickedFile != null && context.mounted) {
  99 + temp.add(pickedFile as XFile);
  100 + }
  101 +
  102 + print(pickedFile);
  103 + return temp;
  104 +
  105 + // <XFile>[pickedFile]
  106 + } catch (e) {
  107 + print(e);
  108 + }
  109 + }
  110 + }
  111 + return [];
  112 + }
  113 +
  114 +
  115 + static T? firstOrNull<T>(List<T> list) {
  116 + return list.isEmpty ? null : list.first;
  117 + }
  118 +
  119 +}
@@ -7,7 +7,9 @@ import 'package:cached_network_image/cached_network_image.dart'; @@ -7,7 +7,9 @@ import 'package:cached_network_image/cached_network_image.dart';
7 import 'package:flutter/material.dart'; 7 import 'package:flutter/material.dart';
8 import 'package:flutter/services.dart'; 8 import 'package:flutter/services.dart';
9 import 'package:flutter_screenutil/flutter_screenutil.dart'; 9 import 'package:flutter_screenutil/flutter_screenutil.dart';
  10 +import 'package:one_key/models/mediaDN.dart';
10 import 'package:one_key/models/upload_img_model.dart'; 11 import 'package:one_key/models/upload_img_model.dart';
  12 +import 'package:one_key/pages/online_check/image_select_ohos_util.dart';
11 import 'package:one_key/pages/online_check/photo_view_wiget.dart'; 13 import 'package:one_key/pages/online_check/photo_view_wiget.dart';
12 import 'package:one_key/pages/online_check/progress.dart'; 14 import 'package:one_key/pages/online_check/progress.dart';
13 15
@@ -34,12 +36,9 @@ import './dispose.dart'; @@ -34,12 +36,9 @@ import './dispose.dart';
34 // import 'package:photo_manager/photo_manager.dart'; 36 // import 'package:photo_manager/photo_manager.dart';
35 import 'package:flutter_native_image/flutter_native_image.dart'; 37 import 'package:flutter_native_image/flutter_native_image.dart';
36 // import 'package:flutter_image_compress/flutter_image_compress.dart'; 38 // 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 39
40 -class MediaDN {  
41 - File? file;  
42 -} 40 +
  41 +
43 42
44 typedef void OnPickImageCallback( 43 typedef void OnPickImageCallback(
45 double maxWidth, double maxHeight, int quality); 44 double maxWidth, double maxHeight, int quality);
@@ -91,7 +90,7 @@ class _ImgPickerWidgetState extends DisposableState<ImgPickerWidget> { @@ -91,7 +90,7 @@ class _ImgPickerWidgetState extends DisposableState<ImgPickerWidget> {
91 // 控制器,可以用于取消任务、获取上述的状态,进度等信息 90 // 控制器,可以用于取消任务、获取上述的状态,进度等信息
92 // PutController putController = PutController(); 91 // PutController putController = PutController();
93 92
94 - final ImagePickerPlatform _picker = new ImagePickerOhos(); 93 +
95 // 当前的任务状态 94 // 当前的任务状态
96 95
97 @override 96 @override
@@ -249,116 +248,9 @@ class _ImgPickerWidgetState extends DisposableState<ImgPickerWidget> { @@ -249,116 +248,9 @@ class _ImgPickerWidgetState extends DisposableState<ImgPickerWidget> {
249 // }); 248 // });
250 // } 249 // }
251 250
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 251
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 252
351 - print(pickedFile);  
352 - return temp;  
353 253
354 - // <XFile>[pickedFile]  
355 - } catch (e) {  
356 - print(e);  
357 - }  
358 - }  
359 - }  
360 - return [];  
361 - }  
362 254
363 ///多图片选择 255 ///多图片选择
364 void pickAsset(RequestType type, {List<AssetPathEntity>? pathList}) async { 256 void pickAsset(RequestType type, {List<AssetPathEntity>? pathList}) async {
@@ -393,11 +285,12 @@ class _ImgPickerWidgetState extends DisposableState<ImgPickerWidget> { @@ -393,11 +285,12 @@ class _ImgPickerWidgetState extends DisposableState<ImgPickerWidget> {
393 imgList.add(mediaDN); 285 imgList.add(mediaDN);
394 }); 286 });
395 } else if (Platform.isOhos) { 287 } else if (Platform.isOhos) {
396 - List<XFile> imagListTemp = await _onImageButtonPressed( 288 + List<XFile> imagListTemp = await ImageSelectOhosUtil.onImageButtonPressed(
397 ImageSource.gallery, 289 ImageSource.gallery,
398 context: context, 290 context: context,
399 isMultiImage: true, 291 isMultiImage: true,
400 - isVideo: false); 292 + isVideo: false,
  293 + limit: widget.maxImageNumber - temp!.length);
401 294
402 imagListTemp.forEach((elenemt) async { 295 imagListTemp.forEach((elenemt) async {
403 MediaDN mediaDN = MediaDN(); 296 MediaDN mediaDN = MediaDN();
@@ -6,7 +6,9 @@ import 'dart:async'; @@ -6,7 +6,9 @@ import 'dart:async';
6 import 'package:cached_network_image/cached_network_image.dart'; 6 import 'package:cached_network_image/cached_network_image.dart';
7 import 'package:flutter/material.dart'; 7 import 'package:flutter/material.dart';
8 import 'package:flutter_screenutil/flutter_screenutil.dart'; 8 import 'package:flutter_screenutil/flutter_screenutil.dart';
  9 +import 'package:one_key/models/mediaDN.dart';
9 import 'package:one_key/models/upload_img_model.dart'; 10 import 'package:one_key/models/upload_img_model.dart';
  11 +import 'package:one_key/pages/online_check/image_select_ohos_util.dart';
10 import 'package:one_key/pages/online_check/photo_view_wiget.dart'; 12 import 'package:one_key/pages/online_check/photo_view_wiget.dart';
11 import 'package:one_key/pages/online_check/progress.dart'; 13 import 'package:one_key/pages/online_check/progress.dart';
12 14
@@ -200,61 +202,39 @@ class _ImgPickerFWidgetState extends DisposableState<ImgPickerFWidget> { @@ -200,61 +202,39 @@ class _ImgPickerFWidgetState extends DisposableState<ImgPickerFWidget> {
200 } else if (widget.uploadType == UploadType.FeastRemarkInvoiceType) { 202 } else if (widget.uploadType == UploadType.FeastRemarkInvoiceType) {
201 temp = widget.model!.feastRemarkInvoiceImageList; 203 temp = widget.model!.feastRemarkInvoiceImageList;
202 } 204 }
203 - List<AssetEntity>? imgList = await AssetPicker.pickAssets(context,  
204 - pickerConfig: AssetPickerConfig(  
205 - maxAssets: widget.maxImageNumber - temp!.length,  
206 - // selectedAssets: assets,  
207 - requestType: type,  
208 - themeColor: MyColours.color_199095));  
209 -  
210 - /// context is required, other params is optional.  
211 - // List<AssetEntity> imgList = await PhotoPicker.pickAsset(  
212 - // // BuildContext required  
213 - // context: context, 205 + List<MediaDN>? imgList = [];
  206 + if (Platform.isAndroid || Platform.isIOS) {
  207 + List<AssetEntity>? imagListTemp = await AssetPicker.pickAssets(context,
  208 + pickerConfig: AssetPickerConfig(
  209 + maxAssets: widget.maxImageNumber - temp!.length,
  210 + // selectedAssets: assets,
  211 + requestType: type,
  212 + themeColor: MyColours.color_199095));
  213 + imagListTemp?.forEach((elenemt) async {
  214 + MediaDN mediaDN = MediaDN();
  215 + mediaDN.file = await elenemt.file;
  216 + imgList.add(mediaDN);
  217 + });
  218 + } else if (Platform.isOhos) {
  219 + List<XFile> imagListTemp = await ImageSelectOhosUtil.onImageButtonPressed(
  220 + ImageSource.gallery,
  221 + context: context,
  222 + isMultiImage: true,
  223 + isVideo: false,
  224 + limit: widget.maxImageNumber - temp!.length);
214 225
215 - // /// The following are optional parameters.  
216 - // themeColor: MyColours.color_199095,  
217 - // // the title color and bottom color  
218 - // textColor: Colors.white,  
219 - // // text color  
220 - // padding: 1.0,  
221 - // // item padding  
222 - // dividerColor: Colors.grey,  
223 - // // divider color  
224 - // disableColor: Colors.grey.shade300,  
225 - // // the check box disable color  
226 - // itemRadio: 0.88,  
227 - // // the content item radio  
228 - // maxSelected: widget.maxImageNumber - temp.length,  
229 - // // max picker image count  
230 - // // provider: I18nProvider.english,  
231 - // provider: I18nProvider.chinese,  
232 - // // i18n provider ,default is chinese. , you can custom I18nProvider or use ENProvider()  
233 - // rowCount: 3,  
234 - // // item row count  
235 - // thumbSize: 150,  
236 - // // preview thumb size , default is 64  
237 - // sortDelegate: SortDelegate.common,  
238 - // // default is common ,or you make custom delegate to sort your gallery  
239 - // checkBoxBuilderDelegate: DefaultCheckBoxBuilderDelegate(  
240 - // activeColor: MyColours.color_353535,  
241 - // unselectedColor: Colors.white,  
242 - // checkColor: MyColours.color_199095,  
243 - // ),  
244 - // // default is DefaultCheckBoxBuilderDelegate ,or you make custom delegate to create checkbox  
245 - // // loadingDelegate: this,  
246 - // // if you want to build custom loading widget,extends LoadingDelegate, [see example/lib/main.dart]  
247 - // badgeDelegate: const DurationBadgeDelegate(),  
248 - // // badgeDelegate to show badge widget  
249 - // pickType: type,  
250 - // photoPathList: pathList,  
251 - // );  
252 - if (imgList == null || imgList.isEmpty) { 226 + imagListTemp.forEach((elenemt) async {
  227 + MediaDN mediaDN = MediaDN();
  228 + mediaDN.file = File(elenemt.path);
  229 + imgList.add(mediaDN);
  230 + });
  231 + }
  232 + if (imgList.length == 0 || imgList.isEmpty) {
253 print("No pick item."); 233 print("No pick item.");
254 return; 234 return;
255 } else { 235 } else {
256 for (int i = 0; i < imgList.length; i++) { 236 for (int i = 0; i < imgList.length; i++) {
257 - var file = (await imgList[i].file)!; 237 + var file = ( imgList[i].file)!;
258 // File compressedFile = await FlutterNativeImage.compressImage( 238 // File compressedFile = await FlutterNativeImage.compressImage(
259 // file.absolute.path, 239 // file.absolute.path,
260 // quality: 50, 240 // quality: 50,
@@ -272,7 +252,7 @@ class _ImgPickerFWidgetState extends DisposableState<ImgPickerFWidget> { @@ -272,7 +252,7 @@ class _ImgPickerFWidgetState extends DisposableState<ImgPickerFWidget> {
272 if (need) { 252 if (need) {
273 file = File(compressedFile!.absolute.path); 253 file = File(compressedFile!.absolute.path);
274 } 254 }
275 - UploadImageUtil().startUpload(context, file, temp.length - 1, false, 255 + UploadImageUtil().startUpload(context, file, temp!.length - 1, false,
276 widget.model!, widget.uploadType, 256 widget.model!, widget.uploadType,
277 countAll: imgList.length, 257 countAll: imgList.length,
278 callback: widget.callback, 258 callback: widget.callback,
@@ -134,7 +134,8 @@ class UploadImageUtil { @@ -134,7 +134,8 @@ class UploadImageUtil {
134 String? mimeType = Utils.getMimeType(selectedFile.path); 134 String? mimeType = Utils.getMimeType(selectedFile.path);
135 print(mimeType); 135 print(mimeType);
136 136
137 - String imageName = Utils.getImageNameByDateTime(selectedFile.path); 137 + String imageName =
  138 + Utils.getImageNameByDateTime(selectedFile.path, extend: '_${index}');
138 print(imageName); 139 print(imageName);
139 140
140 storage 141 storage
@@ -280,6 +281,7 @@ class UploadImageUtil { @@ -280,6 +281,7 @@ class UploadImageUtil {
280 281
281 // 取消当前任务 282 // 取消当前任务
282 putController.cancel(); 283 putController.cancel();
  284 + uploadImageProvider.countUpload = 0;
283 uploadImageProvider.notifyListeners(); 285 uploadImageProvider.notifyListeners();
284 if (error is StorageError) { 286 if (error is StorageError) {
285 switch (error.type) { 287 switch (error.type) {
@@ -372,7 +374,8 @@ class UploadImageUtil { @@ -372,7 +374,8 @@ class UploadImageUtil {
372 String? mimeType = Utils.getMimeType(selectedFile!.path); 374 String? mimeType = Utils.getMimeType(selectedFile!.path);
373 print(mimeType); 375 print(mimeType);
374 376
375 - String imageName = Utils.getImageNameByDateTime(selectedFile.path); 377 + String imageName =
  378 + Utils.getImageNameByDateTime(selectedFile.path, extend: '_${index}');
376 print(imageName); 379 print(imageName);
377 380
378 storage 381 storage
@@ -535,7 +538,8 @@ class UploadImageUtil { @@ -535,7 +538,8 @@ class UploadImageUtil {
535 String? mimeType = Utils.getMimeType(selectedFile.path); 538 String? mimeType = Utils.getMimeType(selectedFile.path);
536 print(mimeType); 539 print(mimeType);
537 540
538 - String imageName = Utils.getImageNameByDateTime(selectedFile.path); 541 + String imageName =
  542 + Utils.getImageNameByDateTime(selectedFile.path, extend: '_${index}');
539 print(imageName); 543 print(imageName);
540 544
541 storage 545 storage
@@ -69,58 +69,39 @@ import 'package:app_update_check_plugin/app_update_check_plugin.dart'; @@ -69,58 +69,39 @@ import 'package:app_update_check_plugin/app_update_check_plugin.dart';
69 typedef BookTimeSetCallback = void Function(bool needChange); 69 typedef BookTimeSetCallback = void Function(bool needChange);
70 70
71 class Utils { 71 class Utils {
  72 + static Future<bool> checkUpdateOhos() async {
  73 + // 鸿蒙商城是否有新版本
  74 + final _appUpdateCheckPlugin = AppUpdateCheckPlugin();
  75 + try {
  76 + bool hasUpdate = await _appUpdateCheckPlugin.checkAppUpdate();
  77 + if (hasUpdate) {
  78 + //跳转应用商城
72 79
73 -static Future<bool> checkUpdateOhos()async{  
74 - // 鸿蒙商城是否有新版本  
75 - final _appUpdateCheckPlugin = AppUpdateCheckPlugin();  
76 - try {  
77 - bool hasUpdate = await _appUpdateCheckPlugin.checkAppUpdate();  
78 - if (hasUpdate) {  
79 - //跳转应用商城  
80 -  
81 - return true;  
82 - } else {  
83 -  
84 - return false;  
85 - }  
86 - } on PlatformException { 80 + return true;
  81 + } else {
87 return false; 82 return false;
88 - // platformVersion = 'Failed to get platform version.';  
89 } 83 }
90 -  
91 - 84 + } on PlatformException {
  85 + return false;
  86 + // platformVersion = 'Failed to get platform version.';
  87 + }
92 } 88 }
93 89
94 -  
95 -  
96 - // 跳转到华为应用商城更新的方法  
97 -static void launchAppGallery() async{  
98 - final appid =Constant.ohos_app_id; //可以是应用id、也可以是鸿蒙应用包名  
99 - // final url='store://appgallery.huawei.com/app/detail?id=$appid'; 90 + // 跳转到华为应用商城更新的方法
  91 + static void launchAppGallery() async {
  92 + final appid = Constant.ohos_app_id; //可以是应用id、也可以是鸿蒙应用包名
  93 + // final url='store://appgallery.huawei.com/app/detail?id=$appid';
100 94
101 - final url= 'store://appgallery.huawei.com/app/detail?id=com.jd.hm.mall&channelId=LAUNCHERSHARE'; 95 + final url =
  96 + 'store://appgallery.huawei.com/app/detail?id=com.jd.hm.mall&channelId=LAUNCHERSHARE';
102 97
103 -  
104 - try{ 98 + try {
105 await launchUrl(Uri.parse(url)); 99 await launchUrl(Uri.parse(url));
106 print('打开成功'); 100 print('打开成功');
107 - }catch(err){  
108 - print('打开失败'); 101 + } catch (err) {
  102 + print('打开失败');
109 } 103 }
110 -  
111 -}  
112 -  
113 -  
114 -  
115 -  
116 -  
117 -  
118 -  
119 -  
120 -  
121 -  
122 -  
123 - 104 + }
124 105
125 static String extractFileNameFromUrl(String url) { 106 static String extractFileNameFromUrl(String url) {
126 try { 107 try {
@@ -131,16 +112,17 @@ static void launchAppGallery() async{ @@ -131,16 +112,17 @@ static void launchAppGallery() async{
131 return ""; // 或者返回null或抛出异常,根据你的需求处理错误情况 112 return ""; // 或者返回null或抛出异常,根据你的需求处理错误情况
132 } 113 }
133 } 114 }
  115 +
134 static String? getMimeType(String filePath) { 116 static String? getMimeType(String filePath) {
135 return lookupMimeType(filePath); // 使用文件扩展名查找,或者传入文件头字节查找更准确的结果 117 return lookupMimeType(filePath); // 使用文件扩展名查找,或者传入文件头字节查找更准确的结果
136 } 118 }
137 119
138 - static String getImageNameByDateTime(String filePath) { 120 + static String getImageNameByDateTime(String filePath, {String extend = ''}) {
139 // 获取当前时间的毫秒数 121 // 获取当前时间的毫秒数
140 int timestamp = DateTime.now().millisecondsSinceEpoch; 122 int timestamp = DateTime.now().millisecondsSinceEpoch;
141 // return lookupMimeType(filePath); 123 // return lookupMimeType(filePath);
142 String extension = path.extension(filePath); // 获取文件扩展名,可选步骤 124 String extension = path.extension(filePath); // 获取文件扩展名,可选步骤
143 - return timestamp.toString() + extension; 125 + return timestamp.toString() + extend + extension;
144 // 格式化时间戳为字符串(例如:1633072800000.png) 126 // 格式化时间戳为字符串(例如:1633072800000.png)
145 // String imageName = '$timestamp.png'; 127 // String imageName = '$timestamp.png';
146 } 128 }
@@ -1361,7 +1343,11 @@ static void launchAppGallery() async{ @@ -1361,7 +1343,11 @@ static void launchAppGallery() async{
1361 static getPickPermission(BuildContext context, VoidCallback callback, 1343 static getPickPermission(BuildContext context, VoidCallback callback,
1362 Permission permissionGroup) async { 1344 Permission permissionGroup) async {
1363 if (!(await checkPermission(permissionGroup))) { 1345 if (!(await checkPermission(permissionGroup))) {
1364 - String title = Platform.isAndroid ? '存储' : Platform.isIOS ? '相册':'图片和视频'; 1346 + String title = Platform.isAndroid
  1347 + ? '存储'
  1348 + : Platform.isIOS
  1349 + ? '相册'
  1350 + : '图片和视频';
1365 if (permissionGroup == Permission.camera) { 1351 if (permissionGroup == Permission.camera) {
1366 title = '相机'; 1352 title = '相机';
1367 } else if (permissionGroup == Permission.location) { 1353 } else if (permissionGroup == Permission.location) {
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 -}