i have a problem that when i close the application from the background, the mobile sends me a notification, but when i click on it, it doesn't take me to a notification screen t
he package
flutter_local_notifications
the database
sqlite
state mangment
get
notification screan
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../theme.dart';
class NotificationScreen extends StatefulWidget {
const NotificationScreen({Key? key, required this.payload}) : super(key: key);
final String payload;
#override
_NotificationScreenState createState() => _NotificationScreenState();
}
class _NotificationScreenState extends State<NotificationScreen> {
String _payload = '';
#override
void initState() {
super.initState();
_payload = widget.payload;
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: context.theme.backgroundColor,
appBar: AppBar(
leading: IconButton(
onPressed: () => Get.back(),
icon: Icon(
Icons.arrow_back_ios,
color: Get.isDarkMode ? Colors.white : darkGreyClr,
),
),
elevation: 0,
backgroundColor: context.theme.backgroundColor,
title: Text(
_payload.toString().split('|')[0],
style: TextStyle(color: Get.isDarkMode ? Colors.white : darkGreyClr),
),
),
body: SafeArea(
child: Column(
children: [
const SizedBox(height: 20),
Column(
children: [
Text(
'اهلا',
style: TextStyle(
fontSize: 26,
fontWeight: FontWeight.w900,
color: Get.isDarkMode ? Colors.white : darkGreyClr,
),
),
const SizedBox(height: 10),
Text(
'لديك تذكير جديد',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w300,
color: Get.isDarkMode ? Colors.grey[100] : darkGreyClr,
),
),
],
),
const SizedBox(height: 10),
Expanded(
child: Container(
padding:
const EdgeInsets.symmetric(horizontal: 30, vertical: 10),
margin: const EdgeInsets.symmetric(horizontal: 30),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: primaryClr,
),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: const [
Icon(
Icons.text_format,
size: 35,
color: Colors.white,
),
SizedBox(width: 20),
Text(
'العنوان',
style: TextStyle(color: Colors.white, fontSize: 30),
),
],
),
const SizedBox(height: 20),
Text(
_payload.toString().split('|')[0],
style:
const TextStyle(color: Colors.white, fontSize: 20),
),
const SizedBox(height: 20),
Row(
children: const [
Icon(
Icons.description,
size: 35,
color: Colors.white,
),
SizedBox(width: 20),
Text(
'الوصف',
style: TextStyle(color: Colors.white, fontSize: 30),
),
],
),
const SizedBox(height: 20),
Text(
_payload.toString().split('|')[1],
style:
const TextStyle(color: Colors.white, fontSize: 20),
textAlign: TextAlign.justify,
),
const SizedBox(height: 20),
Row(
children: const [
Icon(
Icons.calendar_today_outlined,
size: 35,
color: Colors.white,
),
SizedBox(width: 20),
Text(
'التاريخ',
style: TextStyle(color: Colors.white, fontSize: 30),
),
],
),
const SizedBox(height: 20),
Text(
_payload.toString().split('|')[2],
style:
const TextStyle(color: Colors.white, fontSize: 20),
),
],
),
),
),
),
const SizedBox(height: 10),
],
),
),
);
}
}
notification_services
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_native_timezone/flutter_native_timezone.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:rxdart/rxdart.dart';
// ignore: depend_on_referenced_packages
import 'package:timezone/data/latest.dart' as tz;
// ignore: depend_on_referenced_packages
import 'package:timezone/timezone.dart' as tz;
import '/models/task.dart';
import '/ui/pages/notification_screen.dart';
class NotifyHelper {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin(); //
final BehaviorSubject<String> selectNotificationSubject =
BehaviorSubject<String>();
initializeNotification() async {
await _configureLocalTimeZone();
_configureSelectNotificationSubject();
final IOSInitializationSettings initializationSettingsIOS =
// ignore: prefer_const_constructors
IOSInitializationSettings(
requestSoundPermission: false,
requestBadgePermission: false,
requestAlertPermission: false,
onDidReceiveLocalNotification: onDidReceiveLocalNotification);
final AndroidInitializationSettings initializationSettingsAndroid =
// ignore: prefer_const_constructors
AndroidInitializationSettings('#mipmap/ic_launcher');
final InitializationSettings initializationSettings =
InitializationSettings(
iOS: initializationSettingsIOS,
android: initializationSettingsAndroid,
);
await flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onSelectNotification: (String? payload) async {
if (payload != null) {
debugPrint('notification payload: $payload');
}
selectNotificationSubject.add(payload!);
},
);
}
displayNotification({required String title, required String body}) async {
debugPrint('doing test');
var androidPlatformChannelSpecifics = const AndroidNotificationDetails(
'your channel id', 'your channel name',
channelDescription: 'your channel description',
importance: Importance.max,
priority: Priority.high);
var iOSPlatformChannelSpecifics = const IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
5,
title,
body,
platformChannelSpecifics,
payload: 'Default_Sound',
);
}
cancelNotification(Task task) async {
await flutterLocalNotificationsPlugin.cancel(task.id!);
}
cancelAllNotification() async {
await flutterLocalNotificationsPlugin.cancelAll();
}
scheduledNotification(int hour, int minutes, Task task) async {
await flutterLocalNotificationsPlugin.zonedSchedule(
task.id!.toInt(),
task.title,
task.note!,
_convertTime(hour, minutes, task.repeat!, task.date!),
//tz.TZDateTime.now(tz.local).add(const Duration(seconds: 5)),
const NotificationDetails(
android: AndroidNotificationDetails(
'your channel id',
'your channel name',
channelDescription: 'your channel description',
),
),
androidAllowWhileIdle: true,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
matchDateTimeComponents: DateTimeComponents.time,
payload: '${task.title}|${task.note}|${task.startTime}|',
);
}
tz.TZDateTime _convertTime(
int hour, int minutes, String repeat, String date) {
final tz.TZDateTime now = tz.TZDateTime.now(tz.local);
tz.TZDateTime scheduledDate =
tz.TZDateTime(tz.local, now.year, now.month, now.day, hour, minutes);
var formattedDate = DateFormat.yMd().parse(date);
if (scheduledDate.isBefore(now)) {
if (repeat == 'يوميا') {
scheduledDate = tz.TZDateTime(tz.local, now.year, now.month,
(formattedDate.day) + 1, hour, minutes);
}
if (repeat == 'اسبوعيا') {
scheduledDate = tz.TZDateTime(tz.local, now.year, now.month,
(formattedDate.day) + 7, hour, minutes);
}
if (repeat == 'شهريا') {
scheduledDate = tz.TZDateTime(tz.local, now.year,
(formattedDate.month) + 1, formattedDate.day, hour, minutes);
}
}
debugPrint('next scheduledDate = $scheduledDate');
return scheduledDate;
}
Future<void> _configureLocalTimeZone() async {
tz.initializeTimeZones();
final String timezone = await FlutterNativeTimezone.getLocalTimezone();
tz.setLocalLocation(
tz.getLocation(timezone),
);
}
void requestIOSPermissions() {
flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
}
void _configureSelectNotificationSubject() {
selectNotificationSubject.stream.listen((String payload) async {
debugPrint('My payload is $payload');
await Get.to(() => NotificationScreen(payload: payload));
});
}
}
Future onDidReceiveLocalNotification(
int? id, String? title, String? body, String? payload) async {
Get.dialog(
const Text('welcome to flutter'),
);
}
add task page
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import '../../controllers/task_controller.dart';
import '../../models/task.dart';
import '../theme.dart';
import '../widgets/button.dart';
import '../widgets/input_field.dart';
class AddTaskPage extends StatefulWidget {
const AddTaskPage({Key? key}) : super(key: key);
#override
State<AddTaskPage> createState() => _AddTaskPageState();
}
class _AddTaskPageState extends State<AddTaskPage> {
final TaskController _taskController = Get.put(TaskController());
final TextEditingController _titleController = TextEditingController();
final TextEditingController _noteController = TextEditingController();
DateTime _selectedDate = DateTime.now();
String _startTime = DateFormat('hh:mm a')
.format(DateTime.now().add(const Duration(minutes: 1)))
.toString();
String _endTime = DateFormat('hh:mm a')
.format(DateTime.now().add(const Duration(minutes: 15)))
.toString();
String _selectedRepeat = 'بدون';
List<String> repeatList = ['بدون', 'يوميا', 'اسبوعيا', 'شهريا'];
int _selectedColor = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: context.theme.backgroundColor,
appBar: _appBar(),
body: Container(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: SingleChildScrollView(
child: Column(
children: [
Text('اضافة مهمة', style: headingStyle),
InputField(
title: 'عنوان',
hint: 'ادخل العنوان هنا',
controller: _titleController,
),
InputField(
title: 'ملاحظة',
hint: 'ادخل الملاحظة هنا',
controller: _noteController,
),
InputField(
title: 'التاريخ',
hint: DateFormat.yMd().format(_selectedDate),
widget: IconButton(
onPressed: () {
FocusScope.of(context).unfocus();
_getDateFromUser();
},
icon: const Icon(
Icons.calendar_today_outlined,
color: Colors.grey,
),
),
),
Row(
children: [
Expanded(
child: InputField(
title: 'بداية الوقت',
hint: _startTime,
widget: IconButton(
onPressed: () {
FocusScope.of(context).unfocus();
_getTimeFromUser(isStartTime: true);
},
icon: const Icon(
Icons.access_time_rounded,
color: Colors.grey,
),
),
),
),
const SizedBox(width: 12),
Expanded(
child: InputField(
title: 'نهاية الوقت',
hint: _endTime,
widget: IconButton(
onPressed: () {
FocusScope.of(context).unfocus();
_getTimeFromUser(isStartTime: false);
},
icon: const Icon(
Icons.access_time_rounded,
color: Colors.grey,
),
),
),
),
],
),
InputField(
title: 'اعادة',
hint: _selectedRepeat,
widget: Row(
children: [
DropdownButton(
dropdownColor: Colors.blueGrey,
borderRadius: BorderRadius.circular(10),
items: repeatList
.map<DropdownMenuItem<String>>(
(String value) => DropdownMenuItem<String>(
value: value,
child: Text(value,
style: const TextStyle(
color: Colors.white,
)),
),
)
.toList(),
icon: const Icon(Icons.keyboard_arrow_down,
color: Colors.grey),
iconSize: 32,
elevation: 4,
underline: Container(height: 0),
style: subTitleStyle,
onChanged: (String? newValue) {
setState(() {
_selectedRepeat = newValue!;
});
},
),
const SizedBox(width: 6),
],
),
),
const SizedBox(height: 13),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
_colorPalette(),
MyButton(
label: 'اضافة',
onTap: () {
_validateDate();
},
),
],
),
const SizedBox(height: 8),
],
),
),
),
);
}
AppBar _appBar() {
return AppBar(
leading: IconButton(
onPressed: () => Get.back(),
icon: const Icon(
Icons.arrow_back_ios,
size: 24,
color: primaryClr,
),
),
elevation: 0,
backgroundColor: context.theme.backgroundColor,
actions: const [
CircleAvatar(
backgroundImage: AssetImage('images/person.jpeg'),
radius: 18,
),
SizedBox(width: 20),
],
);
}
_validateDate() {
FocusScope.of(context).unfocus();
if (_titleController.text.isNotEmpty && _noteController.text.isNotEmpty) {
_addTasksToDb();
Get.back();
} else if (_titleController.text.isEmpty || _noteController.text.isEmpty) {
Get.snackbar(
'مطلوب',
'!كل الحقول مطلوبة',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.white,
colorText: pinkClr,
icon: const Icon(Icons.warning_amber_rounded, color: Colors.red),
);
} else {
debugPrint('############ SOMETHING BAD HAPPENED #################');
}
}
_addTasksToDb() async {
try {
//print('here is the selected month ${_selectedDate.month}');
//print('here is the selected day ${_selectedDate.day}');
int value = await _taskController.addTask(
task: Task(
title: _titleController.text,
note: _noteController.text,
isCompleted: 0,
date: DateFormat.yMd().format(_selectedDate),
startTime: _startTime,
endTime: _endTime,
color: _selectedColor,
repeat: _selectedRepeat,
),
);
debugPrint('id value = $value');
} catch (e) {
debugPrint('Error = $e');
}
}
Column _colorPalette() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('اللون', style: titleStyle),
const SizedBox(height: 8),
Wrap(
children: List<Widget>.generate(
3,
(index) => GestureDetector(
onTap: () {
setState(() {
_selectedColor = index;
});
},
child: Padding(
padding: const EdgeInsets.only(right: 8),
child: CircleAvatar(
child: _selectedColor == index
? const Icon(Icons.done, size: 16, color: Colors.white)
: null,
backgroundColor: index == 0
? primaryClr
: index == 1
? pinkClr
: orangeClr,
radius: 14,
),
),
),
),
),
],
);
}
_getDateFromUser() async {
DateTime? _pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime.now(),
lastDate: DateTime(2030),
);
if (_pickedDate != null) {
setState(() => _selectedDate = _pickedDate);
} else {
debugPrint('It\'s null or something is wrong');
}
}
_getTimeFromUser({required bool isStartTime}) async {
TimeOfDay? _pickedTime = await showTimePicker(
initialEntryMode: TimePickerEntryMode.input,
context: context,
initialTime: isStartTime
? TimeOfDay.fromDateTime(DateTime.now())
: TimeOfDay.fromDateTime(
DateTime.now().add(const Duration(minutes: 15))),
);
String _formattedTime = _pickedTime!.format(context);
if (isStartTime) {
setState(() => _startTime = _formattedTime);
} else if (!isStartTime) {
setState(() => _endTime = _formattedTime);
} else {
debugPrint('time canceld or something is wrong');
}
}
}
main screan
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import '/ui/theme.dart';
import 'db/db_helper.dart';
import 'services/theme_services.dart';
import 'ui/pages/home_page.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await DBHelper.initDb();
await GetStorage.init();
runApp(
const MyApp(),
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return GetMaterialApp(
theme: Themes.light,
darkTheme: Themes.dark,
themeMode: ThemeServices().theme,
title: 'To Do',
debugShowCheckedModeBanner: false,
home: const HomePage(),
);
}
}
Related
am building a flutter app and am am working with a data from a API i got the list and evreything i did a search bar that works properly by typing either the number of the ticket or the description but am trying to add a new filter , a checkbox that filters the data i have 2 problems
1: when i press on a checkbox and type confirm it works and it shows but the checkbox dosent stay checked
2: how can i implement it so it filter the data from the api directly
and thank you
// ignore_for_file: use_key_in_widget_constructors, avoid_print, avoid_unnecessary_containers, curly_braces_in_flow_control_structures, prefer_const_constructors, non_constant_identifier_names, unnecessary_new, avoid_function_literals_in_foreach_calls, unused_import, avoid_types_as_parameter_names, unused_label, unused_element, file_names, library_private_types_in_public_api, unnecessary_string_interpolations
import 'dart:convert';
import 'dart:io';
import 'package:az/Actifs.dart';
import 'package:az/SR_Details.dart';
import 'package:az/main.dart';
import 'package:badges/badges.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import 'class/sr.dart';
import 'package:dropdown_search/dropdown_search.dart';
class DataFromAPI extends StatefulWidget {
#override
_DataFromAPIState createState() => _DataFromAPIState();
}
List<Sr> _MyAllData=[];
List<Sr> _SrForDsiplay=[];
Map<String, Color> map={
"QUEUED":Color.fromARGB(255, 255, 136, 0),
"CLOSED":Colors.grey,
"Rejected":Colors.red,
"INPROG":Colors.green,
"PENDING":Colors.blue,
"RESOLVED":Colors.green,
"NEW":Colors.blue,
};
Map<String, String> map1={
"1":"Urgent",
"2":"High",
"3":"Medium",
"4":"Low",
};
/*Map<String, Color> map3={
"Urgent":Colors.red,
"High":Color.fromARGB(255, 255, 139, 131),
"Medium":Colors.blue,
"Low":Colors.green,
"null":Colors.grey,
};*/
class Multiselect extends StatefulWidget {
final List<String> items;
const Multiselect({Key? key, required this.items}) : super(key: key);
#override
State<Multiselect> createState() => _MultiselectState();
}
class _MultiselectState extends State<Multiselect> {
final List<String> _selectedItems=[];
void _itemChange(String itemValue, bool isSelected) {
setState(() {
if (isSelected) {
_selectedItems.add(itemValue);
} else {
_selectedItems.remove(itemValue);
}
});
}
// this function is called when the Cancel button is pressed
void _cancel() {
Navigator.pop(context);
}
// this function is called when the Submit button is tapped
void _submit() {
Navigator.pop(context, _selectedItems);
}
#override
Widget build(BuildContext context) {
return AlertDialog(
title: const Text('Select Topics'),
content: SingleChildScrollView(
child: ListBody(
children: widget.items
.map((item) => CheckboxListTile(
value: _selectedItems.contains(item),
title: Text(item),
controlAffinity: ListTileControlAffinity.leading,
onChanged: (isChecked) => _itemChange(item, isChecked!),
))
.toList(),
),
),
actions: [
TextButton(
onPressed: _cancel,
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: _submit,
child: const Text('Submit'),
),
],
);
}
}
class _DataFromAPIState extends State<DataFromAPI> {
List<String> _selectedItems=[];
String title_string = "Liste des SR :";
void _ShowMultiSelect() async{
final List<String> items=[
'QUEUED',
'CLOSED',
'Rejected',
'INPROG',
'PENDING',
'RESOLVED',
'NEW',
];
final List<String>? results =await showDialog(
context: context,
builder: (BuildContext context) {
return Multiselect(items: items);
},
);
if(results !=null){
setState(() {
_selectedItems=results;
});
}
}
#override
void initState() {
loadData().then((value) {
_MyAllData.clear();
setState(() {
_MyAllData.addAll(value);
_SrForDsiplay=_MyAllData;
});
});
super.initState();
}
Future<List<Sr>> loadData() async {
try {
var response = await http.get(Uri.parse(
'http:MXSR/?_lid=&_lpwd=&_format=json'));
if (response.statusCode == 200) {
final jsonBody = json.decode(response.body);
Demandes data = Demandes.fromJson(jsonBody);
final srAttributes = data.queryMxsrResponse.mxsrSet.sr;
title_string='Liste des SR : ${srAttributes.length.toString()}';
return srAttributes;
}
} catch (e) {
throw Exception(e.toString());
}
throw Exception("");
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner:false,
home: new Scaffold(resizeToAvoidBottomInset: false ,
appBar: AppBar(
title: Text(title_string),
leading: IconButton(
icon: Icon(Icons.arrow_back), onPressed: () { Navigator.push(
context, MaterialPageRoute(builder: (context) => Home())); },
),
flexibleSpace: InkWell(onTap: () {
},),
),
body: FutureBuilder<List<Sr>?>(
future: loadData(),
builder: (context, snapshot) {
if (_MyAllData.isEmpty) {
return SizedBox(
height: MediaQuery.of(context).size.height / 1.3,
child: Center(
child: CircularProgressIndicator(),
),
);
} else { return
ListView(
children: <Widget>[Padding(
padding: const EdgeInsets.all(8.0),
child: Column(children:<Widget>[ElevatedButton(onPressed: _ShowMultiSelect,
child: const Text('Filter')),
const Divider(
height: 30,
),
Wrap(
children: _selectedItems
.map((e) => Chip(
label: Text(e),
))
.toList(),
),
Row(children:<Widget>[ Expanded(
child: TextField(
decoration:
InputDecoration( hintText: "Enter id or description"),
onChanged: (text) {
text=text.toLowerCase();
setState(() {
_SrForDsiplay =_MyAllData.where((srAttributes) {
var srDescription = srAttributes.attributes.description!.content.toString().toLowerCase();
var srID= srAttributes.attributes.ticketid.content.toString();
return srDescription.contains(text) || srID.contains(text);
}).toList();
title_string='Liste des SR : ${_SrForDsiplay.length.toString()}';
print(title_string);
}
);
},
)),])
],
),),
new ListView.builder(scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: _SrForDsiplay.length,
itemBuilder: ((_, index) {
return
new ListTile(
title: new Card(
margin: new EdgeInsets.symmetric(
vertical: 2.0, horizontal: 8.0),
elevation: 10,
child: new ListTile(
title: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(padding: new EdgeInsets.all(2.0)),
Row(children :[
Container(
decoration: BoxDecoration(
border: Border.all(
color: Color.fromARGB(255, 255, 255, 255),
),
color: map['${_SrForDsiplay[index].attributes.status.content}'],
borderRadius: BorderRadius.all(Radius.circular(20)),
),
child:Text(' ${_SrForDsiplay[index].attributes.status.content} '),
),
Container(child: Text(' '),),
Container(
decoration: BoxDecoration(
border: Border.all(
color: Color.fromARGB(255, 255, 255, 255),
),
color:Colors.grey,
borderRadius: BorderRadius.all(Radius.circular(20)),
),
child:Text( map1['${_SrForDsiplay[index].attributes.reportedpriority?.content}'] ?? " null "),
),
],
),
SizedBox(
height: 8,
),
Row(children: <Widget>[
Expanded( child: Container(child: Text('${_SrForDsiplay[index].attributes.description?.content}',style: GoogleFonts.openSans(
textStyle: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600)),),),),
Expanded(child: Container(child:Text( ' ${_SrForDsiplay[index].attributes.ticketid.content}',style: GoogleFonts.openSans(
textStyle: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400)),)))
],),
new Divider(
color: Color.fromARGB(255, 110, 109, 109),
),
Text(
'Reported : ${DateFormat.yMMMMEEEEd().format(DateTime.parse('${_SrForDsiplay[index].attributes.statusdate.content}' ))}' ,
style: GoogleFonts.openSans(
textStyle: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400)),
),
new Text(
'Reported by : ${_SrForDsiplay[index].attributes.reportedby?.content}',style: GoogleFonts.openSans(
textStyle: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400)),
),
Row(children: [new Image(image: AssetImage('assets/courroi.png'), width: 20),
Text(
'${_SrForDsiplay[index].relatedMbos?.asset[0].attributes.descriptionasset?.content}'),], ),
Row(children: [new Image(image: AssetImage('assets/emp.png'), width: 20),
Text(
'${_SrForDsiplay[index].attributes.assetsiteid?.content}'),], ) ,
Divider(
color: Color.fromARGB(255, 110, 109, 109),
),
Row(children:[
Expanded(child: Badge(
position: BadgePosition.topEnd(top: -8, end: 20),
badgeColor: Colors.grey,
badgeContent: Text('1'),
child :IconButton(icon :Icon(Icons.file_present_rounded), padding: const EdgeInsets.all(0),
onPressed: () {
},
),
)
),
Expanded(child: IconButton (
icon: Icon(Icons.file_copy),
onPressed: () { },
),),
Expanded(child: IconButton(onPressed:() {
}, icon: Icon(Icons.delete)) )
],)
],
),
trailing: Icon(Icons.arrow_forward_ios_rounded),
),
),
onTap: () {
Navigator.push(
context,MaterialPageRoute(builder: (context) =>SrDetailsScreen(sr: _SrForDsiplay[index])),
);
}
);
}
),
)
]
);
}
},
),
),
);
}
}
i want to edit a listview item when i click on it. I managed (with inkwell) that when I click on a listview item, the bottomsheet opens again where I also create new listview items, but I just can't edit it. I've tried everything I know (I don't know much I'm a beginner). here my codes.
--main.dart--
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import '/model/transaction.dart';
import '/widget/chart.dart';
import '/widget/new_transaction.dart';
import '/widget/transactoin_list.dart';
void main() {
// WidgetsFlutterBinding.ensureInitialized();
// SystemChrome.setPreferredOrientations(
// [
// DeviceOrientation.portraitUp,
// DeviceOrientation.portraitDown,
// ],
// );
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [
Locale("de"),
Locale("en"),
],
debugShowCheckedModeBanner: false,
title: "URLI",
theme: ThemeData(
primarySwatch: Colors.lightGreen,
fontFamily: "JosefinSans",
textTheme: ThemeData()
.textTheme
.copyWith(
headline4: const TextStyle(
fontFamily: "Tochter",
fontSize: 21,
),
headline5: const TextStyle(
fontFamily: "Bombing",
fontSize: 27,
letterSpacing: 3,
),
headline6: const TextStyle(
fontSize: 21,
fontWeight: FontWeight.w900,
),
)
.apply(
bodyColor: Colors.orangeAccent,
displayColor: Colors.orangeAccent.withOpacity(0.5),
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
onPrimary: Colors.white,
primary: Theme.of(context).appBarTheme.backgroundColor,
textStyle: const TextStyle(
fontWeight: FontWeight.bold,
),
),
),
appBarTheme: const AppBarTheme(
titleTextStyle: TextStyle(
fontSize: 60,
fontFamily: "Tochter",
),
),
),
home: const AusgabenRechner(),
);
}
}
class AusgabenRechner extends StatefulWidget {
const AusgabenRechner({Key? key}) : super(key: key);
#override
State<AusgabenRechner> createState() => _AusgabenRechnerState();
}
class _AusgabenRechnerState extends State<AusgabenRechner> {
void _submitAddNewTransaction(BuildContext ctx) {
showModalBottomSheet(
context: ctx,
builder: (_) {
return GestureDetector(
onTap: () {},
child: NewTransaction(addNewTx: _addNewTransaction),
behavior: HitTestBehavior.opaque,
);
},
);
}
bool _showChart = false;
final List<Transaction> _userTransactions = [
// Transaction(
// id: "tx1",
// tittel: "Schuhe",
// preis: 99.99,
// datum: DateTime.now(),
// ),
// Transaction(
// id: "tx2",
// tittel: "Jacke",
// preis: 39.99,
// datum: DateTime.now(),
// ),
];
List<Transaction> get _recentTransactions {
return _userTransactions
.where(
(tx) => tx.datum.isAfter(
DateTime.now().subtract(
const Duration(days: 7),
),
),
)
.toList();
}
void _addNewTransaction(
String txTittel,
double txPreis,
DateTime choosenDate,
) {
final newTx = Transaction(
id: DateTime.now().toString(),
tittel: txTittel,
preis: txPreis,
datum: choosenDate,
);
setState(() {
_userTransactions.add(newTx);
});
}
void _deletedTransaction(String id) {
setState(() {
_userTransactions.removeWhere((tdddx) => tdddx.id == id);
});
}
#override
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
final isInLandscape = mediaQuery.orientation == Orientation.landscape;
final appBar = AppBar(
centerTitle: true,
toolbarHeight: 99,
actions: [
IconButton(
onPressed: () => _submitAddNewTransaction(context),
icon: const Icon(
Icons.add,
color: Colors.white,
),
),
],
title: const Text(
"Ausgaben",
),
);
final txListWidget = SizedBox(
height: (mediaQuery.size.height -
appBar.preferredSize.height -
mediaQuery.padding.top) *
0.45,
child: TransactionList(
transaction: _userTransactions,
delettx: _deletedTransaction,
showNewTransaction: _submitAddNewTransaction,
),
);
return Scaffold(
appBar: appBar,
body: SingleChildScrollView(
child: Column(
children: [
if (isInLandscape)
SizedBox(
height: (mediaQuery.size.height -
appBar.preferredSize.height -
mediaQuery.padding.top) *
0.2,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Chart anzeigen",
style: Theme.of(context).textTheme.headline5,
),
const SizedBox(width: 9),
Switch.adaptive(
inactiveTrackColor:
Theme.of(context).primaryColor.withOpacity(0.3),
activeColor: Theme.of(context).primaryColor,
value: _showChart,
onChanged: (val) {
setState(() {
_showChart = val;
});
},
),
],
),
),
if (!isInLandscape)
SizedBox(
height: (mediaQuery.size.height -
appBar.preferredSize.height -
mediaQuery.padding.top) *
0.24,
child: Chart(
recentTransactions: _recentTransactions,
),
),
if (!isInLandscape)
SizedBox(
height: (mediaQuery.size.height -
appBar.preferredSize.height -
mediaQuery.padding.top) *
0.65,
child: txListWidget),
if (isInLandscape)
_showChart
? SizedBox(
height: (mediaQuery.size.height -
appBar.preferredSize.height -
mediaQuery.padding.top) *
0.51,
child: Chart(
recentTransactions: _recentTransactions,
),
)
: SizedBox(
height: (mediaQuery.size.height -
appBar.preferredSize.height -
mediaQuery.padding.top) *
0.81,
child: txListWidget)
],
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
child: const Icon(
Icons.add,
color: Colors.white,
),
onPressed: () => _submitAddNewTransaction(context),
),
);
}
}
--transaction_list.dart--
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import '/model/transaction.dart';
class TransactionList extends StatefulWidget {
const TransactionList({
Key? key,
required this.transaction,
required this.delettx,
required this.showNewTransaction,
}) : super(key: key);
final List<Transaction> transaction;
final Function delettx;
final Function showNewTransaction;
#override
State<TransactionList> createState() => _TransactionListState();
}
class _TransactionListState extends State<TransactionList> {
#override
Widget build(BuildContext context) {
return widget.transaction.isEmpty
? LayoutBuilder(
builder: (ctx, contrains) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Keine Daten vorhanden!",
style: Theme.of(context).textTheme.headline6,
),
const SizedBox(
height: 30,
),
SizedBox(
height: contrains.maxHeight * 0.45,
child: Image.asset(
"assets/images/schlafen.png",
fit: BoxFit.cover,
),
)
],
);
},
)
: Align(
alignment: Alignment.topCenter,
child: ListView.builder(
shrinkWrap: true,
reverse: true,
itemCount: widget.transaction.length,
itemBuilder: (ctx, index) {
return InkWell(
onLongPress: () => widget.showNewTransaction(ctx),
child: Card(
elevation: 5,
child: ListTile(
leading: CircleAvatar(
radius: 33,
child: Padding(
padding: const EdgeInsets.all(9.0),
child: FittedBox(
child: Row(
children: [
Text(
widget.transaction[index].preis
.toStringAsFixed(2),
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 24,
),
),
const Text(
"€",
style: TextStyle(
fontSize: 21,
),
)
],
),
),
),
),
title: Text(
widget.transaction[index].tittel,
style: Theme.of(context).textTheme.headline6,
),
subtitle: Text(
DateFormat.yMMMMd("de")
.format(widget.transaction[index].datum),
style: Theme.of(context).textTheme.headline4,
),
trailing: MediaQuery.of(context).size.width > 460
? TextButton.icon(
onPressed: () =>
widget.delettx(widget.transaction[index].id),
icon: const Icon(
Icons.delete_outline,
),
label: const Text("Löschen"),
style: TextButton.styleFrom(
primary: Colors.red,
),
)
: IconButton(
onPressed: () =>
widget.delettx(widget.transaction[index].id),
icon: const Icon(
Icons.delete_outline,
color: Colors.red,
),
),
),
),
);
},
),
);
}
}
--new_transaction.dart--
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class NewTransaction extends StatefulWidget {
const NewTransaction({Key? key, required this.addNewTx}) : super(key: key);
final Function addNewTx;
#override
State<NewTransaction> createState() => _NewTransactionState();
}
class _NewTransactionState extends State<NewTransaction> {
final _tittelcontroller = TextEditingController();
final _preiscontroller = TextEditingController();
DateTime? _selectedDate;
void _submitData() {
final enteredTittel = _tittelcontroller.text;
final enteredPreis = double.parse(_preiscontroller.text);
if (_preiscontroller.text.isEmpty) {
return;
}
if (enteredTittel.isEmpty || enteredPreis <= 0 || _selectedDate == null) {
return;
}
widget.addNewTx(
_tittelcontroller.text,
double.parse(_preiscontroller.text),
_selectedDate,
);
Navigator.of(context).pop();
}
void _presentDatePicker() {
showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2022),
lastDate: DateTime.now(),
).then((pickedDate) {
if (pickedDate == null) {
return;
}
setState(() {
_selectedDate = pickedDate;
});
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
bottom: false,
child: SingleChildScrollView(
child: Container(
//height: MediaQuery.of(context).size.height * 0.5,
padding: EdgeInsets.only(
top: 10,
left: 18,
right: 18,
bottom: MediaQuery.of(context).viewInsets.bottom + 10,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
TextButton(
onPressed: _submitData,
child: Text(
"hinzufügen",
style: Theme.of(context).textTheme.headlineSmall,
),
),
TextField(
controller: _tittelcontroller,
onSubmitted: (_) => _submitData(),
decoration: const InputDecoration(
label: Text("Tittel"),
),
),
TextField(
controller: _preiscontroller,
keyboardType:
const TextInputType.numberWithOptions(decimal: true),
onSubmitted: (_) => _submitData(),
decoration: const InputDecoration(
label: Text("Preis"),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 66),
child: Center(
child: Column(
children: [
Text(
_selectedDate == null
? "Kein Datum ausgewählt"
: DateFormat.yMMMMEEEEd("de")
.format(_selectedDate!),
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
const SizedBox(
height: 21,
),
ElevatedButton(
style: Theme.of(context).elevatedButtonTheme.style,
onPressed: _presentDatePicker,
child: const Text("Datum wählen"),
),
],
),
),
)
],
),
),
),
);
}
}
EN: Here is an excample code, how i would solve this, when i understood the problem. The passing of the variables to the new Class is a bit differnent then in your Code but it works the same.
DE: So hier ist jetzt ein Beispielcode, wie ich es lösen würde, wenn ich das Problem richtig verstanden habe, dabei werden die Variabeln etwas anders als bei dir in die neue Klasse übergeben, funktioniert aber gleich
class testListview extends StatefulWidget {
var transaction;
var delettx;
var showNewTransaction;
//Passing the data to new Class
testListview(this.transaction, this.delettx,
this.showNewTransaction);
#override
State<testListview> createState() => _testListviewState();
}
class _testListviewState extends State<testListview> {
var transaction;
var delettx;
var showNewTransaction;
//Pass the data into the State of the new Class
_testListviewState(this.transaction, this.delettx,
this.showNewTransaction);
var transaction_2;
//The init state will be called in the first initialization of
//the Class
#override
void initState() {
//Pass your transactions to a new variable
setState(() {
transaction_2 = transaction;
});
super.initState();
}
#override
Widget build(BuildContext context) {
return ListView.builder(itemBuilder: (BuildContext context,
index){
return TextButton(onPressed: (){
//Change the data with onPressed
setState(() {
transaction_2["preis"] = "500";
});
}, child: Text(transaction_2["preis"]));
});}}
I'm working currently on a flutter project
the app is working fine but i have some issues:
1-i get the notification but i don't get any sound from the notification, i don't know if this is flutter_local_notifications dependency problem because when i tried to update it to the latest version i got few errors from main page and alarm page
2-i can't access these options(Repeat,Sound,Title):
https://i.ibb.co/4fj7x16/s3.png
here is the alarm page:
import 'package:clock_app/alarm_helper.dart';
import 'package:clock_app/constants/theme_data.dart';
import 'package:clock_app/data.dart';
import 'package:clock_app/models/alarm_info.dart';
import 'package:dotted_border/dotted_border.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:intl/intl.dart';
import '../main.dart';
class AlarmPage extends StatefulWidget {
#override
_AlarmPageState createState() => _AlarmPageState();
}
class _AlarmPageState extends State<AlarmPage> {
DateTime _alarmTime;
String _alarmTimeString;
AlarmHelper _alarmHelper = AlarmHelper();
Future<List<AlarmInfo>> _alarms;
#override
void initState() {
_alarmTime = DateTime.now();
_alarmHelper.initializeDatabase().then((value) {
print('------database intialized');
loadAlarms();
});
super.initState();
}
void loadAlarms() {
_alarms = _alarmHelper.getAlarms();
if (mounted) setState(() {});
}
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 32, vertical: 64),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Alarm',
style: TextStyle(
fontFamily: 'avenir',
fontWeight: FontWeight.w700,
color: CustomColors.primaryTextColor,
fontSize: 24),
),
Expanded(
child: FutureBuilder<List<AlarmInfo>>(
future: _alarms,
builder: (context, snapshot) {
if (snapshot.hasData)
return ListView(
children: snapshot.data.map<Widget>((alarm) {
var alarmTime =
DateFormat('hh:mm aa').format(alarm.alarmDateTime);
var gradientColor = GradientTemplate
.gradientTemplate[alarm.gradientColorIndex].colors;
return Container(
margin: const EdgeInsets.only(bottom: 32),
padding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 8),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: gradientColor,
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
boxShadow: [
BoxShadow(
color: gradientColor.last.withOpacity(0.4),
blurRadius: 8,
spreadRadius: 2,
offset: Offset(4, 4),
),
],
borderRadius: BorderRadius.all(Radius.circular(24)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
Icon(
Icons.label,
color: Colors.white,
size: 24,
),
SizedBox(width: 8),
Text(
alarm.title,
style: TextStyle(
color: Colors.white,
fontFamily: 'avenir'),
),
],
),
Switch(
onChanged: (bool value) {},
value: true,
activeColor: Colors.white,
),
],
),
Text(
'Mon-Fri',
style: TextStyle(
color: Colors.white, fontFamily: 'avenir'),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
alarmTime,
style: TextStyle(
color: Colors.white,
fontFamily: 'avenir',
fontSize: 24,
fontWeight: FontWeight.w700),
),
IconButton(
icon: Icon(Icons.delete),
color: Colors.white,
onPressed: () {
_alarmHelper.delete(alarm.id);
},
),
],
),
],
),
);
}).followedBy([
if (alarms.length < 5)
DottedBorder(
strokeWidth: 2,
color: CustomColors.clockOutline,
borderType: BorderType.RRect,
radius: Radius.circular(24),
dashPattern: [5, 4],
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: CustomColors.clockBG,
borderRadius:
BorderRadius.all(Radius.circular(24)),
),
child: FlatButton(
padding: const EdgeInsets.symmetric(
horizontal: 32, vertical: 16),
onPressed: () {
_alarmTimeString =
DateFormat('HH:mm').format(DateTime.now());
showModalBottomSheet(
useRootNavigator: true,
context: context,
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(24),
),
),
builder: (context) {
return StatefulBuilder(
builder: (context, setModalState) {
return Container(
padding: const EdgeInsets.all(32),
child: Column(
children: [
FlatButton(
onPressed: () async {
var selectedTime =
await showTimePicker(
context: context,
initialTime:
TimeOfDay.now(),
);
if (selectedTime != null) {
final now = DateTime.now();
var selectedDateTime =
DateTime(
now.year,
now.month,
now.day,
selectedTime.hour,
selectedTime
.minute);
_alarmTime =
selectedDateTime;
setModalState(() {
_alarmTimeString =
selectedTime
.toString();
});
}
},
child: Text(
_alarmTimeString,
style:
TextStyle(fontSize: 32),
),
),
ListTile(
title: Text('Repeat'),
trailing: Icon(
Icons.arrow_forward_ios),
),
ListTile(
title: Text('Sound'),
trailing: Icon(
Icons.arrow_forward_ios),
),
ListTile(
title: Text('Title'),
trailing: Icon(
Icons.arrow_forward_ios),
),
FloatingActionButton.extended(
onPressed: () async {
DateTime
scheduleAlarmDateTime;
if (_alarmTime
.isAfter(DateTime.now()))
scheduleAlarmDateTime =
_alarmTime;
else
scheduleAlarmDateTime =
_alarmTime.add(
Duration(days: 1));
var alarmInfo = AlarmInfo(
alarmDateTime:
scheduleAlarmDateTime,
gradientColorIndex:
alarms.length,
title: 'alarm',
);
_alarmHelper
.insertAlarm(alarmInfo);
scheduleAlarm(
scheduleAlarmDateTime);
},
icon: Icon(Icons.alarm),
label: Text('Save'),
),
],
),
);
},
);
},
);
// scheduleAlarm();
},
child: Column(
children: <Widget>[
Image.asset(
'assets/add_alarm.png',
scale: 1.5,
),
SizedBox(height: 8),
Text(
'Add Alarm',
style: TextStyle(
color: Colors.white,
fontFamily: 'avenir'),
),
],
),
),
),
)
else
Text('Only 5 alarms allowed!'),
]).toList(),
);
return Center(
child: Text(
'Loading..',
style: TextStyle(color: Colors.white),
),
);
},
),
),
],
),
);
}
void scheduleAlarm(DateTime scheduledNotificationDateTime) async {
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'alarm_notif',
'alarm_notif',
'Channel for Alarm notification',
icon: 'logo',
sound: RawResourceAndroidNotificationSound('a_long_cold_sting'),
largeIcon: DrawableResourceAndroidBitmap('logo'),
);
var iOSPlatformChannelSpecifics = IOSNotificationDetails(
sound: 'a_long_cold_sting.wav',
presentAlert: true,
presentBadge: true,
presentSound: true);
var platformChannelSpecifics = NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.schedule(
0,
'Office',
'Good morning! Time for office.',
scheduledNotificationDateTime,
platformChannelSpecifics);
}
}
and here is the main page:
import 'package:clock_app/enums.dart';
import 'package:clock_app/models/menu_info.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:provider/provider.dart';
import 'views/homepage.dart';
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
void main() async {
WidgetsFlutterBinding.ensureInitialized();
var initializationSettingsAndroid =
AndroidInitializationSettings('logo');
var initializationSettingsIOS = IOSInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
onDidReceiveLocalNotification:
(int id, String title, String body, String payload) async {});
var initializationSettings = InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: (String payload) async {
if (payload != null) {
debugPrint('notification payload: ' + payload);
}
});
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: ChangeNotifierProvider<MenuInfo>(
create: (context) => MenuInfo(MenuType.clock),
child: HomePage(),
),
);
}
}
and the dependencies:
flutter_local_notifications: ^1.4.4+2
i am still learning and following a tutorial, so please if you know what is the problem and how to solve it explain to me
Thanks in advance
in flutter local notification, you can set the alarm to be insisted by setting extra flag 4, and thus keep the alarm repeat until user tap on it
for more detail click here
I am trying to navigate from one screen to another with route. When I hit the button for the page to move to the route provided I get the error:
I/flutter ( 8790): Another exception was thrown: There are multiple heroes that share the same tag within a subtree.
Sharing with you the source code:
import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_counter/flutter_counter.dart';
import 'package:gender_selection/gender_selection.dart';
import 'package:group_chats/addContactUI.dart';
import 'package:group_chats/addPhone.dart';
import 'package:group_chats/letGoUI.dart';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'Animation/FadeAnimation.dart';
import 'Model/insertUserModel.dart';
class AddProfileUI extends StatefulWidget {
final List<String> listFriends;
final String phone;
AddProfileUI(this.listFriends, this.phone);
#override
_AddProfileUIState createState() => _AddProfileUIState();
}
class _AddProfileUIState extends State<AddProfileUI> {
File _image;
final picker = ImagePicker();
final _formKey = GlobalKey<FormState>();
String name = "";
String city = "";
TextEditingController dobController = TextEditingController();
bool single = false;
Gender gender;
final _scaffoldKey = GlobalKey<ScaffoldState>();
int defaultValue = 18;
List<String> selectedContact;
SharedPreferences prefs;
bool _loading = true;
Future initPrefs() async {
prefs = await SharedPreferences.getInstance();
}
uploadImage(String userId) async {
try {
FormData formData = new FormData.fromMap({
"file":
await MultipartFile.fromFile(_image.path, filename: "$userId.jpg"),
});
var response = await Dio().post(
"https://us-central1-app-backend-fc090.cloudfunctions.net/webApi/api/v1/upload_profile/$userId",
data: formData);
if (response.statusCode == 200)
return response.data;
else
return null;
} catch (e) {
print(e.toString());
return null;
}
}
Future<InsertUserModel> insertData() async {
try {
for (int i = 0; i < selectedContact.length; i++) {
if (selectedContact[i][0] == "0") {
selectedContact[i] = selectedContact[i].replaceRange(0, 1, "+972");
}
}
var body = jsonEncode({
"gender": gender.index == 0 ? "male" : "female",
"city": city,
"last_login": {},
"friends": selectedContact ?? [],
"single": single,
"name": name,
"phone_number": widget.phone,
"age": defaultValue
});
final String apiUrl =
"https://us-central1-app-backend-fc090.cloudfunctions.net/webApi/api/v1/users/${AddPhoneUI.uid}";
final response = await http.post(apiUrl,
headers: {"content-type": "application/json"}, body: body);
if (response.statusCode == 200) {
final responseString = response.body;
return insertUserModelFromJson(responseString);
}
} catch (e) {
setState(() {
_loading = false;
});
}
}
getUserData() async {
try {
final String apiUrl =
"https://us-central1-app-backend-fc090.cloudfunctions.net/webApi/api/v1/users/";
final response = await http.get(apiUrl);
if (response.statusCode == 200) {
final responseString = response.body;
return insertUserModelFromJson(responseString);
}
} catch (e) {
setState(() {
_loading = false;
});
Scaffold.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.red,
content: Text('Error: ${e.toString()}'),
duration: Duration(milliseconds: 2500),
));
}
}
Future<void> _selectStartingDate(BuildContext context) async {
DateTime selectedDate = DateTime.now();
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: DateTime(1950),
lastDate: DateTime(
DateTime.now().year, DateTime.now().month, DateTime.now().day),
);
if (picked != null && picked != selectedDate)
setState(() {
selectedDate = picked;
dobController.text = selectedDate.year.toString() +
"-" +
selectedDate.month.toString() +
"-" +
selectedDate.day.toString();
});
}
Future getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
_image = File(pickedFile.path);
});
}
showPopUp(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
shape:
OutlineInputBorder(borderRadius: BorderRadius.circular(14.0)),
content: Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
height: 20.0,
),
Text(
"My Profile",
style: TextStyle(
fontSize: 27.0, fontWeight: FontWeight.w600),
),
SizedBox(
height: 30.0,
),
RichText(
text: TextSpan(
text: "Your friends will be able to\nsee ",
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
),
children: <TextSpan>[
TextSpan(
text: 'only',
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.w500)),
TextSpan(text: 'your picture and\name.'),
],
)),
SizedBox(
height: 10.0,
),
RichText(
text: TextSpan(
text: "Other fields are used for\n",
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
),
children: <TextSpan>[
TextSpan(
text: 'research issues',
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.w500)),
TextSpan(text: "only."),
],
)),
SizedBox(
height: 10.0,
),
RichText(
text: TextSpan(
text: "Please fill all the fields.",
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
),
)),
SizedBox(
height: 80.0,
),
MaterialButton(
shape: OutlineInputBorder(
borderSide: BorderSide(width: 1.0)),
color: Colors.white38,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 20.0),
child: Text(
"Ok, got it",
style: TextStyle(fontSize: 18.0),
),
),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
));
}
#override
void initState() {
super.initState();
selectedContact = widget.listFriends;
initPrefs();
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
body: SafeArea(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(right: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {},
),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddContactUI(),
)).then((value) {
setState(() {
selectedContact = value;
});
});
},
child: Column(
children: [
Icon(
Icons.supervisor_account,
size: 40.0,
),
Text("Add Friends"),
],
),
)
],
),
),
Container(
child: GestureDetector(
onTap: () async {
await getImage();
},
child: CircleAvatar(
radius: 60.0,
backgroundImage: _image != null
? Image.file(_image).image
: Image.asset("assets/empty.png").image,
backgroundColor: Colors.transparent,
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: FadeAnimation(
1.7,
Form(
key: _formKey,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Color(0xff5E17EB).withOpacity(0.3),
blurRadius: 20,
offset: Offset(0, 10),
)
]),
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border(
bottom:
BorderSide(color: Colors.grey[200]))),
child: TextFormField(
textInputAction: TextInputAction.next,
onFieldSubmitted: (_) =>
FocusScope.of(context).nextFocus(),
onChanged: (val) {
setState(() {
name = val;
});
},
validator: (val) =>
val.isEmpty ? "Enter Name" : null,
decoration: InputDecoration(
border: InputBorder.none,
hintText: "Name",
hintStyle: TextStyle(color: Colors.grey)),
),
),
Container(
decoration: BoxDecoration(
border: Border(
bottom:
BorderSide(color: Colors.grey[200]))),
padding: EdgeInsets.all(10),
child: TextFormField(
textInputAction: TextInputAction.next,
keyboardType: TextInputType.text,
onChanged: (val) {
setState(() {
city = val;
});
},
validator: (val) {
if (val.isEmpty) return "Enter City";
// if (val.length < 6)
// return "Password should be at least 6 characters";
return null;
},
decoration: InputDecoration(
border: InputBorder.none,
hintText: "City",
hintStyle: TextStyle(color: Colors.grey)),
),
),
Container(
height: 140.0,
padding: EdgeInsets.all(10),
child: GenderSelection(
selectedGender: gender,
maleText: "", //default Male
femaleText: "", //default Female
linearGradient: LinearGradient(colors: [
Colors.indigo,
Colors.black
]), //List: [Colors.indigo, Colors.black]
selectedGenderIconBackgroundColor:
Colors.indigo, // default red
checkIconAlignment:
Alignment.centerRight, // default bottomRight
selectedGenderCheckIcon:
null, // default Icons.check
onChanged: (Gender gender) {
this.gender = gender;
print(this.gender);
},
equallyAligned: true,
animationDuration: Duration(milliseconds: 400),
isCircular: true, // default : true,
isSelectedGenderIconCircular: true,
opacityOfGradient: 0.6,
padding: const EdgeInsets.all(3),
size: 120, //default : 120
),
),
SizedBox(
height: 10.0,
),
Row(
children: [
Checkbox(
value: single,
onChanged: (value) {
setState(() {
single = !single;
});
},
),
Text(
"Are you Single?",
style: TextStyle(fontSize: 16.0),
)
],
),
Padding(
padding: const EdgeInsets.all(14.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
"Age:",
style: TextStyle(fontSize: 18.0),
),
Counter(
initialValue: defaultValue,
buttonSize: 35.0,
textStyle: TextStyle(fontSize: 25.0),
minValue: 0,
color: Colors.black,
maxValue: 80,
step: 1,
decimalPlaces: 0,
onChanged: (value) {
// get the latest value from here
setState(() {
defaultValue = value;
});
},
),
],
),
),
],
),
),
),
),
),
SizedBox(
height: 20.0,
),
FadeAnimation(
1.9,
MaterialButton(
shape: OutlineInputBorder(borderSide: BorderSide(width: 1.0)),
color: Colors.black,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 20.0),
child: Text(
"Next",
style: TextStyle(
fontSize: 18.0,
color: Colors.white,
),
),
),
onPressed: () async {
if (_formKey.currentState.validate()) {
InsertUserModel result = await insertData();
// var imageResult = await uploadImage(result.id);
print(result.data[0].id);
if (_image != null) {
await uploadImage(result.data[0].id);
}
setState(() {
_loading = false;
});
if (result != null) {
await prefs.setString("userID", result.data[0].id);
final snackBar = SnackBar(
content: Text(
result.message,
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.green,
duration: Duration(milliseconds: 2000),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LetGoUI(result.data[0].id),
));
} else {
final snackBar = SnackBar(
content: Text(
"Here is some error, please try again later!",
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.red,
duration: Duration(milliseconds: 2000),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
}
},
),
)
],
),
),
),
);
}
}
I really don't understand what is the problem because I'm not using any Heros and not have double FloatingActionButton.
How do I solve this?
Thanks
There might be problem with showing snackbar while navigating. you should remove that problem by calling following method before navigating.
void removeSnackBarCallsBeforeNavigation() {
ScaffoldMessenger.of(context).removeCurrentSnackBar();
}
I am using a function _showNotificationsAfterSecond to get notifications after a delay of 3 seconds. I tried to make a for loop to run this function 8 times so that I get 8 notifications after a delay of 3 seconds each. Upon pressing the "Start Reminders" button (which calls the function), I only get one notification and after that nothing.
What am I doing wrong?
Here's my code:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: LocalNotifications(),
);
}
}
class LocalNotifications extends StatefulWidget {
#override
_LocalNotificationsState createState() => _LocalNotificationsState();
}
class _LocalNotificationsState extends State<LocalNotifications> {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
AndroidInitializationSettings androidInitializationSettings;
IOSInitializationSettings iosInitializationSettings;
InitializationSettings initializationSettings;
#override
void initState() {
super.initState();
initializing();
}
void initializing() async {
androidInitializationSettings =
AndroidInitializationSettings('mipmap/ic_launcher');
iosInitializationSettings = IOSInitializationSettings(
onDidReceiveLocalNotification: onDidReceiveLocalNotification);
initializationSettings = InitializationSettings(
androidInitializationSettings, iosInitializationSettings);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
}
void _showNotificationsAfterSecond() async {
for( int i = 0 ; i < 8 ; i ++) {
notificationAfterSec();
}
}
Future<Null> delay(int milliseconds) {
return new Future.delayed(new Duration(milliseconds: milliseconds));
}
Future<void> notificationAfterSec() async {
var timeDelayed = DateTime.now().add(Duration(seconds: 3));
AndroidNotificationDetails androidNotificationDetails =
AndroidNotificationDetails(
'second id', 'second heading', 'second text',
priority: Priority.High,
importance: Importance.Max,
ticker: 'test');
IOSNotificationDetails iosNotificationDetails = IOSNotificationDetails();
NotificationDetails notificationDetails =
NotificationDetails(androidNotificationDetails, iosNotificationDetails);
await flutterLocalNotificationsPlugin.schedule(
1, 'yo', 'wfqawsfqsqacqfqcwefs', timeDelayed, notificationDetails);
}
Future<void> turnOffNotification(
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin) async {
await flutterLocalNotificationsPlugin.cancelAll();
}
Future onSelectNotification(String payLoad) {
if (payLoad != null) {
print(payLoad);
}
// we can set navigator to navigate another screen
}
Future onDidReceiveLocalNotification(
int id, String title, String body, String payload) async {
return CupertinoAlertDialog(
title: Text(title),
content: Text(body),
actions: <Widget>[
CupertinoDialogAction(
isDefaultAction: true,
onPressed: () {
print("");
},
child: Text("Okay")),
],
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Hydration"),
actions: <Widget>[
FlatButton(
textColor: Colors.white,
onPressed: () {
DialogUtils.showCustomDialog(context,
title: "Why should this be a priority?",
okBtnText: "Got It!",
okBtnFunction: () => Navigator.pop(context));
},
child: Icon(Icons.info_outline),
shape: CircleBorder(side: BorderSide(color: Colors.transparent)),
),
],
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/wat.jfif'), fit: BoxFit.cover)),
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
padding: EdgeInsets.all(20.0),
margin: EdgeInsets.fromLTRB(20.0, 30.0, 20.0, 0.0),
child: Column(
children: <Widget>[
Text(
'Water Intake Reminder',
style: TextStyle(color: Colors.white, fontSize: 30),
textAlign: TextAlign.center,
),
Padding(
padding: EdgeInsets.symmetric(
vertical: 20.0, horizontal: 20.0)),
Container(
child: FittedBox(
child: Image.asset(
'assets/drinking.jpg',
width: 300,
height: 300,
), //adjust this baad mein
fit: BoxFit.fill,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
),
),
],
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Colors.blueAccent[100],
),
height: 400.0,
width: 300.0,
),
Padding(padding: EdgeInsets.fromLTRB(8.0, 20.0, 8.0, 8.0)),
Padding(padding: EdgeInsets.fromLTRB(8.0, 1.0, 8.0, 1.0)),
Row(
children: <Widget>[
Padding(padding: EdgeInsets.fromLTRB(9.0, 9.0, 9.0, 9.0)),
FloatingActionButton.extended(
heroTag: "btn1",
onPressed: _showNotificationsAfterSecond,
label: Text(
"Start Reminders",
style: TextStyle(fontSize: 16.0, color: Colors.white),
),
),
Padding(padding: EdgeInsets.fromLTRB(5.0, 5.0, 5.0, 5.0)),
FloatingActionButton.extended(
heroTag: "btn2",
onPressed: () {
turnOffNotification(flutterLocalNotificationsPlugin);
},
label: Text(
"Stop Reminders",
style: TextStyle(fontSize: 16.0, color: Colors.white),
),
),
Padding(padding: EdgeInsets.fromLTRB(9.0, 9.0, 9.0, 9.0)),
],
),
],
),
),
);
}
}
class DialogUtils {
static DialogUtils _instance = new DialogUtils.internal();
DialogUtils.internal();
factory DialogUtils() => _instance;
static void showCustomDialog(BuildContext context,
{#required String title,
String okBtnText = "hhegregrbge",
#required Function okBtnFunction}) {
showDialog(
context: context,
builder: (_) {
return AlertDialog(
backgroundColor: Colors.deepPurpleAccent[100],
title: Text(
title,
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
content: Text(
" When you're pregnant, you need more water than the average person in order to form amniotic fluid, produce extra blood, build newtissue, carry nutrients, enhance digestion, and flush out wastes and toxins.Since you need more water during pregnancy, how much is enough? It’s recommended that you drink 8-12 glasses of water a day, or 2.3 liters.",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white70),
),
actions: <Widget>[
FlatButton(
child: Text(
okBtnText,
style: TextStyle(color: Colors.white),
),
onPressed: okBtnFunction,
),
],
);
});
}
}
You can copy paste run full code below
You need to use different id, you can pass i as schedule id
code snippet
void _showNotificationsAfterSecond() async {
for (int i = 0; i < 8; i++) {
notificationAfterSec(i);
}
}
Future<void> notificationAfterSec(int id) async {
...
await flutterLocalNotificationsPlugin.schedule(id, '${id} yo',
'wfqawsfqsqacqfqcwefs', timeDelayed, notificationDetails);
working demo
full code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: LocalNotifications(),
);
}
}
class LocalNotifications extends StatefulWidget {
#override
_LocalNotificationsState createState() => _LocalNotificationsState();
}
class _LocalNotificationsState extends State<LocalNotifications> {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
AndroidInitializationSettings androidInitializationSettings;
IOSInitializationSettings iosInitializationSettings;
InitializationSettings initializationSettings;
#override
void initState() {
super.initState();
initializing();
}
void initializing() async {
androidInitializationSettings =
AndroidInitializationSettings('mipmap/ic_launcher');
iosInitializationSettings = IOSInitializationSettings(
onDidReceiveLocalNotification: onDidReceiveLocalNotification);
initializationSettings = InitializationSettings(
androidInitializationSettings, iosInitializationSettings);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
}
void _showNotificationsAfterSecond() async {
for (int i = 0; i < 8; i++) {
notificationAfterSec(i);
}
}
Future<Null> delay(int milliseconds) {
return new Future.delayed(new Duration(milliseconds: milliseconds));
}
Future<void> notificationAfterSec(int id) async {
var timeDelayed = DateTime.now().add(Duration(seconds: 3));
AndroidNotificationDetails androidNotificationDetails =
AndroidNotificationDetails(
'second id', 'second heading', 'second text',
priority: Priority.High,
importance: Importance.Max,
ticker: 'test');
IOSNotificationDetails iosNotificationDetails = IOSNotificationDetails();
NotificationDetails notificationDetails =
NotificationDetails(androidNotificationDetails, iosNotificationDetails);
await flutterLocalNotificationsPlugin.schedule(id, '${id} yo',
'wfqawsfqsqacqfqcwefs', timeDelayed, notificationDetails);
}
Future<void> turnOffNotification(
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin) async {
await flutterLocalNotificationsPlugin.cancelAll();
}
Future onSelectNotification(String payLoad) {
if (payLoad != null) {
print(payLoad);
}
// we can set navigator to navigate another screen
}
Future onDidReceiveLocalNotification(
int id, String title, String body, String payload) async {
return CupertinoAlertDialog(
title: Text(title),
content: Text(body),
actions: <Widget>[
CupertinoDialogAction(
isDefaultAction: true,
onPressed: () {
print("");
},
child: Text("Okay")),
],
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Hydration"),
actions: <Widget>[
FlatButton(
textColor: Colors.white,
onPressed: () {
DialogUtils.showCustomDialog(context,
title: "Why should this be a priority?",
okBtnText: "Got It!",
okBtnFunction: () => Navigator.pop(context));
},
child: Icon(Icons.info_outline),
shape: CircleBorder(side: BorderSide(color: Colors.transparent)),
),
],
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage('https://picsum.photos/250?image=9'),
fit: BoxFit.cover)),
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
padding: EdgeInsets.all(20.0),
margin: EdgeInsets.fromLTRB(20.0, 30.0, 20.0, 0.0),
child: Column(
children: <Widget>[
Text(
'Water Intake Reminder',
style: TextStyle(color: Colors.white, fontSize: 30),
textAlign: TextAlign.center,
),
Padding(
padding: EdgeInsets.symmetric(
vertical: 20.0, horizontal: 20.0)),
Container(
child: FittedBox(
child: Image.network(
'https://picsum.photos/250?image=9',
width: 300,
height: 300,
), //adjust this baad mein
fit: BoxFit.fill,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
),
),
],
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Colors.blueAccent[100],
),
height: 400.0,
width: 300.0,
),
Padding(padding: EdgeInsets.fromLTRB(8.0, 20.0, 8.0, 8.0)),
Padding(padding: EdgeInsets.fromLTRB(8.0, 1.0, 8.0, 1.0)),
Row(
children: <Widget>[
Padding(padding: EdgeInsets.fromLTRB(9.0, 9.0, 9.0, 9.0)),
FloatingActionButton.extended(
heroTag: "btn1",
onPressed: _showNotificationsAfterSecond,
label: Text(
"Start Reminders",
style: TextStyle(fontSize: 16.0, color: Colors.white),
),
),
Padding(padding: EdgeInsets.fromLTRB(5.0, 5.0, 5.0, 5.0)),
FloatingActionButton.extended(
heroTag: "btn2",
onPressed: () {
turnOffNotification(flutterLocalNotificationsPlugin);
},
label: Text(
"Stop Reminders",
style: TextStyle(fontSize: 16.0, color: Colors.white),
),
),
Padding(padding: EdgeInsets.fromLTRB(9.0, 9.0, 9.0, 9.0)),
],
),
],
),
),
);
}
}
class DialogUtils {
static DialogUtils _instance = new DialogUtils.internal();
DialogUtils.internal();
factory DialogUtils() => _instance;
static void showCustomDialog(BuildContext context,
{#required String title,
String okBtnText = "hhegregrbge",
#required Function okBtnFunction}) {
showDialog(
context: context,
builder: (_) {
return AlertDialog(
backgroundColor: Colors.deepPurpleAccent[100],
title: Text(
title,
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
content: Text(
" When you're pregnant, you need more water than the average person in order to form amniotic fluid, produce extra blood, build newtissue, carry nutrients, enhance digestion, and flush out wastes and toxins.Since you need more water during pregnancy, how much is enough? It’s recommended that you drink 8-12 glasses of water a day, or 2.3 liters.",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white70),
),
actions: <Widget>[
FlatButton(
child: Text(
okBtnText,
style: TextStyle(color: Colors.white),
),
onPressed: okBtnFunction,
),
],
);
});
}
}