Skip to content

Commit

Permalink
added ImageService and written its tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Azad99-9 committed Dec 21, 2023
1 parent c32f81c commit 2f89048
Show file tree
Hide file tree
Showing 11 changed files with 296 additions and 187 deletions.
13 changes: 9 additions & 4 deletions lib/locator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:talawa/services/comment_service.dart';
import 'package:talawa/services/database_mutation_functions.dart';
import 'package:talawa/services/event_service.dart';
import 'package:talawa/services/graphql_config.dart';
import 'package:talawa/services/image_service.dart';
import 'package:talawa/services/navigation_service.dart';
import 'package:talawa/services/org_service.dart';
import 'package:talawa/services/post_service.dart';
Expand Down Expand Up @@ -70,12 +71,15 @@ final connectivity = locator<Connectivity>();
///creating GetIt for OrganizationService.
final organizationService = locator<OrganizationService>();

///creating GetIt for ImageCropper.
final imageCropper = locator<ImageCropper>();

///creating GetIt for ImagePicker.
final imagePicker = locator<ImagePicker>();

///creating GetIt for ImageService.
final imageService = locator<ImageService>();

Check warning on line 78 in lib/locator.dart

View check run for this annotation

Codecov / codecov/patch

lib/locator.dart#L78

Added line #L78 was not covered by tests

///creating GetIt for ImageCropper.
final imageCropper = locator<ImageCropper>();

Check warning on line 81 in lib/locator.dart

View check run for this annotation

Codecov / codecov/patch

lib/locator.dart#L81

Added line #L81 was not covered by tests

/// This function registers the widgets/objects in "GetIt".
///
/// **params**:
Expand Down Expand Up @@ -104,8 +108,9 @@ void setupLocator() {
locator.registerLazySingleton(() => MultiMediaPickerService());
locator.registerLazySingleton(() => Connectivity());
locator.registerLazySingleton(() => ChatService());
locator.registerLazySingleton(() => ImageCropper());
locator.registerLazySingleton(() => ImageService());
locator.registerLazySingleton(() => ImagePicker());
locator.registerLazySingleton(() => ImageCropper());

//graphql
locator.registerSingleton(GraphqlConfig());
Expand Down
78 changes: 78 additions & 0 deletions lib/services/image_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:talawa/locator.dart';

/// ImageService class provides different functions as service in the context of Images.
///
/// Services include:
/// * `cropImage`
/// * `convertToBase64`
class ImageService {
/// instance of ImageCropper.
final ImageCropper _imageCropper = locator<ImageCropper>();

/// This function is used to crop the image selected by the user.
///
/// The function accepts a `File` type image and returns `File` type of cropped image.
///
/// **params**:
/// * `imageFile`: the image file to be cropped.
///
/// **returns**:
/// * `Future<File?>`: the image after been cropped.
Future<File?> cropImage({required File imageFile}) async {
// try, to crop the image and returns a File with cropped image path.
try {
final CroppedFile? croppedImage = await _imageCropper.cropImage(
sourcePath: imageFile.path,
aspectRatioPresets: [
CropAspectRatioPreset.square,
CropAspectRatioPreset.original,
],
uiSettings: [
AndroidUiSettings(
toolbarTitle: 'Crop Image',
toolbarColor: const Color(0xff18191A),
toolbarWidgetColor: Colors.white,
backgroundColor: Colors.black,
cropGridColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false,
),
IOSUiSettings(
minimumAspectRatio: 1.0,
),
],
);
if (croppedImage != null) {
return File(croppedImage.path);
}
} catch (e) {
print(
"MultiMediaPickerService : Exception occurred while cropping Image",
);
}
return null;
}

/// This function is used to convert the image into Base64 format.
///
/// **params**:
/// * `file`: Takes the image in format of file.
///
/// **returns**:
/// * `Future<String>`: image in string format
Future<String> convertToBase64(File file) async {
try {
final List<int> bytes = await file.readAsBytes();
final String base64String = base64Encode(bytes);
print(base64String);
return base64String;
} catch (error) {
return '';
}
}
}
70 changes: 19 additions & 51 deletions lib/services/third_party_service/multi_media_pick_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ Service usage: "add_post_view_model.dart"
import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:talawa/locator.dart';
import 'package:talawa/services/image_service.dart';
import 'package:talawa/services/navigation_service.dart';
import 'package:talawa/widgets/custom_alert_dialog.dart';

Expand All @@ -26,12 +25,14 @@ class MultiMediaPickerService {
MultiMediaPickerService() {
_picker = locator<ImagePicker>();
_fileStream = _fileStreamController.stream.asBroadcastStream();
_imageService = locator<ImageService>();
}

//Local Variables
final StreamController<File> _fileStreamController = StreamController();
late Stream<File> _fileStream;
late ImagePicker _picker;
late ImageService _imageService;
//Getters

/// This function returns the stream of files.
Expand Down Expand Up @@ -63,23 +64,14 @@ class MultiMediaPickerService {
);
// if image is selected or not null, call the cropImage function that provide service to crop the selected image.
if (image != null) {
return await cropImage(imageFile: File(image.path));
return await _imageService.cropImage(imageFile: File(image.path));
}
} catch (e) {
// if the permission denied or error occurs.
if (e is PlatformException && e.code == 'camera_access_denied') {
// push the dialog alert with the message.
locator<NavigationService>().pushDialog(
CustomAlertDialog(
success: () {
locator<NavigationService>().pop();
openAppSettings();
},
dialogTitle: 'Permission Denied',
successText: 'SETTINGS',
dialogSubTitle:
"Camera permission is required, to use this feature, give permission from app settings",
),
permissionDeniedDialog(),
);
}
print(
Expand All @@ -89,47 +81,23 @@ class MultiMediaPickerService {
return null;
}

/// This function is used to crop the image selected by the user.
///
/// The function accepts a `File` type image and returns `File` type of cropped image.
/// This function returns the permission denied dialog.
///
/// **params**:
/// * `imageFile`: the image file to be cropped.
/// None
///
/// **returns**:
/// * `Future<File?>`: the image after been cropped.
Future<File?> cropImage({required File imageFile}) async {
// try, to crop the image and returns a File with cropped image path.
try {
final CroppedFile? croppedImage = await locator<ImageCropper>().cropImage(
sourcePath: imageFile.path,
aspectRatioPresets: [
CropAspectRatioPreset.square,
CropAspectRatioPreset.original,
],
uiSettings: [
AndroidUiSettings(
toolbarTitle: 'Crop Image',
toolbarColor: const Color(0xff18191A),
toolbarWidgetColor: Colors.white,
backgroundColor: Colors.black,
cropGridColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false,
),
IOSUiSettings(
minimumAspectRatio: 1.0,
),
],
);
if (croppedImage != null) {
return File(croppedImage.path);
}
} catch (e) {
print(
"MultiMediaPickerService : Exception occurred while cropping Image",
);
}
return null;
/// * `CustomAlertDialog`: Custom Alert Dialog widget.
CustomAlertDialog permissionDeniedDialog() {
return CustomAlertDialog(
success: () {
locator<NavigationService>().pop();
openAppSettings();
},
dialogTitle: 'Permission Denied',
successText: 'SETTINGS',
dialogSubTitle:
"Camera permission is required, to use this feature, give permission from app settings",
);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:talawa/enums/enums.dart';
import 'package:talawa/locator.dart';
import 'package:talawa/models/organization/org_info.dart';
import 'package:talawa/services/database_mutation_functions.dart';
import 'package:talawa/services/image_service.dart';
import 'package:talawa/services/navigation_service.dart';
import 'package:talawa/services/third_party_service/multi_media_pick_service.dart';
import 'package:talawa/services/user_config.dart';
Expand All @@ -22,6 +22,7 @@ class AddPostViewModel extends BaseModel {
//Services
late MultiMediaPickerService _multiMediaPickerService;
late NavigationService _navigationService;
late ImageService _imageService;

// ignore: unused_field
late File? _imageFile;
Expand Down Expand Up @@ -65,7 +66,7 @@ class AddPostViewModel extends BaseModel {
/// **returns**:
/// * `Future<void>`: define_the_return
Future<void> setImageInBase64(File file) async {
_imageInBase64 = await convertToBase64(file);
_imageInBase64 = await _imageService.convertToBase64(file);
notifyListeners();
}

Expand Down Expand Up @@ -121,33 +122,15 @@ class AddPostViewModel extends BaseModel {
void initialise() {
_navigationService = locator<NavigationService>();
_imageFile = null;
_imageInBase64 = null;
_multiMediaPickerService = locator<MultiMediaPickerService>();
_imageService = locator<ImageService>();
if (!demoMode) {
_dbFunctions = locator<DataBaseMutationFunctions>();
_selectedOrg = locator<UserConfig>().currentOrg;
}
}

/// to convert the image in base64.
///
///
/// **params**:
/// * `file`: file of image clicked.
///
/// **returns**:
/// * `Future<String>`: Future string containing the base 64 format image
Future<String> convertToBase64(File file) async {
try {
final List<int> bytes = await file.readAsBytes();
final String base64String = base64Encode(bytes);
print(base64String);
_imageInBase64 = base64String;
return base64String;
} catch (error) {
return '';
}
}

/// This function is used to get the image from gallery.
///
/// The function uses the `_multiMediaPickerService` services.
Expand All @@ -164,7 +147,7 @@ class AddPostViewModel extends BaseModel {
if (image != null) {
_imageFile = image;
// convertImageToBase64(image.path);
convertToBase64(image);
_imageInBase64 = await _imageService.convertToBase64(image);
// print(_imageInBase64);
_navigationService.showTalawaErrorSnackBar(
"Image is added",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
Expand Down Expand Up @@ -63,25 +62,6 @@ class EditProfilePageViewModel extends BaseModel {
}
}

/// This function is used to convert the image into Base64 format.
///
/// **params**:
/// * `file`: Takes the image in format of file.
///
/// **returns**:
/// * `Future<String>`: image in string format
Future<String> convertToBase64(File file) async {
try {
final List<int> bytes = await file.readAsBytes();
final String base64String = base64Encode(bytes);
print(base64String);
imageFile = base64String as File?;
return base64String;
} catch (error) {
return '';
}
}

/// This function remove the selected image.
///
/// **params**:
Expand Down
9 changes: 9 additions & 0 deletions test/helpers/test_helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import 'package:talawa/services/comment_service.dart';
import 'package:talawa/services/database_mutation_functions.dart';
import 'package:talawa/services/event_service.dart';
import 'package:talawa/services/graphql_config.dart';
import 'package:talawa/services/image_service.dart';
import 'package:talawa/services/navigation_service.dart';
import 'package:talawa/services/org_service.dart';
import 'package:talawa/services/post_service.dart';
Expand Down Expand Up @@ -53,6 +54,7 @@ import 'package:talawa/view_model/theme_view_model.dart';
import 'package:talawa/view_model/widgets_view_models/custom_drawer_view_model.dart';
import 'package:talawa/view_model/widgets_view_models/like_button_view_model.dart';
import 'package:talawa/view_model/widgets_view_models/progress_dialog_view_model.dart';
import '../service_tests/image_service_test.dart';
import '../views/main_screen_test.dart';
import 'test_helpers.mocks.dart';

Expand Down Expand Up @@ -427,6 +429,13 @@ ImageCropper getAndRegisterImageCropper() {
return service;
}

ImageService getAndRegisterImageService() {
_removeRegistrationIfExists<ImageService>();
final service = MockImageService();
locator.registerLazySingleton<ImageService>(() => service);
return service;
}

ImagePicker getAndRegisterImagePicker() {
_removeRegistrationIfExists<ImagePicker>();
final service = MockImagePicker();
Expand Down
Loading

0 comments on commit 2f89048

Please sign in to comment.