Skip to content

Commit

Permalink
feat(user): change user avatar
Browse files Browse the repository at this point in the history
  • Loading branch information
lambiengcode committed Oct 8, 2023
1 parent 28e7e0b commit 32d9fd8
Show file tree
Hide file tree
Showing 19 changed files with 667 additions and 32 deletions.
44 changes: 44 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ PODS:
- flutter_facebook_auth (6.0.1):
- FBSDKLoginKit (~> 16.1.3)
- Flutter
- flutter_image_compress_common (1.0.0):
- Flutter
- Mantle
- SDWebImage
- SDWebImageWebPCoder
- flutter_native_splash (0.0.1):
- Flutter
- flutter_secure_storage (6.0.0):
Expand Down Expand Up @@ -164,6 +169,23 @@ PODS:
- AppAuth/Core (~> 1.6)
- GTMSessionFetcher/Core (< 3.0, >= 1.5)
- GTMSessionFetcher/Core (2.3.0)
- image_picker_ios (0.0.1):
- Flutter
- libwebp (1.3.2):
- libwebp/demux (= 1.3.2)
- libwebp/mux (= 1.3.2)
- libwebp/sharpyuv (= 1.3.2)
- libwebp/webp (= 1.3.2)
- libwebp/demux (1.3.2):
- libwebp/webp
- libwebp/mux (1.3.2):
- libwebp/demux
- libwebp/sharpyuv (1.3.2)
- libwebp/webp (1.3.2):
- libwebp/sharpyuv
- Mantle (2.2.0):
- Mantle/extobjc (= 2.2.0)
- Mantle/extobjc (2.2.0)
- nanopb (2.30909.0):
- nanopb/decode (= 2.30909.0)
- nanopb/encode (= 2.30909.0)
Expand All @@ -179,6 +201,12 @@ PODS:
- PromisesObjC (= 2.3.1)
- ReachabilitySwift (5.0.0)
- RecaptchaInterop (100.0.0)
- SDWebImage (5.18.2):
- SDWebImage/Core (= 5.18.2)
- SDWebImage/Core (5.18.2)
- SDWebImageWebPCoder (0.13.0):
- libwebp (~> 1.0)
- SDWebImage/Core (~> 5.17)
- sign_in_with_apple (0.0.1):
- Flutter
- sqflite (0.0.3):
Expand All @@ -196,10 +224,12 @@ DEPENDENCIES:
- firebase_performance (from `.symlinks/plugins/firebase_performance/ios`)
- Flutter (from `Flutter`)
- flutter_facebook_auth (from `.symlinks/plugins/flutter_facebook_auth/ios`)
- flutter_image_compress_common (from `.symlinks/plugins/flutter_image_compress_common/ios`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- flutter_webrtc (from `.symlinks/plugins/flutter_webrtc/ios`)
- google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/ios`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
Expand Down Expand Up @@ -231,11 +261,15 @@ SPEC REPOS:
- GoogleUtilities
- GTMAppAuth
- GTMSessionFetcher
- libwebp
- Mantle
- nanopb
- PromisesObjC
- PromisesSwift
- ReachabilitySwift
- RecaptchaInterop
- SDWebImage
- SDWebImageWebPCoder
- WebRTC-SDK

EXTERNAL SOURCES:
Expand All @@ -257,6 +291,8 @@ EXTERNAL SOURCES:
:path: Flutter
flutter_facebook_auth:
:path: ".symlinks/plugins/flutter_facebook_auth/ios"
flutter_image_compress_common:
:path: ".symlinks/plugins/flutter_image_compress_common/ios"
flutter_native_splash:
:path: ".symlinks/plugins/flutter_native_splash/ios"
flutter_secure_storage:
Expand All @@ -265,6 +301,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_webrtc/ios"
google_sign_in_ios:
:path: ".symlinks/plugins/google_sign_in_ios/ios"
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
permission_handler_apple:
Expand Down Expand Up @@ -302,6 +340,7 @@ SPEC CHECKSUMS:
FirebaseSessions: ee59a7811bef4c15f65ef6472f3210faa293f9c8
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_facebook_auth: 47c7a8594f2d6864618e30b5a6d59dff0d2e59fe
flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
flutter_webrtc: 55df3aaa802114dad390191a46c2c8d535751268
Expand All @@ -312,13 +351,18 @@ SPEC CHECKSUMS:
GoogleUtilities: 13e2c67ede716b8741c7989e26893d151b2b2084
GTMAppAuth: 0ff230db599948a9ad7470ca667337803b3fc4dd
GTMSessionFetcher: 3a63d75eecd6aa32c2fc79f578064e1214dfdec2
image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4
PromisesSwift: 28dca69a9c40779916ac2d6985a0192a5cb4a265
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
RecaptchaInterop: 7d1a4a01a6b2cb1610a47ef3f85f0c411434cb21
SDWebImage: c0de394d7cf7f9838aed1fd6bb6037654a4572e4
SDWebImageWebPCoder: af09429398d99d524cae2fe00f6f0f6e491ed102
sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440
sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
WebRTC-SDK: c24d2a6c9f571f2ed42297cb8ffba9557093142b
Expand Down
4 changes: 4 additions & 0 deletions ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@
<true/>
<key>UIStatusBarHidden</key>
<false/>
<key>NSPhotoLibraryUsageDescription</key>
<string>Waterbus needs access to your photos so you can include them in your profile.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Waterbus needs access to your photos so you can include them in your profile.</string>
<key>NSCameraUsageDescription</key>
<string>Waterbus Camera Usage!</string>
<key>NSMicrophoneUsageDescription</key>
Expand Down
45 changes: 45 additions & 0 deletions lib/core/helpers/image_utils.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Dart imports:
import 'dart:io';
import 'dart:math';

// Package imports:
import 'package:flutter_image_compress/flutter_image_compress.dart';

// Project imports:
import 'package:waterbus/core/utils/path_helper.dart';

class ImageUtils {
Future<File> reduceSize(String pathImage, {int quality = 80}) async {
if (isNeedReduce(pathImage)) {
final String tempPath = await PathHelper.tempDirWaterbus;
final XFile? result = await FlutterImageCompress.compressAndGetFile(
pathImage,
'$tempPath/${DateTime.now().microsecondsSinceEpoch}.jpeg',
quality: quality,
numberOfRetries: 2, // retry times when error
);

if (result != null) {
return File(result.path);
}
}

return File(pathImage);
}

bool isNeedReduce(String path) {
final file = File(path);
final int bytes = file.lengthSync();
if (bytes <= 0) return false;
final i = (log(bytes) / log(1024)).floor();
final size = bytes / pow(1024, i);
if (i < 1) {
if (i == 1 && size > 100) {
return false;
}

return true;
}
return true;
}
}
18 changes: 12 additions & 6 deletions lib/core/injection/injection_container.config.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

145 changes: 145 additions & 0 deletions lib/features/common/widgets/images/waterbus_image_picker.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// Dart imports:
import 'dart:io';

// Flutter imports:
import 'package:flutter/material.dart';

// Package imports:
import 'package:flutter_phosphor_icons/flutter_phosphor_icons.dart';
import 'package:image_picker/image_picker.dart';
import 'package:sizer/sizer.dart';

// Project imports:
import 'package:waterbus/core/helpers/image_utils.dart';
import 'package:waterbus/core/navigator/app_navigator.dart';
import 'package:waterbus/features/common/styles/style.dart';
import 'package:waterbus/features/common/widgets/dialogs/dialog_loading.dart';

class WaterbusImagePicker {
final ImagePicker _picker = ImagePicker();

Widget _buildImageModalButton(
BuildContext context, {
required IconData icon,
required String text,
required ImageSource source,
Function(File)? handleFinish,
}) {
return TextButton(
onPressed: () async {
try {
AppNavigator.pop();
final XFile? image = await _getImage(
context: AppNavigator.context,
source: source,
);

if (handleFinish != null && image != null) {
displayLoadingLayer();

final File imageReduce = await ImageUtils().reduceSize(
File(image.path).path,
);

handleFinish(imageReduce);

AppNavigator.pop();
}
} catch (exception) {
debugPrint(exception.toString());
}
},
style: ButtonStyle(
animationDuration: Duration.zero,
foregroundColor: MaterialStateProperty.resolveWith<Color>(
(states) {
if (states.contains(MaterialState.pressed)) {
return Colors.black.withOpacity(0.5);
}
return Colors.black;
},
),
overlayColor: MaterialStateProperty.all<Color>(Colors.transparent),
),
child: Container(
padding: EdgeInsets.symmetric(vertical: 10.sp),
child: Row(
children: [
Icon(
icon,
size: 20.sp,
color: Theme.of(context).textTheme.titleMedium?.color,
),
SizedBox(width: 12.sp),
Text(
text,
style: TextStyle(
color: Theme.of(context).textTheme.titleMedium?.color,
fontSize: 13.25.sp,
fontWeight: FontWeight.w400,
),
),
],
),
),
);
}

Future openImagePicker({
required BuildContext context,
String text = 'Change your avatar',
Function(File)? handleFinish,
}) async {
return showModalBottomSheet(
context: context,
builder: (context) {
return Container(
width: double.infinity,
height: 170.sp,
padding: EdgeInsets.symmetric(horizontal: 16.sp),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24.sp),
Text(
text,
style: TextStyle(
fontSize: 15.sp,
fontWeight: FontWeight.w600,
color: Theme.of(context).textTheme.bodyLarge?.color,
),
),
SizedBox(
height: 6.sp,
),
_buildImageModalButton(
context,
icon: PhosphorIcons.file_image,
text: 'Choose photo from gallery',
source: ImageSource.gallery,
handleFinish: handleFinish,
),
divider,
_buildImageModalButton(
context,
icon: PhosphorIcons.instagram_logo,
text: 'Take a photo',
source: ImageSource.camera,
handleFinish: handleFinish,
),
SizedBox(
height: 8.sp,
),
],
),
);
},
);
}

// MARK: private
Future _getImage({context, source = ImageSource.gallery}) async {
return await _picker.pickImage(source: source, imageQuality: 100);
}
}
1 change: 1 addition & 0 deletions lib/features/home/widgets/stack_avatar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class StackAvatar extends StatelessWidget {
size: size,
margin: EdgeInsets.only(left: index * (size * 0.8)),
urlToImage: images[index],
isCircleShape: true,
);
}
}
Loading

0 comments on commit 32d9fd8

Please sign in to comment.