1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-25 22:39:22 +00:00

Can crop image

This commit is contained in:
Pierre HUBERT 2021-03-13 17:50:59 +01:00
parent 2a00530126
commit ea45bf828c
7 changed files with 91 additions and 6 deletions

View File

@ -14,6 +14,7 @@
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<!-- This is required on Android 11+ for image picker -->
<queries> <queries>
<intent> <intent>
<action android:name="android.media.action.IMAGE_CAPTURE" /> <action android:name="android.media.action.IMAGE_CAPTURE" />
@ -69,5 +70,11 @@
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
</activity> </activity>
<!-- This let the image cropper work -->
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
</application> </application>
</manifest> </manifest>

View File

@ -1,5 +1,6 @@
import 'package:comunic/models/api_request.dart'; import 'package:comunic/models/api_request.dart';
import 'package:comunic/ui/dialogs/record_audio_dialog.dart'; import 'package:comunic/ui/dialogs/record_audio_dialog.dart';
import 'package:comunic/ui/routes/image_editor_route.dart';
import 'package:comunic/utils/files_utils.dart'; import 'package:comunic/utils/files_utils.dart';
import 'package:comunic/utils/intl_utils.dart'; import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart'; import 'package:comunic/utils/ui_utils.dart';
@ -132,6 +133,8 @@ Future<BytesFile> showPickFileDialog({
file = BytesFile(image.path.split("/").last, await image.readAsBytes()); file = BytesFile(image.path.split("/").last, await image.readAsBytes());
file = await showImageCropper(context, file);
break; break;
// Pick an video // Pick an video

View File

@ -0,0 +1,53 @@
import 'dart:io';
import 'package:comunic/models/api_request.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/log_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:flutter/material.dart';
import 'package:image_cropper/image_cropper.dart';
import '../../models/api_request.dart';
import '../../utils/files_utils.dart';
/// Image cropper route
///
/// @author Pierre Hubert
/// Attempt to crop image
///
/// Return original image in case of error / if the user did not crop the image
Future<BytesFile> showImageCropper(
BuildContext context, BytesFile source) async {
assert(context != null);
assert(source != null);
File file;
File cropped;
try {
file = await generateTemporaryFile();
await file.writeAsBytes(source.bytes);
File cropped = await ImageCropper.cropImage(
sourcePath: file.absolute.path,
compressFormat: ImageCompressFormat.png,
androidUiSettings: AndroidUiSettings(
toolbarColor: Colors.black,
toolbarTitle: tr("Crop Photo"),
toolbarWidgetColor: Colors.white,
),
);
if (cropped == null) return null;
return BytesFile("cropped.png", await cropped.readAsBytes());
} catch (e, s) {
logError(e, s);
snack(context, tr("Failed to execute image cropper!"));
return source;
} finally {
if (file != null && await file.exists()) file.delete();
if (cropped != null && await cropped.exists()) cropped.delete();
}
}

View File

@ -1,6 +1,11 @@
import 'dart:io';
import 'package:comunic/utils/intl_utils.dart'; import 'package:comunic/utils/intl_utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
import 'package:random_string/random_string.dart';
/// Files utilities /// Files utilities
/// ///
@ -46,6 +51,16 @@ Future<PickedFile> pickImage(BuildContext context) async {
: ImageSource.gallery); : ImageSource.gallery);
} }
/// Generate a new temporary file
///
/// Throws in case of failure
Future<File> generateTemporaryFile() async {
final tempDir = await getTemporaryDirectory();
if (tempDir == null)
throw Exception("Could not generate temporary directory!");
return File(path.join(tempDir.path, randomString(15, from: 65, to: 90)));
}
/// Check if a mime type maps to an image or not /// Check if a mime type maps to an image or not
bool isImage(String mimeType) => mimeType.startsWith("image/"); bool isImage(String mimeType) => mimeType.startsWith("image/");

View File

@ -3,11 +3,10 @@ import 'dart:io';
import 'package:comunic/models/api_request.dart'; import 'package:comunic/models/api_request.dart';
import 'package:comunic/utils/log_utils.dart'; import 'package:comunic/utils/log_utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
import 'package:random_string/random_string.dart';
import 'package:video_thumbnail/video_thumbnail.dart'; import 'package:video_thumbnail/video_thumbnail.dart';
import 'files_utils.dart';
/// Video utilities /// Video utilities
/// ///
/// @author Pierre Hubert /// @author Pierre Hubert
@ -20,9 +19,7 @@ Future<BytesFile> generateVideoThumbnail({
File file; File file;
try { try {
final tempDir = await getTemporaryDirectory(); file = await generateTemporaryFile();
if (tempDir == null) return null;
file = File(path.join(tempDir.path, randomString(15, from: 65, to: 90)));
await file.writeAsBytes(videoFile.bytes); await file.writeAsBytes(videoFile.bytes);

View File

@ -282,6 +282,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.19" version: "2.1.19"
image_cropper:
dependency: "direct main"
description:
name: image_cropper
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.0"
image_picker: image_picker:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -123,6 +123,9 @@ dependencies:
# Color picker # Color picker
flutter_colorpicker: ^0.3.5 flutter_colorpicker: ^0.3.5
# Image cropper
image_cropper: ^1.4.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter