This makes the avatar cropper much more consistent with the background cropper. Fixes #168.
103 lines
2.7 KiB
Dart
103 lines
2.7 KiB
Dart
import 'dart:async';
|
|
import 'dart:io';
|
|
import 'dart:typed_data';
|
|
import 'package:bloc/bloc.dart';
|
|
import 'package:cropperx/cropperx.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
import 'package:get_it/get_it.dart';
|
|
import 'package:moxxyv2/ui/bloc/navigation_bloc.dart';
|
|
import 'package:moxxyv2/ui/constants.dart';
|
|
|
|
part 'crop_bloc.freezed.dart';
|
|
part 'crop_event.dart';
|
|
part 'crop_state.dart';
|
|
|
|
class CropBloc extends Bloc<CropEvent, CropState> {
|
|
CropBloc() : super(CropState()) {
|
|
on<ImageCroppedEvent>(_onImageCropped);
|
|
on<ResetImageEvent>(_onImageReset);
|
|
on<SetImageEvent>(_onImageSet);
|
|
}
|
|
late Completer<Uint8List?> _completer;
|
|
final GlobalKey cropKey = GlobalKey();
|
|
|
|
Future<void> _onImageCropped(ImageCroppedEvent event, Emitter<CropState> emit) async {
|
|
emit(
|
|
state.copyWith(
|
|
isWorking: true,
|
|
),
|
|
);
|
|
|
|
final bytes = await Cropper.crop(
|
|
cropperKey: cropKey,
|
|
);
|
|
_completer.complete(bytes);
|
|
|
|
GetIt.I.get<NavigationBloc>().add(PoppedRouteEvent());
|
|
|
|
await _onImageReset(ResetImageEvent(), emit);
|
|
}
|
|
|
|
Future<void> _onImageReset(ResetImageEvent event, Emitter<CropState> emit) async {
|
|
emit(
|
|
state.copyWith(
|
|
image: null,
|
|
isWorking: false,
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> _onImageSet(SetImageEvent event, Emitter<CropState> emit) async {
|
|
emit(
|
|
state.copyWith(
|
|
image: event.image,
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> _performCropping(String path) async {
|
|
final file = File(path);
|
|
if (!file.existsSync()) _completer.complete(null);
|
|
|
|
final bytes = await file.readAsBytes();
|
|
|
|
add(SetImageEvent(bytes));
|
|
}
|
|
|
|
/// User-callable function. Loads the image, navigates to the page
|
|
/// and allows the user to crop the image. The future resolves when
|
|
/// either an error occures or the image has been cropped.
|
|
/// [path] is the path to the file to load.
|
|
Future<Uint8List?> cropImage(String path) {
|
|
_completer = Completer();
|
|
|
|
add(ResetImageEvent());
|
|
GetIt.I.get<NavigationBloc>().add(
|
|
PushedNamedEvent(
|
|
const NavigationDestination(cropRoute),
|
|
),
|
|
);
|
|
_performCropping(path);
|
|
|
|
return _completer.future;
|
|
}
|
|
|
|
/// User-callable function. Loads the image, navigates to the page
|
|
/// and allows the user to crop the image. The future resolves when
|
|
/// either an error occures or the image has been cropped.
|
|
Future<Uint8List?> cropImageWithData(Uint8List data) {
|
|
_completer = Completer();
|
|
|
|
GetIt.I.get<NavigationBloc>().add(
|
|
PushedNamedEvent(
|
|
const NavigationDestination(cropRoute),
|
|
),
|
|
);
|
|
|
|
add(SetImageEvent(data));
|
|
|
|
return _completer.future;
|
|
}
|
|
}
|