Encrypted peer-to-peer IM for data security. Own data, own privacy. (Rust+Flutter)
 
 
 
 
 
 

135 lines
4.5 KiB

import 'dart:io' show File;
import 'dart:ui' show ImageByteFormat, ImageFilter;
import 'package:crop/crop.dart';
import 'package:flutter/material.dart';
import 'package:esse/l10n/localizations.dart';
import 'package:esse/utils/pick_image.dart';
class _CropAvatar extends StatefulWidget {
final Function callback;
final File image;
_CropAvatar({Key? key, required this.callback, required this.image}) : super(key: key);
@override
_CropAvatarState createState() => _CropAvatarState();
}
class _CropAvatarState extends State<_CropAvatar> {
CropController _imageController = CropController(aspectRatio: 1.0);
double _imageScale = 1.0;
@override
Widget build(BuildContext context) {
final color = Theme.of(context).colorScheme;
final lang = AppLocalizations.of(context);
return AlertDialog(
content: Container(
height: 180.0,
//width: 200.0,
padding: EdgeInsets.only(top: 20.0),
child: Column(children: [
Container(
height: 120.0,
width: 120.0,
child: Crop(
controller: _imageController,
shape: BoxShape.rectangle,
helper: Container(
decoration: BoxDecoration(
//borderRadius: BorderRadius.circular(15.0),
border: Border.all(color: color.primary, width: 2),
),
child: Icon(Icons.filter_center_focus_rounded,
color: color.primary),
),
child: Image(
image: FileImage(widget.image), fit: BoxFit.cover)),
),
const SizedBox(height: 8.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: [
GestureDetector(
child: Icon(Icons.zoom_in_rounded,
size: 30.0, color: color.primary),
onTap: () => setState(() {
_imageScale += 0.5;
_imageController.scale = _imageScale;
}),
),
GestureDetector(
child: Icon(Icons.zoom_out_rounded,
size: 30.0, color: color.primary),
onTap: () => setState(() {
if (_imageScale > 1.0) {
_imageScale -= 0.5;
_imageController.scale = _imageScale;
}
}),
),
])
])),
actions: [
Container(
margin: const EdgeInsets.only(right: 40.0, bottom: 20.0),
child: GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Text(lang.cancel))),
Container(
margin: const EdgeInsets.only(right: 20.0, bottom: 20.0),
child: GestureDetector(
onTap: () async {
final pixelRatio = MediaQuery.of(context).devicePixelRatio;
final cropped = await _imageController.crop(pixelRatio: pixelRatio);
final byteData = await cropped?.toByteData(format: ImageByteFormat.png);
Navigator.of(context).pop();
widget.callback(byteData!.buffer.asUint8List());
},
child: Text(lang.ok,
style: TextStyle(color: color.primary)))),
]);
}
}
Widget _buildMaterialDialogTransitions(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 4 * animation.value, sigmaY: 4 * animation.value),
child: ScaleTransition(
scale: CurvedAnimation(
parent: animation,
curve: Curves.easeOut,
),
child: child,
));
}
void selectAvatar(BuildContext context, Function callback) async {
final imagePath = await pickImage();
if (imagePath == null) {
return;
}
final image = File(imagePath);
showGeneralDialog(
context: context,
barrierDismissible: true,
barrierLabel:
MaterialLocalizations.of(context).modalBarrierDismissLabel,
barrierColor: Color(0x26ADB0BB),
transitionDuration: const Duration(milliseconds: 150),
transitionBuilder: _buildMaterialDialogTransitions,
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return _CropAvatar(callback: callback, image: image);
});
}