mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-04 04:04:18 +00:00 
			
		
		
		
	Can crop image
This commit is contained in:
		@@ -14,6 +14,7 @@
 | 
			
		||||
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
 | 
			
		||||
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
 | 
			
		||||
 | 
			
		||||
   <!-- This is required on Android 11+ for image picker -->
 | 
			
		||||
    <queries>
 | 
			
		||||
        <intent>
 | 
			
		||||
            <action android:name="android.media.action.IMAGE_CAPTURE" />
 | 
			
		||||
@@ -69,5 +70,11 @@
 | 
			
		||||
                <category android:name="android.intent.category.LAUNCHER"/>
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
        </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>
 | 
			
		||||
</manifest>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
import 'package:comunic/models/api_request.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/intl_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 = await showImageCropper(context, file);
 | 
			
		||||
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Pick an video
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										53
									
								
								lib/ui/routes/image_editor_route.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								lib/ui/routes/image_editor_route.dart
									
									
									
									
									
										Normal 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();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,11 @@
 | 
			
		||||
import 'dart:io';
 | 
			
		||||
 | 
			
		||||
import 'package:comunic/utils/intl_utils.dart';
 | 
			
		||||
import 'package:flutter/material.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
 | 
			
		||||
///
 | 
			
		||||
@@ -46,6 +51,16 @@ Future<PickedFile> pickImage(BuildContext context) async {
 | 
			
		||||
          : 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
 | 
			
		||||
bool isImage(String mimeType) => mimeType.startsWith("image/");
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,11 +3,10 @@ import 'dart:io';
 | 
			
		||||
import 'package:comunic/models/api_request.dart';
 | 
			
		||||
import 'package:comunic/utils/log_utils.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 'files_utils.dart';
 | 
			
		||||
 | 
			
		||||
/// Video utilities
 | 
			
		||||
///
 | 
			
		||||
/// @author Pierre Hubert
 | 
			
		||||
@@ -20,9 +19,7 @@ Future<BytesFile> generateVideoThumbnail({
 | 
			
		||||
  File file;
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    final tempDir = await getTemporaryDirectory();
 | 
			
		||||
    if (tempDir == null) return null;
 | 
			
		||||
    file = File(path.join(tempDir.path, randomString(15, from: 65, to: 90)));
 | 
			
		||||
    file = await generateTemporaryFile();
 | 
			
		||||
 | 
			
		||||
    await file.writeAsBytes(videoFile.bytes);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -282,6 +282,13 @@ packages:
 | 
			
		||||
      url: "https://pub.dartlang.org"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    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:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
 
 | 
			
		||||
@@ -123,6 +123,9 @@ dependencies:
 | 
			
		||||
  # Color picker
 | 
			
		||||
  flutter_colorpicker: ^0.3.5
 | 
			
		||||
 | 
			
		||||
  # Image cropper
 | 
			
		||||
  image_cropper: ^1.4.0
 | 
			
		||||
 | 
			
		||||
dev_dependencies:
 | 
			
		||||
  flutter_test:
 | 
			
		||||
    sdk: flutter
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user