Merge pull request 'feature/update-event' (#7) from feature/update-event into main

Reviewed-on: #7
This commit is contained in:
v4l3n71n 2024-09-04 23:08:25 +02:00
commit 4f12fdf8b3
9 changed files with 623 additions and 82 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1,34 @@
import 'package:flutter/material.dart';
import '../pages/ListItemMenu.dart';
mixin ShowEventDialog<T extends StatefulWidget> on State<T> {
void showEventDialog(BuildContext context, String text) {
// Create AlertDialog
AlertDialog dialog = AlertDialog(
title: Text("Evenement ajoute"),
content: Text(text),
actions: [
ElevatedButton(
child: Text("OK"),
style: ElevatedButton.styleFrom(
padding: EdgeInsets.symmetric(horizontal: 50, vertical: 20),
textStyle:
TextStyle(fontSize: 15, fontWeight: FontWeight.normal)),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => ListItemMenu())); // Return value
}),
],
);
// Call showDialog function to show dialog.
Future futureValue = showDialog(
context: context,
builder: (BuildContext context) {
return dialog;
});
}
}

View File

@ -0,0 +1,67 @@
import 'package:flutter/material.dart';
import 'events.dart';
import '../variable/globals.dart' as globals;
import 'package:http/http.dart' as http;
import 'dart:io';
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
mixin ShowDescImageGet<T extends StatefulWidget> on State<T> {
Future<void> getEvents(var events) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var accessToken = prefs.getString("access_token") ?? "";
List<String> send = ["toto"];
if (accessToken.isNotEmpty) {
var urlPut = Uri.parse("${globals.api}/events");
print("start date : ${events["start_date"]}");
var responsePut = await http.put(urlPut,
headers: {
HttpHeaders.cookieHeader: 'access_token=${accessToken}',
HttpHeaders.acceptHeader: 'application/json, text/plain, */*',
HttpHeaders.contentTypeHeader: 'application/json'
},
body: jsonEncode({
'name': events["name"],
'place': events["place"],
'start_date': events['date'],
'end_date': events['date'],
'organizers': send,
'latitude': '0.0',
'longitude': '0.0',
}));
print("http put code status : ${responsePut.statusCode}");
print("http put body : ${responsePut.body}");
}
}
void showDescImageGetDialog(BuildContext context, var events) {
// Create AlertDialog
String name = events['name'];
AlertDialog dialog = AlertDialog(
title: Text("Voir la description de l'evenement"),
content: Text("${name} a été trouvé. Voulez-vous voir sa description ? "),
actions: [
TextButton(
child: Text("Annuler"),
onPressed: () {
Navigator.of(context).pop("Yes, Of course!"); // Return value
}),
TextButton(
child: Text("Oui"),
onPressed: () {
getEvents(events); // Return value
}),
],
);
// Call showDialog function to show dialog.
Future futureValue = showDialog(
context: context,
builder: (BuildContext context) {
return dialog;
});
}
}

View File

@ -1,11 +1,13 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'dart:io'; import 'dart:io';
import '../classes/descriptionImage.dart'; import '../classes/addEventImage.dart';
import '../classes/alert.dart'; import '../classes/alert.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_gemini/flutter_gemini.dart'; import 'package:flutter_gemini/flutter_gemini.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;
import "ItemMenu.dart";
import 'UpdateEventImage.dart';
import 'dart:convert'; import 'dart:convert';
@ -52,21 +54,37 @@ class DisplayPictureScreen extends StatefulWidget {
// A widget that displays the picture taken by the user. // A widget that displays the picture taken by the user.
class DisplayPictureScreenState extends State<DisplayPictureScreen> class DisplayPictureScreenState extends State<DisplayPictureScreen>
with ShowDescImageAdd, ShowErrorDialog { with ShowDescImageAdd, ShowErrorDialog, TickerProviderStateMixin {
late AnimationController controller;
@override @override
void initState() { void initState() {
controller = AnimationController(
/// [AnimationController]s can be created with `vsync: this` because of
/// [TickerProviderStateMixin].
vsync: this,
duration: const Duration(seconds: 5),
)..addListener(() {
setState(() {});
});
controller.repeat(reverse: false);
super.initState(); super.initState();
_getEventInfosFromImage(); _getEventInfosFromImage();
} }
@override
void dispose() {
controller.dispose();
super.dispose();
}
Future<void> displayError(String e) async { Future<void> displayError(String e) async {
print("problem gemini : ${e}"); print("problem gemini : ${e}");
showErrorDialog(context, showErrorDialog(context,
"L'IA de Google n'a pas su analyser l'image. Recommecer avec une autre"); "L'IA de Google n'a pas su analyser l'image. Recommecer avec une autre");
} }
Future<void> searchEvents(String json) async { Future<void> searchEvents(String json, String imagePath) async {
print(json); print(json);
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
@ -84,7 +102,16 @@ class DisplayPictureScreenState extends State<DisplayPictureScreen>
var events = jsonDecode(utf8.decode(responseGet.bodyBytes)); var events = jsonDecode(utf8.decode(responseGet.bodyBytes));
print("reponse http : ${events.length}"); print("reponse http : ${events.length}");
if (events.length == 0) { if (events.length == 0) {
showDescImageAddDialog(context, jsonData); Navigator.push(
context,
MaterialPageRoute(
builder: (_) => UpdateeventImage(
events: jsonData, imagePath: imagePath)));
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => ItemMenu(title: events[0]["id"])));
} }
} }
} else { } else {
@ -105,10 +132,11 @@ class DisplayPictureScreenState extends State<DisplayPictureScreen>
gemini gemini
.textAndImage( .textAndImage(
text: text:
"Peux-tu donner le nom, la date et le lieu de l'évènement sous format JSON avec les valeurs suivantes : name, place et date avec le format suivant YYYY-MM-ddTTHH:mm, et sans la présence de json dans la chaîne de caractère", "Peux-tu donner le nom, la date avec l'année actuelle ou d'une année future proche et le lieu de l'évènement sous format JSON avec les valeurs suivantes : name, address, city, zip_code, country, description, start_date et end_date sous le format en YYYY-MM-DD HH:mm:ssZ, et sans la présence du mot json dans la chaîne de caractère",
images: [file.readAsBytesSync()], images: [file.readAsBytesSync()],
modelName: "models/gemini-1.5-flash-latest") modelName: "models/gemini-1.5-pro-latest")
.then((value) => searchEvents(value?.content?.parts?.last.text ?? '')) .then((value) => searchEvents(
value?.content?.parts?.last.text ?? '', widget.imagePath))
.catchError((e) => displayError); .catchError((e) => displayError);
} }
@ -118,10 +146,19 @@ class DisplayPictureScreenState extends State<DisplayPictureScreen>
appBar: AppBar(title: const Text('Display the Picture')), appBar: AppBar(title: const Text('Display the Picture')),
// The image is stored as a file on the device. Use the `Image.file` // The image is stored as a file on the device. Use the `Image.file`
// constructor with the given path to display the image. // constructor with the given path to display the image.
body: SingleChildScrollView( body: Padding(
child: Column(children: <Widget>[ padding: const EdgeInsets.all(20.0),
Image.file(File(widget.imagePath)), child: Column(
Text("Analyse en cours...") mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(
'Analyse de l\'image en cours',
style: Theme.of(context).textTheme.titleLarge,
),
CircularProgressIndicator(
value: controller.value,
semanticsLabel: 'Loading progress',
),
]))); ])));
} }
} }

View File

@ -14,6 +14,8 @@ import '../variable/globals.dart' as globals;
import '../classes/events.dart'; import '../classes/events.dart';
import 'ListItemMenu.dart';
void main() { void main() {
initializeDateFormatting("fr_FR", null).then((_) => (const MyApp())); initializeDateFormatting("fr_FR", null).then((_) => (const MyApp()));
} }
@ -186,7 +188,13 @@ class _ItemMenuState extends State<ItemMenu> with ShowErrorDialog {
title: Text("${eventName}"), title: Text("${eventName}"),
backgroundColor: Colors.blue, backgroundColor: Colors.blue,
foregroundColor: Colors.white, foregroundColor: Colors.white,
), leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (_) => ListItemMenu()));
},
)),
body: SingleChildScrollView( body: SingleChildScrollView(
child: Column( child: Column(
children: <Widget>[ children: <Widget>[

View File

@ -0,0 +1,393 @@
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import 'dart:convert';
import 'dart:io';
import '../classes/alert.dart';
import '../classes/eventAdded.dart';
import '../variable/globals.dart' as globals;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
Map<String, dynamic> events = {};
String imagePath = "";
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: UpdateeventImage(events: events, imagePath: imagePath),
);
}
}
class UpdateeventImage extends StatefulWidget {
const UpdateeventImage(
{Key? key, required this.events, required this.imagePath})
: super(key: key);
final Map<String, dynamic> events;
final String imagePath;
@override
_UpdateeventImageState createState() => _UpdateeventImageState();
}
class _UpdateeventImageState extends State<UpdateeventImage>
with ShowErrorDialog, ShowEventDialog {
TextEditingController inputName = TextEditingController();
TextEditingController inputAddress = TextEditingController();
TextEditingController inputZipCode = TextEditingController();
TextEditingController inputCity = TextEditingController();
TextEditingController inputCountry = TextEditingController();
TextEditingController inputDate = TextEditingController();
TextEditingController inputDesc = TextEditingController();
TextEditingController startDatepicker = TextEditingController();
TextEditingController startTimepicker = TextEditingController();
TextEditingController endDatepicker = TextEditingController();
TextEditingController endTimepicker = TextEditingController();
onTapFunctionDatePicker(
{required BuildContext context, required String position}) async {
DateTime? pickedDate = await showDatePicker(
context: context,
firstDate: DateTime.parse(widget.events["date"]),
initialDate: DateTime.parse(widget.events["date"]),
lastDate: DateTime(2104));
if (pickedDate == null) return;
if (position == "start") {
startDatepicker.text = DateFormat("dd-MM-yyyy").format(pickedDate);
}
if (position == "end") {
endDatepicker.text = DateFormat("dd-MM-yyyy").format(pickedDate);
}
}
onTapFunctionTimePicker(
{required BuildContext context, required String position}) async {
TimeOfDay? pickedDate = await showTimePicker(
context: context,
initialTime:
TimeOfDay.fromDateTime(DateTime.parse(widget.events["date"])));
if (pickedDate == null) return;
if (position == "start") {
startTimepicker.text = pickedDate.format(context);
}
if (position == "end") {
endTimepicker.text = pickedDate.format(context);
}
}
String formatDate(String date) {
var splitedDate = date.split("-");
var day = splitedDate[0];
var month = splitedDate[1];
var year = splitedDate[2];
return "${year}-${month}-${day}";
}
Future<void> _updateEvent(BuildContext context) async {
var url = Uri.parse("${globals.api}/token");
var name = inputName.text;
var place = inputAddress.text;
var city = inputCity.text;
var country = inputCountry.text;
var zipCode = inputZipCode.text;
var description = inputDesc.text;
var startDateFormat = formatDate(startDatepicker.text);
var endDateFormat = formatDate(endDatepicker.text);
var startDate =
"${startDateFormat}T${startTimepicker.text.replaceAll('-', ':')}";
var endDate = "${endDateFormat}T${endTimepicker.text.replaceAll('-', ':')}";
print("start date : ${startDate}");
print("end date : ${endDate}");
SharedPreferences prefs = await SharedPreferences.getInstance();
var accessToken = prefs.getString("access_token") ?? "";
List<String> send = ["toto"];
if (accessToken.isNotEmpty) {
try {
//String credentials = "${pseudo}:${password}";
//Codec<String, String> stringToBase64 = utf8.fuse(base64);
//String encoded = stringToBase64.encode(credentials);
var urlPut = Uri.parse("${globals.api}/events");
var responsePut = await http.put(urlPut,
headers: {
HttpHeaders.cookieHeader: 'access_token=${accessToken}',
HttpHeaders.acceptHeader: 'application/json, text/plain, */*',
HttpHeaders.contentTypeHeader: 'application/json'
},
body: jsonEncode({
'name': name,
'place': place,
'start_date': startDate,
'end_date': endDate,
'zip_code': zipCode,
'country': country,
'city': city,
'organizers': send,
'latitude': '0.0',
'longitude': '0.0',
'description': description
}));
print(responsePut.statusCode);
if ((responsePut.statusCode == 200) ||
(responsePut.statusCode == 201)) {
showEventDialog(context, "Evenement ${name} ajoute");
} else {
var text = "";
switch (responsePut.statusCode) {
case 400:
{
text = "Requête mal construite";
}
break;
case 406:
{
text = "Mot de passe incorrect";
}
break;
case 404:
{
text = "Utilisateur inconnu";
}
break;
case 403:
{
text = "Utilisateur desactive";
}
break;
case 410:
{
text = "Token invalide";
}
break;
case 500:
{
text = "Probleme interne du serveur";
}
break;
default:
{
text = "Probleme d'authentification inconnu";
}
break;
}
showErrorDialog(context, text);
}
} catch (e) {
showErrorDialog(context, "${e}");
}
} else {
showErrorDialog(context, "Champ vide");
}
}
void start() async {
inputName.text = widget.events["name"];
inputCity.text = widget.events["city"];
inputAddress.text = widget.events["address"];
inputZipCode.text = widget.events["zip_code"];
inputCountry.text = widget.events["country"];
inputDesc.text = widget.events["description"];
DateTime pickedStartDate = DateTime.parse(widget.events["start_date"]);
DateTime pickedEndDate = DateTime.parse(widget.events["end_date"]);
startDatepicker.text = DateFormat("dd-MM-yyyy").format(pickedStartDate);
endDatepicker.text = DateFormat("dd-MM-yyyy").format(pickedEndDate);
startTimepicker.text = DateFormat("HH-mm").format(pickedStartDate);
endTimepicker.text = DateFormat("HH-mm").format(pickedEndDate);
}
@override
void initState() {
start();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text("Add or Update a event"),
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 60.0),
child: Center(
child: Container(
width: 200,
height: 150,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100.0)),
child: Image.file(File(widget.imagePath))),
),
),
Padding(
//padding: const EdgeInsets.only(left:15.0,right: 15.0,top:0,bottom: 0),
padding: EdgeInsets.symmetric(horizontal: 15),
child: TextField(
controller: inputName,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Nom',
hintText: 'Modifier le nom de l\'évènement'),
),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
//padding: EdgeInsets.symmetric(horizontal: 15),
child: TextField(
controller: inputAddress,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Adresse',
hintText: 'Entrer une adresse'),
),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
//padding: EdgeInsets.symmetric(horizontal: 15),
child: TextField(
controller: inputZipCode,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Code postal',
hintText: 'Entrer un code postal'),
),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
//padding: EdgeInsets.symmetric(horizontal: 15),
child: TextField(
controller: inputCity,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Ville',
hintText: 'Entrer une ville'),
),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
//padding: EdgeInsets.symmetric(horizontal: 15),
child: TextField(
controller: inputCountry,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Pays',
hintText: 'Entrer un pays'),
),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
//padding: EdgeInsets.symmetric(horizontal: 15),
child: TextField(
controller: startDatepicker,
readOnly: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Date de debut de l\'évènement',
hintText: 'Cliquez ici pour selectionner une date'),
onTap: () => onTapFunctionDatePicker(
context: context, position: "start")),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
//padding: EdgeInsets.symmetric(horizontal: 15),
child: TextField(
controller: startTimepicker,
readOnly: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Heure de debut de l\'évènement',
hintText: 'Cliquez ici pour selectionner une heure'),
onTap: () => onTapFunctionTimePicker(
context: context, position: "start")),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
//padding: EdgeInsets.symmetric(horizontal: 15),
child: TextField(
controller: endDatepicker,
readOnly: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Date de fin de l\'évènement',
hintText: 'Cliquez ici pour selectionner une date'),
onTap: () => onTapFunctionDatePicker(
context: context, position: "end")),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
//padding: EdgeInsets.symmetric(horizontal: 15),
child: TextField(
controller: endTimepicker,
readOnly: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Heure de fin de l\'évènement',
hintText: 'Cliquez ici pour selectionner une heure'),
onTap: () => onTapFunctionTimePicker(
context: context, position: "end")),
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 15, bottom: 0),
//padding: EdgeInsets.symmetric(horizontal: 15),
child: TextField(
controller: inputDesc,
keyboardType: TextInputType.multiline,
maxLines: 10,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Description',
hintText: 'Décrire l\'evènement'),
),
),
SizedBox(
height: 30,
),
Container(
height: 50,
width: 250,
decoration: BoxDecoration(
color: Colors.blue, borderRadius: BorderRadius.circular(20)),
child: TextButton(
onPressed: () {
_updateEvent(context);
},
child: Text(
'Ajouter',
style: TextStyle(color: Colors.white, fontSize: 25),
),
),
)
],
),
),
);
}
}

View File

@ -21,26 +21,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: camera name: camera
sha256: "2170a943dcb67be2af2c6bcda8775e74b41d4c02d6a4eb10bdc832ee185c4eea" sha256: "26ff41045772153f222ffffecba711a206f670f5834d40ebf5eed3811692f167"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.11.0+1" version: "0.11.0+2"
camera_android_camerax: camera_android_camerax:
dependency: transitive dependency: transitive
description: description:
name: camera_android_camerax name: camera_android_camerax
sha256: "7c03940cb8c92eb5b184952674a07cc4a73c6ba2b3568aad70255ad4cb913660" sha256: "8bd9cab67551642eb33ceb33ece7acc0890014fc90ddfae637c7e2b683657e65"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.6.7+1" version: "0.6.7+2"
camera_avfoundation: camera_avfoundation:
dependency: transitive dependency: transitive
description: description:
name: camera_avfoundation name: camera_avfoundation
sha256: b5093a82537b64bb88d4244f8e00b5ba69e822a5994f47b31d11400e1db975e5 sha256: "7c28969a975a7eb2349bc2cb2dfe3ad218a33dba9968ecfb181ce08c87486655"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.9.17+1" version: "0.9.17+3"
camera_platform_interface: camera_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -53,10 +53,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: camera_web name: camera_web
sha256: b9235ec0a2ce949daec546f1f3d86f05c3921ed31c7d9ab6b7c03214d152fc2d sha256: "595f28c89d1fb62d77c73c633193755b781c6d2e0ebcd8dc25b763b514e6ba8f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.4" version: "0.3.5"
characters: characters:
dependency: transitive dependency: transitive
description: description:
@ -85,10 +85,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: cross_file name: cross_file
sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32" sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.4+1" version: "0.3.4+2"
cupertino_icons: cupertino_icons:
dependency: "direct main" dependency: "direct main"
description: description:
@ -97,6 +97,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.8" version: "1.0.8"
date_format_field:
dependency: "direct main"
description:
name: date_format_field
sha256: d07a428bd253454ff3123f2e57511cf6ec101d1135af3b79cebb40e1bee8bab8
url: "https://pub.dev"
source: hosted
version: "0.1.0"
dio: dio:
dependency: transitive dependency: transitive
description: description:
@ -165,10 +173,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: file_selector_windows name: file_selector_windows
sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0 sha256: "2ad726953f6e8affbc4df8dc78b77c3b4a060967a291e528ef72ae846c60fb69"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.9.3+1" version: "0.9.3+2"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -186,10 +194,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_gemini name: flutter_gemini
sha256: c6079dc6f95c6191e609e9cc627c268ef0bf2526cbba6a2f61aa41ea0053e9a0 sha256: "993765fafb595e5d32153f393b9c5e71f853caa5bef123d292c21f672d2b9675"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.4" version: "2.0.5"
flutter_lints: flutter_lints:
dependency: "direct dev" dependency: "direct dev"
description: description:
@ -202,10 +210,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: flutter_plugin_android_lifecycle name: flutter_plugin_android_lifecycle
sha256: c6b0b4c05c458e1c01ad9bcc14041dd7b1f6783d487be4386f793f47a8a4d03e sha256: "9d98bd47ef9d34e803d438f17fd32b116d31009f534a6fa5ce3a1167f189a6de"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.20" version: "2.0.21"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -228,10 +236,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: http name: http
sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.1" version: "1.2.2"
http_parser: http_parser:
dependency: transitive dependency: transitive
description: description:
@ -252,18 +260,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: image_picker_android name: image_picker_android
sha256: cea2bd5b9fcff039a4901d3b13c67fe747f940be9ba76bde1bcd218d168eeb7f sha256: c0e72ecd170b00a5590bb71238d57dc8ad22ee14c60c6b0d1a4e05cafbc5db4b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.12+6" version: "0.8.12+11"
image_picker_for_web: image_picker_for_web:
dependency: transitive dependency: transitive
description: description:
name: image_picker_for_web name: image_picker_for_web
sha256: "5d6eb13048cd47b60dbf1a5495424dea226c5faf3950e20bf8120a58efb5b5f3" sha256: "65d94623e15372c5c51bebbcb820848d7bcb323836e12dfdba60b5d3a8b39e50"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.4" version: "3.0.5"
image_picker_ios: image_picker_ios:
dependency: transitive dependency: transitive
description: description:
@ -324,18 +332,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker name: leak_tracker
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.4" version: "10.0.5"
leak_tracker_flutter_testing: leak_tracker_flutter_testing:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker_flutter_testing name: leak_tracker_flutter_testing
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "3.0.5"
leak_tracker_testing: leak_tracker_testing:
dependency: transitive dependency: transitive
description: description:
@ -364,18 +372,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.0" version: "0.11.1"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.12.0" version: "1.15.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
@ -396,18 +404,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: path_provider name: path_provider
sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.3" version: "2.1.4"
path_provider_android: path_provider_android:
dependency: transitive dependency: transitive
description: description:
name: path_provider_android name: path_provider_android
sha256: "30c5aa827a6ae95ce2853cdc5fe3971daaac00f6f081c419c013f7f57bff2f5e" sha256: "490539678396d4c3c0b06efdaab75ae60675c3e0c66f72bc04c2e2c1e0e2abeb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.7" version: "2.2.9"
path_provider_foundation: path_provider_foundation:
dependency: transitive dependency: transitive
description: description:
@ -436,10 +444,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: path_provider_windows name: path_provider_windows
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.1" version: "2.3.0"
platform: platform:
dependency: transitive dependency: transitive
description: description:
@ -460,58 +468,58 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: shared_preferences name: shared_preferences
sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 sha256: c272f9cabca5a81adc9b0894381e9c1def363e980f960fa903c604c471b22f68
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.3" version: "2.3.1"
shared_preferences_android: shared_preferences_android:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577" sha256: a7e8467e9181cef109f601e3f65765685786c1a738a83d7fbbde377589c0d974
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.3" version: "2.3.1"
shared_preferences_foundation: shared_preferences_foundation:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_foundation name: shared_preferences_foundation
sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7" sha256: "776786cff96324851b656777648f36ac772d88bc4c669acff97b7fce5de3c849"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.0" version: "2.5.1"
shared_preferences_linux: shared_preferences_linux:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_linux name: shared_preferences_linux
sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.2" version: "2.4.1"
shared_preferences_platform_interface: shared_preferences_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_platform_interface name: shared_preferences_platform_interface
sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b" sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.2" version: "2.4.1"
shared_preferences_web: shared_preferences_web:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_web name: shared_preferences_web
sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.4.2"
shared_preferences_windows: shared_preferences_windows:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_windows name: shared_preferences_windows
sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.2" version: "2.4.1"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -569,10 +577,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.0" version: "0.7.2"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
@ -593,26 +601,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vm_service name: vm_service
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "14.2.1" version: "14.2.5"
web: web:
dependency: transitive dependency: transitive
description: description:
name: web name: web
sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.1" version: "1.0.0"
win32:
dependency: transitive
description:
name: win32
sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4
url: "https://pub.dev"
source: hosted
version: "5.5.1"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:

View File

@ -44,6 +44,7 @@ dependencies:
flutter_gemini: ^2.0.4 flutter_gemini: ^2.0.4
flutter_dotenv: ^5.1.0 flutter_dotenv: ^5.1.0
image_picker: ^1.1.2 image_picker: ^1.1.2
date_format_field: ^0.1.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
@ -71,6 +72,7 @@ flutter:
assets: assets:
- images/flutter.png - images/flutter.png
- .env - .env
- images/search.png
# - images/a_dot_ham.jpeg # - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see # An image asset can refer to one or more resolution-specific "variants", see