commit
9d08c15119
|
@ -1,11 +1,16 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:smoke_cess_app/pages/main_page.dart';
|
import 'package:smoke_cess_app/pages/main_page.dart';
|
||||||
import 'package:smoke_cess_app/service/database_service.dart';
|
import 'package:smoke_cess_app/service/database_service.dart';
|
||||||
|
import 'package:smoke_cess_app/service/notification_service.dart';
|
||||||
|
import 'package:timezone/data/latest.dart' as tz;
|
||||||
|
|
||||||
void main() async {
|
void main() {
|
||||||
|
// to ensure all the widgets are initialized.
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
//init database
|
//init database
|
||||||
DatabaseService.instance;
|
DatabaseService.instance;
|
||||||
|
tz.initializeTimeZones();
|
||||||
|
NotificationService().initNotification();
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:audioplayers/audioplayers.dart';
|
import 'package:audioplayers/audioplayers.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:smoke_cess_app/widgets/popup_for_start_and_stop.dart';
|
||||||
|
|
||||||
class IntervalTimerPage extends StatefulWidget {
|
class IntervalTimerPage extends StatefulWidget {
|
||||||
const IntervalTimerPage({Key? key}) : super(key: key);
|
const IntervalTimerPage({Key? key}) : super(key: key);
|
||||||
|
@ -38,11 +39,18 @@ class _IntervalTimerPageState extends State<IntervalTimerPage> {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startTimer() {
|
void _startTimer() async {
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return const TimerStartStopPopup(
|
||||||
|
title: 'Motivation vor dem Training',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
_isPaused = false;
|
_isPaused = false;
|
||||||
() async {
|
await AudioPlayer().play(UrlSource('assets/go.mp3'));
|
||||||
await AudioPlayer().play(UrlSource('assets/go.mp3'));
|
|
||||||
}();
|
|
||||||
_timer = Timer.periodic(const Duration(seconds: 1), (_) => _tick());
|
_timer = Timer.periodic(const Duration(seconds: 1), (_) => _tick());
|
||||||
Future.delayed(const Duration(seconds: 1)).then((value) {
|
Future.delayed(const Duration(seconds: 1)).then((value) {
|
||||||
_playWarmUpMusic();
|
_playWarmUpMusic();
|
||||||
|
@ -51,9 +59,9 @@ class _IntervalTimerPageState extends State<IntervalTimerPage> {
|
||||||
|
|
||||||
void _resetTimer() {
|
void _resetTimer() {
|
||||||
() async {
|
() async {
|
||||||
await coolDownPlayer.dispose();
|
await coolDownPlayer.stop();
|
||||||
await warmUpPlayer.dispose();
|
await warmUpPlayer.stop();
|
||||||
await workoutPlayer.dispose();
|
await workoutPlayer.stop();
|
||||||
}();
|
}();
|
||||||
_isPaused = true;
|
_isPaused = true;
|
||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
|
@ -61,6 +69,14 @@ class _IntervalTimerPageState extends State<IntervalTimerPage> {
|
||||||
_currentDuration = _warmupDuration;
|
_currentDuration = _warmupDuration;
|
||||||
_totalDuration = const Duration(minutes: 35);
|
_totalDuration = const Duration(minutes: 35);
|
||||||
setState(() {});
|
setState(() {});
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return const TimerStartStopPopup(
|
||||||
|
title: 'Motivation nach dem Training',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _playWarmUpMusic() async {
|
Future<void> _playWarmUpMusic() async {
|
||||||
|
@ -69,8 +85,9 @@ class _IntervalTimerPageState extends State<IntervalTimerPage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _playWorkoutMusic() async {
|
Future<void> _playWorkoutMusic() async {
|
||||||
await warmUpPlayer.dispose();
|
await warmUpPlayer.stop();
|
||||||
Future.delayed(const Duration(microseconds: 600)).then((value) async {
|
Future.delayed(const Duration(microseconds: 600)).then((value) async {
|
||||||
|
await workoutPlayer.setReleaseMode(ReleaseMode.loop);
|
||||||
await workoutPlayer.play(UrlSource('assets/workout.mp3'));
|
await workoutPlayer.play(UrlSource('assets/workout.mp3'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -105,7 +122,8 @@ class _IntervalTimerPageState extends State<IntervalTimerPage> {
|
||||||
_currentBlock++;
|
_currentBlock++;
|
||||||
_currentDuration = _cooldownDuration;
|
_currentDuration = _cooldownDuration;
|
||||||
() async {
|
() async {
|
||||||
await workoutPlayer.dispose();
|
await workoutPlayer.stop();
|
||||||
|
await coolDownPlayer.setReleaseMode(ReleaseMode.loop);
|
||||||
await coolDownPlayer.play(UrlSource('assets/cool_down.mp3'));
|
await coolDownPlayer.play(UrlSource('assets/cool_down.mp3'));
|
||||||
}();
|
}();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'package:smoke_cess_app/models/settings.dart';
|
||||||
import 'package:smoke_cess_app/service/database_service.dart';
|
import 'package:smoke_cess_app/service/database_service.dart';
|
||||||
import 'package:smoke_cess_app/service/json_service.dart';
|
import 'package:smoke_cess_app/service/json_service.dart';
|
||||||
import 'package:smoke_cess_app/service/settings_service.dart';
|
import 'package:smoke_cess_app/service/settings_service.dart';
|
||||||
|
import 'package:smoke_cess_app/service/notification_service.dart';
|
||||||
|
|
||||||
import '../models/sleep.dart';
|
import '../models/sleep.dart';
|
||||||
import '../widgets/missing_config_popup.dart';
|
import '../widgets/missing_config_popup.dart';
|
||||||
|
@ -70,6 +71,7 @@ class ScannerPageState extends State<ScannerPage> {
|
||||||
textStyle: const TextStyle(fontSize: 20)),
|
textStyle: const TextStyle(fontSize: 20)),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
loadSettingsFromLocalJSON();
|
loadSettingsFromLocalJSON();
|
||||||
|
NotificationService().setAllNotifications();
|
||||||
},
|
},
|
||||||
child: const Text('Read JSON'),
|
child: const Text('Read JSON'),
|
||||||
),
|
),
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import 'package:smoke_cess_app/service/settings_service.dart';
|
||||||
|
import 'package:timezone/timezone.dart';
|
||||||
|
|
||||||
|
const int trainingTime = 40;
|
||||||
|
|
||||||
|
const weekDays = {
|
||||||
|
"Montag": 1,
|
||||||
|
"Dienstag": 2,
|
||||||
|
"Mittwoch": 3,
|
||||||
|
"Donnerstag": 4,
|
||||||
|
"Freitag": 5,
|
||||||
|
"Samstag": 6,
|
||||||
|
"Sonntag": 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
Future<List<TZDateTime>> getDatesforAll() async {
|
||||||
|
List<TZDateTime> allDates = [];
|
||||||
|
List<TZDateTime> moodDates = await getDatesforMood();
|
||||||
|
List<TZDateTime> sleepDates = await getDatesforSleep();
|
||||||
|
allDates.addAll(moodDates);
|
||||||
|
allDates.addAll(sleepDates);
|
||||||
|
return allDates;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<TZDateTime>> getDatesforMood() async {
|
||||||
|
final List<String>? selectedDays = await getMoodQueryDaysCategories();
|
||||||
|
final int? selectedHours = await getMoodQueryHours();
|
||||||
|
final int? selectedMinutes = await getMoodQueryMinutes();
|
||||||
|
return createTZDateTimes(selectedDays, selectedHours, selectedMinutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<TZDateTime>> getDatesforSleep() async {
|
||||||
|
final List<String>? selectedDays = await getSleepQueryDaysCategories();
|
||||||
|
final int? selectedHours = await getSleepQueryHours();
|
||||||
|
final int? selectedMinutes = await getSleepQueryMinutes();
|
||||||
|
return createTZDateTimes(selectedDays, selectedHours, selectedMinutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TZDateTime> createTZDateTimes(
|
||||||
|
List<String>? selectedDays, int? selectedHours, int? selectedMinutes) {
|
||||||
|
List<TZDateTime> tzDateTimes = [];
|
||||||
|
if (selectedDays == null ||
|
||||||
|
selectedHours == null ||
|
||||||
|
selectedMinutes == null) {
|
||||||
|
return tzDateTimes;
|
||||||
|
}
|
||||||
|
final Iterable<int?> selectedDaysInt =
|
||||||
|
selectedDays.map((day) => weekDays[day]);
|
||||||
|
for (int i = 0; i < trainingTime; i++) {
|
||||||
|
final DateTime date = DateTime.now().add(Duration(days: i));
|
||||||
|
if (selectedDaysInt.contains(date.weekday)) {
|
||||||
|
tzDateTimes.add(TZDateTime.local(date.year, date.month, date.day,
|
||||||
|
selectedHours, selectedMinutes, 0, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tzDateTimes;
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
|
import 'package:smoke_cess_app/service/date_service.dart';
|
||||||
|
import 'package:timezone/timezone.dart';
|
||||||
|
|
||||||
|
class NotificationService {
|
||||||
|
static final NotificationService _notificationService =
|
||||||
|
NotificationService._internal();
|
||||||
|
|
||||||
|
factory NotificationService() {
|
||||||
|
return _notificationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
|
||||||
|
FlutterLocalNotificationsPlugin();
|
||||||
|
|
||||||
|
NotificationService._internal();
|
||||||
|
|
||||||
|
Future<void> initNotification() async {
|
||||||
|
// Android initialization
|
||||||
|
const AndroidInitializationSettings initializationSettingsAndroid =
|
||||||
|
AndroidInitializationSettings('@mipmap/ic_launcher');
|
||||||
|
|
||||||
|
// ios initialization
|
||||||
|
const IOSInitializationSettings initializationSettingsIOS =
|
||||||
|
IOSInitializationSettings(
|
||||||
|
requestAlertPermission: false,
|
||||||
|
requestBadgePermission: false,
|
||||||
|
requestSoundPermission: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
const InitializationSettings initializationSettings =
|
||||||
|
InitializationSettings(
|
||||||
|
android: initializationSettingsAndroid,
|
||||||
|
iOS: initializationSettingsIOS);
|
||||||
|
// the initialization settings are initialized after they are setted
|
||||||
|
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setAllNotifications() async {
|
||||||
|
List<TZDateTime> moodDates = await getDatesforMood();
|
||||||
|
List<TZDateTime> sleepDates = await getDatesforSleep();
|
||||||
|
for (var date in moodDates) {
|
||||||
|
setNotification(1, "Mood", "Evaluate your mood", date);
|
||||||
|
print("mood");
|
||||||
|
}
|
||||||
|
for (var date in sleepDates) {
|
||||||
|
setNotification(1, "Sleep", "Evaluate your sleep", date);
|
||||||
|
print("sleep");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setNotification(
|
||||||
|
int id, String title, String body, TZDateTime tzDateTime) async {
|
||||||
|
await flutterLocalNotificationsPlugin.zonedSchedule(
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
body,
|
||||||
|
tzDateTime, //schedule the notification to show after 2 seconds.
|
||||||
|
const NotificationDetails(
|
||||||
|
// Android details
|
||||||
|
android: AndroidNotificationDetails('main_channel', 'Main Channel',
|
||||||
|
channelDescription: "ashwin",
|
||||||
|
importance: Importance.max,
|
||||||
|
priority: Priority.max),
|
||||||
|
// iOS details
|
||||||
|
iOS: IOSNotificationDetails(
|
||||||
|
sound: 'default.wav',
|
||||||
|
presentAlert: true,
|
||||||
|
presentBadge: true,
|
||||||
|
presentSound: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Type of time interpretation
|
||||||
|
uiLocalNotificationDateInterpretation:
|
||||||
|
UILocalNotificationDateInterpretation.absoluteTime,
|
||||||
|
androidAllowWhileIdle:
|
||||||
|
true, // To show notification even when the app is closed
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,18 +18,18 @@ class ElevatedCard extends StatelessWidget {
|
||||||
borderRadius: BorderRadius.circular(16.0),
|
borderRadius: BorderRadius.circular(16.0),
|
||||||
),
|
),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(14.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
title,
|
title,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 18.0,
|
fontSize: 16.0,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 8.0),
|
const SizedBox(height: 8.0),
|
||||||
child,
|
child,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -16,7 +16,7 @@ class MoodForm extends StatefulWidget {
|
||||||
|
|
||||||
class _MoodFormState extends State<MoodForm> {
|
class _MoodFormState extends State<MoodForm> {
|
||||||
final GlobalKey<FormState> _moodFormKey = GlobalKey<FormState>();
|
final GlobalKey<FormState> _moodFormKey = GlobalKey<FormState>();
|
||||||
MySlider slider = const MySlider('');
|
MySlider slider = const MySlider();
|
||||||
String _textInput = "";
|
String _textInput = "";
|
||||||
|
|
||||||
void submitForm() {
|
void submitForm() {
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:smoke_cess_app/widgets/slider.dart';
|
||||||
|
import 'package:smoke_cess_app/widgets/submit_form_button.dart';
|
||||||
|
import 'package:smoke_cess_app/widgets/text_formfield.dart';
|
||||||
|
|
||||||
|
class TimerStartStopPopup extends StatefulWidget {
|
||||||
|
final String title;
|
||||||
|
|
||||||
|
const TimerStartStopPopup({Key? key, required this.title}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
TimerStartStopPopupState createState() => TimerStartStopPopupState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimerStartStopPopupState extends State<TimerStartStopPopup> {
|
||||||
|
final MySlider slider = const MySlider();
|
||||||
|
|
||||||
|
void submitForm(BuildContext context) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onFormFieldSave(String? newValue) => newValue!;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text(widget.title),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(top: 8),
|
||||||
|
child: MySlider(labelText: 'Motivation'),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
MyTextFormField('Beschreibe deinen Motivation', onFormFieldSave),
|
||||||
|
SubmitFormButton(() => submitForm(context)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ class SleepForm extends StatefulWidget {
|
||||||
|
|
||||||
class _SleepFormState extends State<SleepForm> {
|
class _SleepFormState extends State<SleepForm> {
|
||||||
final GlobalKey<FormState> _sleepFormKey = GlobalKey<FormState>();
|
final GlobalKey<FormState> _sleepFormKey = GlobalKey<FormState>();
|
||||||
MySlider slider = const MySlider('');
|
MySlider slider = const MySlider();
|
||||||
String _textInput = "";
|
String _textInput = "";
|
||||||
TimePicker sleepTimePicker = TimePicker(
|
TimePicker sleepTimePicker = TimePicker(
|
||||||
const TimeOfDay(hour: 22, minute: 00),
|
const TimeOfDay(hour: 22, minute: 00),
|
||||||
|
|
|
@ -3,8 +3,10 @@ import 'package:flutter/material.dart';
|
||||||
double _currentSliderValue = 50;
|
double _currentSliderValue = 50;
|
||||||
|
|
||||||
class MySlider extends StatefulWidget {
|
class MySlider extends StatefulWidget {
|
||||||
final String _title;
|
final String _labelText;
|
||||||
const MySlider(this._title, {Key? key}) : super(key: key);
|
const MySlider({Key? key, String labelText = 'Stimmung'})
|
||||||
|
: _labelText = labelText,
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() => SliderState();
|
State<StatefulWidget> createState() => SliderState();
|
||||||
|
@ -30,7 +32,6 @@ class SliderState extends State<MySlider> {
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(widget._title),
|
|
||||||
SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
@ -58,7 +59,7 @@ class SliderState extends State<MySlider> {
|
||||||
controller: _textFieldController,
|
controller: _textFieldController,
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Stimmung',
|
labelText: widget._labelText,
|
||||||
errorText: _errorText,
|
errorText: _errorText,
|
||||||
),
|
),
|
||||||
onChanged: (text) {
|
onChanged: (text) {
|
||||||
|
|
58
pubspec.lock
58
pubspec.lock
|
@ -1,6 +1,13 @@
|
||||||
# Generated by pub
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
packages:
|
||||||
|
args:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: args
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.0"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -99,6 +106,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.5"
|
version: "1.0.5"
|
||||||
|
dbus:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: dbus
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.7.8"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -132,6 +146,27 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.1"
|
||||||
|
flutter_local_notifications:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_local_notifications
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "9.9.1"
|
||||||
|
flutter_local_notifications_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_local_notifications_linux
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.1"
|
||||||
|
flutter_local_notifications_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_local_notifications_platform_interface
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "5.0.0"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -247,6 +282,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.3"
|
version: "2.1.3"
|
||||||
|
petitparser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: petitparser
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "5.1.0"
|
||||||
platform:
|
platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -385,6 +427,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.12"
|
version: "0.4.12"
|
||||||
|
timezone:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: timezone
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.8.0"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -419,7 +468,14 @@ packages:
|
||||||
name: xdg_directories
|
name: xdg_directories
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "0.2.0+3"
|
||||||
|
xml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xml
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "6.1.0"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.18.2 <3.0.0"
|
dart: ">=2.18.2 <3.0.0"
|
||||||
flutter: ">=3.3.0"
|
flutter: ">=3.3.0"
|
||||||
|
|
|
@ -38,6 +38,8 @@ dependencies:
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
|
flutter_local_notifications: ^9.3.1
|
||||||
|
timezone: ^0.8.0
|
||||||
shared_preferences: ^2.0.17
|
shared_preferences: ^2.0.17
|
||||||
audioplayers: ^3.0.1
|
audioplayers: ^3.0.1
|
||||||
mobile_scanner: ^3.0.0
|
mobile_scanner: ^3.0.0
|
||||||
|
|
Loading…
Reference in New Issue