diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index e1ff723..34d2e7f 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -36,6 +36,10 @@ + diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 030b5b7..402e2e1 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -9,6 +9,9 @@ PODS: - FMDB (2.7.5): - FMDB/standard (= 2.7.5) - FMDB/standard (2.7.5) + - image_cropper (0.0.4): + - Flutter + - TOCropViewController (~> 2.6.1) - image_picker (0.0.1): - Flutter - just_audio (0.0.1): @@ -20,6 +23,7 @@ PODS: - sqflite (0.0.2): - Flutter - FMDB (>= 2.7.5) + - TOCropViewController (2.6.1) - url_launcher_ios (0.0.1): - Flutter @@ -28,6 +32,7 @@ DEPENDENCIES: - Flutter (from `Flutter`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - flutter_vibrate (from `.symlinks/plugins/flutter_vibrate/ios`) + - image_cropper (from `.symlinks/plugins/image_cropper/ios`) - image_picker (from `.symlinks/plugins/image_picker/ios`) - just_audio (from `.symlinks/plugins/just_audio/ios`) - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`) @@ -38,6 +43,7 @@ DEPENDENCIES: SPEC REPOS: trunk: - FMDB + - TOCropViewController EXTERNAL SOURCES: audio_session: @@ -48,6 +54,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_secure_storage/ios" flutter_vibrate: :path: ".symlinks/plugins/flutter_vibrate/ios" + image_cropper: + :path: ".symlinks/plugins/image_cropper/ios" image_picker: :path: ".symlinks/plugins/image_picker/ios" just_audio: @@ -67,11 +75,13 @@ SPEC CHECKSUMS: flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec flutter_vibrate: 9f4c2ab57008965f78969472367c329dd77eb801 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + image_cropper: 60c2789d1f1a78c873235d4319ca0c34a69f2d98 image_picker: 9aa50e1d8cdacdbed739e925b7eea16d014367e6 just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa path_provider_ios: 7d7ce634493af4477d156294792024ec3485acd5 record: 7ee2393532f8553bbb09fa19e95478323b7c0a99 sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 + TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863 url_launcher_ios: 02f1989d4e14e998335b02b67a7590fa34f971af PODFILE CHECKSUM: a75497545d4391e2d394c3668e20cfb1c2bbd4aa diff --git a/lib/pages/home/settings/profile/widgets/profile_photo.dart b/lib/pages/home/settings/profile/widgets/profile_photo.dart index 53c1003..1791b94 100644 --- a/lib/pages/home/settings/profile/widgets/profile_photo.dart +++ b/lib/pages/home/settings/profile/widgets/profile_photo.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:didvan/config/theme_data.dart'; import 'package:didvan/constants/app_icons.dart'; import 'package:didvan/models/enums.dart'; @@ -5,15 +7,16 @@ import 'package:didvan/models/view/action_sheet_data.dart'; import 'package:didvan/models/view/alert_data.dart'; import 'package:didvan/pages/home/widgets/menu_item.dart'; import 'package:didvan/providers/user_provider.dart'; -import 'package:didvan/routes/routes.dart'; import 'package:didvan/services/media/media.dart'; import 'package:didvan/utils/action_sheet.dart'; import 'package:didvan/widgets/didvan/divider.dart'; import 'package:didvan/widgets/didvan/text.dart'; import 'package:didvan/widgets/skeleton_image.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:provider/provider.dart'; +import 'package:image_cropper/image_cropper.dart'; class ProfilePhoto extends StatefulWidget { const ProfilePhoto({Key? key}) : super(key: key); @@ -135,27 +138,31 @@ class _ProfilePhotoState extends State { return; } final pickedFile = await MediaService.pickImage(source: source); - if (pickedFile != null) { - ActionSheetUtils.showLogoLoadingIndicator(); - final bytes = await pickedFile.readAsBytes(); - ActionSheetUtils.pop(); - Navigator.of(context).pushNamed( - Routes.imageCropper, - arguments: { - 'bytes': bytes, - 'onCropped': () async { - final result = await state.setProfilePhoto(pickedFile); - ActionSheetUtils.showAlert( - AlertData( - message: result - ? 'تصویر پروفایل بارگذاری شد.' - : 'بارگذاری تصویر موفقیت آمیز نبود.', - aLertType: result ? ALertType.success : ALertType.error, - ), - ); - } - }, + File? file; + if (pickedFile != null && !kIsWeb) { + file = await ImageCropper().cropImage( + sourcePath: pickedFile.path, + aspectRatio: const CropAspectRatio(ratioX: 1, ratioY: 1), + iosUiSettings: const IOSUiSettings( + title: 'برش تصویر', + doneButtonTitle: 'تایید', + cancelButtonTitle: 'بازگشت', + ), + androidUiSettings: const AndroidUiSettings(toolbarTitle: 'برش تصویر'), + compressQuality: 70, ); + if (file == null) return; } + if (pickedFile == null) return; + final uploadFile = kIsWeb ? pickedFile : file; + final result = await state.setProfilePhoto(uploadFile); + ActionSheetUtils.showAlert( + AlertData( + message: result + ? 'تصویر پروفایل بارگذاری شد.' + : 'بارگذاری تصویر موفقیت آمیز نبود.', + aLertType: result ? ALertType.success : ALertType.error, + ), + ); } } diff --git a/lib/pages/splash/splash.dart b/lib/pages/splash/splash.dart index 9850236..7aaddf7 100644 --- a/lib/pages/splash/splash.dart +++ b/lib/pages/splash/splash.dart @@ -64,7 +64,7 @@ class _SplashState extends State { SpinKitSpinningLines( color: Theme.of(context).colorScheme.primary, ), - if (_errorOccured) const SizedBox(height: 38), + if (_errorOccured) const SizedBox(height: 30), if (_errorOccured) DidvanButton( width: 120, diff --git a/lib/providers/user_provider.dart b/lib/providers/user_provider.dart index 77aa17d..219acd1 100644 --- a/lib/providers/user_provider.dart +++ b/lib/providers/user_provider.dart @@ -64,7 +64,7 @@ class UserProvider extends CoreProvier { appState = AppState.idle; return true; } - appState = AppState.failed; + appState = AppState.idle; return false; } diff --git a/lib/routes/route_generator.dart b/lib/routes/route_generator.dart index 2f145d4..450a9a1 100644 --- a/lib/routes/route_generator.dart +++ b/lib/routes/route_generator.dart @@ -24,7 +24,6 @@ import 'package:didvan/pages/home/settings/general_settings/settings_state.dart' import 'package:didvan/pages/home/settings/profile/profile.dart'; import 'package:didvan/pages/splash/splash.dart'; import 'package:didvan/routes/routes.dart'; -import 'package:didvan/widgets/image_cropper.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -67,12 +66,6 @@ class RouteGenerator { return _createRoute( const AboutUs(), ); - case Routes.imageCropper: - return _createRoute( - ImageCropper( - data: settings.arguments as Map, - ), - ); case Routes.generalSettings: return _createRoute( ChangeNotifierProvider( diff --git a/lib/widgets/image_cropper.dart b/lib/widgets/image_cropper.dart deleted file mode 100644 index fd67e93..0000000 --- a/lib/widgets/image_cropper.dart +++ /dev/null @@ -1,201 +0,0 @@ -import 'package:crop/crop.dart'; -import 'package:didvan/config/theme_data.dart'; -import 'package:didvan/constants/app_icons.dart'; -import 'package:flutter/material.dart'; - -class ImageCropper extends StatefulWidget { - final Map data; - - const ImageCropper({Key? key, required this.data}) : super(key: key); - - @override - State createState() => _ImageCropperState(); -} - -class _ImageCropperState extends State { - double _rotation = 0; - BoxShape shape = BoxShape.rectangle; - - final _controller = CropController(); - - get _bytes => widget.data['bytes']; - get _onCropped => widget.data['onCropped']; - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - return Scaffold( - appBar: AppBar( - title: const Text('برش عکس'), - centerTitle: true, - actions: [ - IconButton( - onPressed: _cropImage, - tooltip: 'Crop', - icon: const Icon(Icons.crop), - ) - ], - ), - body: Column( - children: [ - Expanded( - child: Container( - color: Colors.black, - padding: const EdgeInsets.all(8), - child: Crop( - onChanged: (decomposition) { - if (_rotation != decomposition.rotation) { - setState(() { - _rotation = ((decomposition.rotation + 180) % 360) - 180; - }); - } - }, - controller: _controller, - shape: shape, - child: Image.memory( - _bytes, - fit: BoxFit.cover, - ), - helper: shape == BoxShape.rectangle - ? Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.white, width: 2), - ), - ) - : null, - ), - ), - ), - Row( - children: [ - IconButton( - icon: const Icon(Icons.redo), - tooltip: 'برگرداندن', - onPressed: () { - _controller.rotation = 0; - _controller.scale = 1; - _controller.offset = Offset.zero; - setState(() { - _rotation = 0; - }); - }, - ), - Expanded( - child: SliderTheme( - data: theme.sliderTheme.copyWith( - trackShape: const RectangularSliderTrackShape(), - ), - child: Slider( - thumbColor: Theme.of(context).colorScheme.title, - divisions: 360, - value: _rotation, - min: -180, - max: 180, - label: '$_rotation°', - onChanged: (n) { - setState(() { - _rotation = n.roundToDouble(); - _controller.rotation = _rotation; - }); - }, - ), - ), - ), - // PopupMenuButton( - // icon: const Icon(Icons.crop_free), - // itemBuilder: (context) => [ - // const PopupMenuItem( - // child: Text("Box"), - // value: BoxShape.rectangle, - // ), - // const PopupMenuItem( - // child: Text("Oval"), - // value: BoxShape.circle, - // ), - // ], - // tooltip: 'Crop Shape', - // onSelected: (x) { - // setState(() { - // shape = x; - // }); - // }, - // ), - // PopupMenuButton( - // icon: const Icon(Icons.aspect_ratio), - // itemBuilder: (context) => [ - // const PopupMenuItem( - // child: Text("Original"), - // value: 1000 / 667.0, - // ), - // const PopupMenuDivider(), - // const PopupMenuItem( - // child: Text("16:9"), - // value: 16.0 / 9.0, - // ), - // const PopupMenuItem( - // child: Text("4:3"), - // value: 4.0 / 3.0, - // ), - // const PopupMenuItem( - // child: Text("1:1"), - // value: 1, - // ), - // const PopupMenuItem( - // child: Text("3:4"), - // value: 3.0 / 4.0, - // ), - // const PopupMenuItem( - // child: Text("9:16"), - // value: 9.0 / 16.0, - // ), - // ], - // tooltip: 'Aspect Ratio', - // onSelected: (x) { - // _controller.aspectRatio = x; - // setState(() {}); - // }, - // ), - ], - ), - ], - ), - ); - } - - void _cropImage() async { - final pixelRatio = MediaQuery.of(context).devicePixelRatio; - final cropped = await _controller.crop(pixelRatio: pixelRatio); - - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => Scaffold( - appBar: AppBar( - title: const Text('تایید برش'), - centerTitle: true, - actions: [ - Builder( - builder: (context) => IconButton( - icon: const Icon( - DidvanIcons.check_circle_solid, - size: 32, - ), - onPressed: () { - Navigator.of(context).pop(); - Navigator.of(context).pop(); - _onCropped(); - }, - ), - ), - ], - ), - body: Center( - child: RawImage( - image: cropped, - ), - ), - ), - fullscreenDialog: true, - ), - ); - } -} diff --git a/pubspec.lock b/pubspec.lock index 21c01a3..6942b4d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -92,20 +92,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.15.0" - collision: - dependency: transitive - description: - name: collision - url: "https://pub.dartlang.org" - source: hosted - version: "0.0.3" - crop: - dependency: "direct main" - description: - name: crop - url: "https://pub.dartlang.org" - source: hosted - version: "0.5.2" cross_file: dependency: transitive description: @@ -308,6 +294,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.0" + image_cropper: + dependency: "direct main" + description: + name: image_cropper + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.0" image_picker: dependency: "direct main" description: @@ -656,13 +649,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.8" - transparent_image: - dependency: "direct main" - description: - name: transparent_image - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 9174c6b..119a748 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -57,10 +57,10 @@ dependencies: bot_toast: ^4.0.1 flutter_secure_storage: ^5.0.2 flutter_html: ^3.0.0-alpha.2 - crop: ^0.5.2 url_launcher: ^6.0.18 - transparent_image: ^2.0.0 audio_video_progress_bar: ^0.10.0 + image_cropper: ^1.5.0 + dev_dependencies: flutter_test: