Merge pull request 'feature/edit-image' (#29) from feature/edit-image into main
Reviewed-on: #29
This commit is contained in:
commit
8d8c30f506
@ -63,8 +63,6 @@ class CameraState extends State<Camera> {
|
|||||||
_initializeControllerFuture = _controller.initialize();
|
_initializeControllerFuture = _controller.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getCamera() async {}
|
|
||||||
|
|
||||||
Future<void> pickImage() async {
|
Future<void> pickImage() async {
|
||||||
final imagePicker = ImagePicker();
|
final imagePicker = ImagePicker();
|
||||||
final pickedFile = await imagePicker.pickImage(source: ImageSource.gallery);
|
final pickedFile = await imagePicker.pickImage(source: ImageSource.gallery);
|
||||||
|
154
covas_mobile/lib/pages/CameraEdit.dart
Normal file
154
covas_mobile/lib/pages/CameraEdit.dart
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import '../classes/events.dart';
|
||||||
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'EditEvent.dart';
|
||||||
|
import 'package:camera/camera.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
Future<void> main() async {
|
||||||
|
// Ensure that plugin services are initialized so that `availableCameras()`
|
||||||
|
// can be called before `runApp()`
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
// Obtain a list of the available cameras on the device.
|
||||||
|
final cameras = await availableCameras();
|
||||||
|
|
||||||
|
// Get a specific camera from the list of available cameras.
|
||||||
|
final firstCamera = cameras.first;
|
||||||
|
Events? events;
|
||||||
|
|
||||||
|
runApp(
|
||||||
|
MaterialApp(
|
||||||
|
theme: ThemeData.dark(),
|
||||||
|
home: CameraEdit(
|
||||||
|
// Pass the appropriate camera to the TakePictureScreen widget.
|
||||||
|
camera: firstCamera,
|
||||||
|
events: events),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A screen that allows users to take a picture using a given camera.
|
||||||
|
class CameraEdit extends StatefulWidget {
|
||||||
|
const CameraEdit({super.key, required this.camera, required this.events});
|
||||||
|
final Events? events;
|
||||||
|
|
||||||
|
final CameraDescription camera;
|
||||||
|
|
||||||
|
@override
|
||||||
|
CameraEditState createState() => CameraEditState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class CameraEditState extends State<CameraEdit> {
|
||||||
|
late CameraController _controller;
|
||||||
|
late Future<void> _initializeControllerFuture;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
// To display the current output from the Camera,
|
||||||
|
// create a CameraController.
|
||||||
|
|
||||||
|
_controller = CameraController(
|
||||||
|
// Get a specific camera from the list of available cameras.
|
||||||
|
widget.camera,
|
||||||
|
// Define the resolution to use.
|
||||||
|
ResolutionPreset.medium,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Next, initialize the controller. This returns a Future.
|
||||||
|
_initializeControllerFuture = _controller.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> pickImage() async {
|
||||||
|
final imagePicker = ImagePicker();
|
||||||
|
final pickedFile = await imagePicker.pickImage(source: ImageSource.gallery);
|
||||||
|
if (pickedFile != null) {
|
||||||
|
await Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => EditEvent(
|
||||||
|
// Pass the automatically generated path to
|
||||||
|
// the DisplayPictureScreen widget.
|
||||||
|
events: widget.events,
|
||||||
|
imgPath: pickedFile.path,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
// Dispose of the controller when the widget is disposed.
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(title: const Text('Take a picture')),
|
||||||
|
// You must wait until the controller is initialized before displaying the
|
||||||
|
// camera preview. Use a FutureBuilder to display a loading spinner until the
|
||||||
|
// controller has finished initializing.
|
||||||
|
body: FutureBuilder<void>(
|
||||||
|
future: _initializeControllerFuture,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
|
// If the Future is complete, display the preview.
|
||||||
|
return CameraPreview(_controller);
|
||||||
|
} else {
|
||||||
|
// Otherwise, display a loading indicator.
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
floatingActionButton: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
FloatingActionButton(
|
||||||
|
onPressed: pickImage,
|
||||||
|
child: Icon(Icons.photo_library),
|
||||||
|
),
|
||||||
|
SizedBox(width: 40),
|
||||||
|
FloatingActionButton(
|
||||||
|
// Provide an onPressed callback.
|
||||||
|
onPressed: () async {
|
||||||
|
// Take the Picture in a try / catch block. If anything goes wrong,
|
||||||
|
// catch the error.
|
||||||
|
try {
|
||||||
|
// Ensure that the camera is initialized.
|
||||||
|
await _initializeControllerFuture;
|
||||||
|
|
||||||
|
// Attempt to take a picture and get the file `image`
|
||||||
|
// where it was saved.
|
||||||
|
final image = await _controller.takePicture();
|
||||||
|
|
||||||
|
if (!context.mounted) return;
|
||||||
|
|
||||||
|
// If the picture was taken, display it on a new screen.
|
||||||
|
await Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => EditEvent(
|
||||||
|
// Pass the automatically generated path to
|
||||||
|
// the DisplayPictureScreen widget.
|
||||||
|
events: widget.events,
|
||||||
|
imgPath: image.path,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
// If an error occurs, log the error to the console.
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.camera_alt),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:covas_mobile/pages/CameraEdit.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
@ -7,9 +8,14 @@ import 'package:textfield_tags/textfield_tags.dart';
|
|||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'dart:typed_data';
|
||||||
import '../classes/events.dart';
|
import '../classes/events.dart';
|
||||||
|
|
||||||
import 'ItemMenu.dart';
|
import 'ItemMenu.dart';
|
||||||
|
import 'CameraEdit.dart';
|
||||||
|
import 'package:camera/camera.dart';
|
||||||
|
|
||||||
import '../classes/alert.dart';
|
import '../classes/alert.dart';
|
||||||
import '../classes/eventAdded.dart';
|
import '../classes/eventAdded.dart';
|
||||||
|
|
||||||
@ -26,15 +32,21 @@ class MyApp extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
home: EditEvent(events: events),
|
home: EditEvent(
|
||||||
|
events: events,
|
||||||
|
imgPath: "",
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EditEvent extends StatefulWidget {
|
class EditEvent extends StatefulWidget {
|
||||||
const EditEvent({Key? key, required this.events}) : super(key: key);
|
const EditEvent({Key? key, required this.events, required this.imgPath})
|
||||||
|
: super(key: key);
|
||||||
final Events? events;
|
final Events? events;
|
||||||
|
|
||||||
|
final String imgPath;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_EditEventState createState() => _EditEventState();
|
_EditEventState createState() => _EditEventState();
|
||||||
}
|
}
|
||||||
@ -196,12 +208,41 @@ class _EditEventState extends State<EditEvent>
|
|||||||
if (responseGet.statusCode == 200) {
|
if (responseGet.statusCode == 200) {
|
||||||
var events = jsonDecode(utf8.decode(responseGet.bodyBytes));
|
var events = jsonDecode(utf8.decode(responseGet.bodyBytes));
|
||||||
if (events.length > 0) {
|
if (events.length > 0) {
|
||||||
showErrorDialog(context, "Evenement deja existant");
|
if (events[0]["id"] != widget.events!.id) {
|
||||||
|
showErrorDialog(context, "Evenement deja existant");
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (widget.imgPath.isNotEmpty) {
|
||||||
|
final params = {
|
||||||
|
'expiration': '15552000',
|
||||||
|
'key': dotenv.env["IMGBB_API_KEY"],
|
||||||
|
};
|
||||||
|
print("Post Img");
|
||||||
|
final urlPost = Uri.parse('https://api.imgbb.com/1/upload')
|
||||||
|
.replace(queryParameters: params);
|
||||||
|
File image = File(widget.imgPath);
|
||||||
|
Uint8List _bytes = await image.readAsBytes();
|
||||||
|
String _base64String = base64.encode(_bytes);
|
||||||
|
|
||||||
|
final req = http.MultipartRequest('POST', urlPost)
|
||||||
|
..fields['image'] = _base64String;
|
||||||
|
|
||||||
|
final stream = await req.send();
|
||||||
|
final res = await http.Response.fromStream(stream);
|
||||||
|
|
||||||
|
final status = res.statusCode;
|
||||||
|
print("code status imgbb ${status}");
|
||||||
|
if (status != 200) {
|
||||||
|
showErrorDialog(context, "Image non posté");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var body = json.decode(utf8.decode(res.bodyBytes));
|
||||||
|
imgUrl = body["data"]["url"];
|
||||||
|
}
|
||||||
var urlPut =
|
var urlPut =
|
||||||
Uri.parse("${globals.api}/events/${widget.events!.id}");
|
Uri.parse("${globals.api}/events/${widget.events!.id}");
|
||||||
var responsePut = await http.put(urlPut,
|
var responsePut = await http.put(urlPut,
|
||||||
@ -411,6 +452,14 @@ class _EditEventState extends State<EditEvent>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> popCamera() async {
|
||||||
|
await availableCameras().then((value) => Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (_) =>
|
||||||
|
CameraEdit(camera: value.first, events: widget.events))));
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -425,30 +474,57 @@ class _EditEventState extends State<EditEvent>
|
|||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Padding(
|
if (widget.imgPath.isNotEmpty)
|
||||||
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 60.0),
|
padding: const EdgeInsets.only(top: 60.0),
|
||||||
child: Image.network(
|
child: Center(
|
||||||
imgUrl,
|
child: Container(
|
||||||
width: MediaQuery.of(context).size.width *
|
width: 200,
|
||||||
0.5, // 50% of screen width
|
height: 150,
|
||||||
height: MediaQuery.of(context).size.height * 0.5,
|
decoration: BoxDecoration(
|
||||||
loadingBuilder: (BuildContext context, Widget child,
|
borderRadius: BorderRadius.circular(100.0)),
|
||||||
ImageChunkEvent? loadingProgress) {
|
child: Image.file(File(widget.imgPath))),
|
||||||
if (loadingProgress == null) {
|
),
|
||||||
return child; // The image has finished loading
|
),
|
||||||
}
|
if (widget.imgPath.isEmpty)
|
||||||
return Center(
|
Padding(
|
||||||
child: CircularProgressIndicator(),
|
padding: const EdgeInsets.only(top: 60.0),
|
||||||
);
|
child: Image.network(
|
||||||
},
|
imgUrl,
|
||||||
errorBuilder: (BuildContext context, Object error,
|
width: MediaQuery.of(context).size.width *
|
||||||
StackTrace? stackTrace) {
|
0.5, // 50% of screen width
|
||||||
return Center(
|
height: MediaQuery.of(context).size.height * 0.5,
|
||||||
child: Icon(Icons.error,
|
loadingBuilder: (BuildContext context, Widget child,
|
||||||
size: MediaQuery.of(context).size.width * 0.1),
|
ImageChunkEvent? loadingProgress) {
|
||||||
);
|
if (loadingProgress == null) {
|
||||||
},
|
return child; // The image has finished loading
|
||||||
)),
|
}
|
||||||
|
return Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
errorBuilder: (BuildContext context, Object error,
|
||||||
|
StackTrace? stackTrace) {
|
||||||
|
return Center(
|
||||||
|
child: Icon(Icons.error,
|
||||||
|
size: MediaQuery.of(context).size.width * 0.1),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 15),
|
||||||
|
child: ElevatedButton.icon(
|
||||||
|
onPressed: popCamera,
|
||||||
|
icon: Icon(Icons.edit, size: 16), // Edit icon
|
||||||
|
label: Text("Edit Image"), // Button text
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: Colors.blue, // Button color
|
||||||
|
foregroundColor: Colors.white, // Text color
|
||||||
|
padding:
|
||||||
|
EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
Padding(
|
Padding(
|
||||||
//padding: const EdgeInsets.only(left:15.0,right: 15.0,top:0,bottom: 0),
|
//padding: const EdgeInsets.only(left:15.0,right: 15.0,top:0,bottom: 0),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 15),
|
padding: EdgeInsets.symmetric(horizontal: 15),
|
||||||
|
@ -408,7 +408,11 @@ class _ItemMenuState extends State<ItemMenu> with ShowErrorDialog {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (_) => EditEvent(events: events)),
|
MaterialPageRoute(
|
||||||
|
builder: (_) => EditEvent(
|
||||||
|
events: events,
|
||||||
|
imgPath: "",
|
||||||
|
)),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
backgroundColor: Colors.blue,
|
backgroundColor: Colors.blue,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user