Skip to content

Commit 6cc3466

Browse files
crop profile picture feature and improve comment display (#50)
* crop profile picture feature * improve comment style * fix comment style * fix default color for comment
1 parent 61b2788 commit 6cc3466

8 files changed

Lines changed: 102 additions & 21 deletions

File tree

android/app/src/main/AndroidManifest.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
<category android:name="android.intent.category.LAUNCHER"/>
3030
</intent-filter>
3131
</activity>
32+
<activity
33+
android:name="com.yalantis.ucrop.UCropActivity"
34+
android:screenOrientation="portrait"
35+
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
3236
<!-- Don't delete the meta-data below.
3337
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
3438
<meta-data

ios/Podfile.lock

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ PODS:
88
- Flutter
99
- geolocator_apple (1.2.0):
1010
- Flutter
11+
- image_cropper (0.0.4):
12+
- Flutter
13+
- TOCropViewController (~> 2.6.1)
1114
- image_gallery_saver (2.0.2):
1215
- Flutter
1316
- image_picker_ios (0.0.1):
@@ -20,6 +23,7 @@ PODS:
2023
- shared_preferences_foundation (0.0.1):
2124
- Flutter
2225
- FlutterMacOS
26+
- TOCropViewController (2.6.1)
2327
- wakelock (0.0.1):
2428
- Flutter
2529

@@ -29,13 +33,18 @@ DEPENDENCIES:
2933
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
3034
- flutter_tts (from `.symlinks/plugins/flutter_tts/ios`)
3135
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/ios`)
36+
- image_cropper (from `.symlinks/plugins/image_cropper/ios`)
3237
- image_gallery_saver (from `.symlinks/plugins/image_gallery_saver/ios`)
3338
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
3439
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
3540
- share_plus (from `.symlinks/plugins/share_plus/ios`)
3641
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
3742
- wakelock (from `.symlinks/plugins/wakelock/ios`)
3843

44+
SPEC REPOS:
45+
trunk:
46+
- TOCropViewController
47+
3948
EXTERNAL SOURCES:
4049
Flutter:
4150
:path: Flutter
@@ -47,6 +56,8 @@ EXTERNAL SOURCES:
4756
:path: ".symlinks/plugins/flutter_tts/ios"
4857
geolocator_apple:
4958
:path: ".symlinks/plugins/geolocator_apple/ios"
59+
image_cropper:
60+
:path: ".symlinks/plugins/image_cropper/ios"
5061
image_gallery_saver:
5162
:path: ".symlinks/plugins/image_gallery_saver/ios"
5263
image_picker_ios:
@@ -66,11 +77,13 @@ SPEC CHECKSUMS:
6677
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
6778
flutter_tts: 0f492aab6accf87059b72354fcb4ba934304771d
6879
geolocator_apple: 9157311f654584b9bb72686c55fc02a97b73f461
80+
image_cropper: a3291c624a953049bc6a02e1f8c8ceb162a24b25
6981
image_gallery_saver: cb43cc43141711190510e92c460eb1655cd343cb
7082
image_picker_ios: 99dfe1854b4fa34d0364e74a78448a0151025425
7183
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
7284
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
7385
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
86+
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
7487
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
7588

7689
PODFILE CHECKSUM: 2442f0b84dc733c75ff32e76bcf04626a168288b

lib/presentation/common/activity/widgets/activity_comments.dart

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,21 @@ class ActivityComments extends HookConsumerWidget {
2222
final GlobalKey<FormState> formKey;
2323

2424
final currentUserPictureDataProvider =
25-
FutureProvider.family<String?, Activity>((ref, activity) async {
25+
FutureProvider.family<ImageProvider?, Activity>((ref, activity) async {
2626
final user = await StorageUtils.getUser();
2727
final provider =
2828
ref.read(activityItemViewModelProvider(activity.id).notifier);
2929

3030
user != null ? provider.getProfilePicture(user.id) : null;
31-
return user?.id;
31+
32+
if (user?.id != null) {
33+
final profilePicture =
34+
ref.watch(profilePictureViewModelProvider(user!.id)).profilePicture;
35+
return profilePicture != null
36+
? MemoryImage(profilePicture)
37+
: await ColorUtils.colorToImageProvider((Colors.white70));
38+
}
39+
return await ColorUtils.colorToImageProvider(Colors.white70);
3240
});
3341

3442
final commentUserPictureDataProvider =
@@ -90,7 +98,6 @@ class ActivityComments extends HookConsumerWidget {
9098
overflow: TextOverflow.visible,
9199
),
92100
),
93-
const Spacer(),
94101
if (currentUser.id == comment.user.id)
95102
IconButton(
96103
color: ColorUtils.black,
@@ -201,24 +208,14 @@ class ActivityComments extends HookConsumerWidget {
201208
height: state.comments.isNotEmpty ? 210 : 80,
202209
child: CommentBox(
203210
userImage: currentUserPictureProvider.when(
204-
data: (userId) {
205-
if (userId != null) {
206-
final profilePicture = ref
207-
.watch(profilePictureViewModelProvider(userId))
208-
.profilePicture;
209-
return profilePicture != null
210-
? MemoryImage(profilePicture)
211-
: null;
212-
}
213-
return null;
214-
},
215-
loading: () => null,
216-
error: (_, __) => null,
217-
),
211+
data: (picture) {
212+
return picture;
213+
},
214+
loading: () => null,
215+
error: (_, __) => null),
218216
sendButtonMethod: () => commentsProvider.comment(currentActivity),
219217
formKey: formKey,
220218
commentController: commentsProvider.commentController,
221-
backgroundColor: ColorUtils.white,
222219
textColor: ColorUtils.mainMedium,
223220
sendWidget:
224221
Icon(Icons.send_sharp, size: 30, color: ColorUtils.main),

lib/presentation/common/core/utils/color_utils.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'dart:ui' as ui;
2+
13
import 'package:flutter/material.dart';
24

35
/// Utility class for color-related operations.
@@ -66,6 +68,22 @@ class ColorUtils {
6668
final lightColor = generateLightColor(baseColor);
6769
return [darkColor, lightColor];
6870
}
71+
72+
static Future<ImageProvider<Object>?> colorToImageProvider(Color color,
73+
{double width = 32.0, double height = 32.0}) async {
74+
final recorder = ui.PictureRecorder();
75+
final canvas = Canvas(recorder);
76+
final paint = Paint()..color = color;
77+
canvas.drawRect(Rect.fromLTRB(0, 0, width, height), paint);
78+
final picture = recorder.endRecording();
79+
final img = await picture.toImage(width.toInt(), height.toInt());
80+
final byteData = await img.toByteData(format: ui.ImageByteFormat.png);
81+
if (byteData != null) {
82+
return MemoryImage(byteData.buffer.asUint8List());
83+
} else {
84+
return null;
85+
}
86+
}
6987
}
7088

7189
/// Extension methods for the [Color] class.

lib/presentation/common/core/widgets/upload_file.dart

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import 'dart:typed_data';
33
import 'package:flutter/material.dart';
44
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
55
import 'package:hooks_riverpod/hooks_riverpod.dart';
6+
import 'package:image_cropper/image_cropper.dart';
67
import 'package:image_picker/image_picker.dart';
7-
import '../utils/ui_utils.dart';
88

99
import '../utils/color_utils.dart';
10+
import '../utils/ui_utils.dart';
1011

1112
/// A widget that allow to upload a file
1213
class UploadFileWidget extends HookConsumerWidget {
@@ -61,9 +62,32 @@ class UploadFileWidget extends HookConsumerWidget {
6162
await _picker.pickImage(source: ImageSource.gallery);
6263

6364
if (pickedImage != null) {
64-
Uint8List file = await pickedImage.readAsBytes();
65+
CroppedFile? croppedFile = await ImageCropper().cropImage(
66+
sourcePath: pickedImage.path,
67+
aspectRatioPresets: [
68+
CropAspectRatioPreset.square,
69+
CropAspectRatioPreset.ratio3x2,
70+
CropAspectRatioPreset.original,
71+
CropAspectRatioPreset.ratio4x3,
72+
CropAspectRatioPreset.ratio16x9
73+
],
74+
uiSettings: [
75+
AndroidUiSettings(
76+
toolbarTitle: 'Cropper',
77+
toolbarColor: ColorUtils.main,
78+
toolbarWidgetColor: Colors.white,
79+
initAspectRatio: CropAspectRatioPreset.square,
80+
lockAspectRatio: false),
81+
IOSUiSettings(
82+
title: 'Cropper',
83+
),
84+
],
85+
);
6586

66-
callbackFunc(file);
87+
if (croppedFile != null) {
88+
Uint8List file = await croppedFile.readAsBytes();
89+
callbackFunc(file);
90+
}
6791
}
6892
},
6993
child: Text(AppLocalizations.of(context)!.profile_picture_select,

pubspec.lock

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,30 @@ packages:
541541
url: "https://pub.dev"
542542
source: hosted
543543
version: "4.1.6"
544+
image_cropper:
545+
dependency: "direct main"
546+
description:
547+
name: image_cropper
548+
sha256: f4bad5ed2dfff5a7ce0dfbad545b46a945c702bb6182a921488ef01ba7693111
549+
url: "https://pub.dev"
550+
source: hosted
551+
version: "5.0.1"
552+
image_cropper_for_web:
553+
dependency: transitive
554+
description:
555+
name: image_cropper_for_web
556+
sha256: "865d798b5c9d826f1185b32e5d0018c4183ddb77b7b82a931e1a06aa3b74974e"
557+
url: "https://pub.dev"
558+
source: hosted
559+
version: "3.0.0"
560+
image_cropper_platform_interface:
561+
dependency: transitive
562+
description:
563+
name: image_cropper_platform_interface
564+
sha256: ee160d686422272aa306125f3b6fb1c1894d9b87a5e20ed33fa008e7285da11e
565+
url: "https://pub.dev"
566+
source: hosted
567+
version: "5.0.0"
544568
image_gallery_saver:
545569
dependency: "direct main"
546570
description:

pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ dependencies:
6969
image_picker: ^1.0.4
7070
share_plus: ^6.3.4
7171
comment_box: ^0.0.18
72+
image_cropper: ^5.0.1
7273

7374
dev_dependencies:
7475
flutter_test:
5.57 KB
Loading

0 commit comments

Comments
 (0)