refactor folder names
parent
5f7b63d9b5
commit
c87a59a0b6
|
@ -1,7 +1,7 @@
|
||||||
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/services/database_service.dart';
|
||||||
import 'package:smoke_cess_app/service/notification_service.dart';
|
import 'package:smoke_cess_app/services/notification_service.dart';
|
||||||
import 'package:timezone/data/latest.dart' as tz;
|
import 'package:timezone/data/latest.dart' as tz;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import 'package:smoke_cess_app/service/json_service.dart';
|
import 'package:smoke_cess_app/services/json_service.dart';
|
||||||
|
|
||||||
class Settings {
|
class Settings {
|
||||||
final int group;
|
final int group;
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'package:smoke_cess_app/pages/relapse_page.dart';
|
||||||
import 'package:smoke_cess_app/pages/scanner_page.dart';
|
import 'package:smoke_cess_app/pages/scanner_page.dart';
|
||||||
import 'package:smoke_cess_app/pages/sleep_page.dart';
|
import 'package:smoke_cess_app/pages/sleep_page.dart';
|
||||||
import 'package:smoke_cess_app/pages/interval_page.dart';
|
import 'package:smoke_cess_app/pages/interval_page.dart';
|
||||||
import 'package:smoke_cess_app/service/settings_service.dart';
|
import 'package:smoke_cess_app/services/settings_service.dart';
|
||||||
import 'package:smoke_cess_app/widgets/missing_config_popup.dart';
|
import 'package:smoke_cess_app/widgets/missing_config_popup.dart';
|
||||||
|
|
||||||
class MyHomePage extends StatefulWidget {
|
class MyHomePage extends StatefulWidget {
|
||||||
|
|
|
@ -2,10 +2,10 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:mobile_scanner/mobile_scanner.dart';
|
import 'package:mobile_scanner/mobile_scanner.dart';
|
||||||
import 'package:smoke_cess_app/models/mood.dart';
|
import 'package:smoke_cess_app/models/mood.dart';
|
||||||
import 'package:smoke_cess_app/models/settings.dart';
|
import 'package:smoke_cess_app/models/settings.dart';
|
||||||
import 'package:smoke_cess_app/service/database_service.dart';
|
import 'package:smoke_cess_app/services/database_service.dart';
|
||||||
import 'package:smoke_cess_app/service/json_service.dart';
|
import 'package:smoke_cess_app/services/json_service.dart';
|
||||||
import 'package:smoke_cess_app/service/settings_service.dart';
|
import 'package:smoke_cess_app/services/settings_service.dart';
|
||||||
import 'package:smoke_cess_app/service/notification_service.dart';
|
import 'package:smoke_cess_app/services/notification_service.dart';
|
||||||
|
|
||||||
import '../models/sleep.dart';
|
import '../models/sleep.dart';
|
||||||
import '../widgets/missing_config_popup.dart';
|
import '../widgets/missing_config_popup.dart';
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:path/path.dart';
|
||||||
|
import 'package:smoke_cess_app/models/mood.dart';
|
||||||
|
import 'package:sqflite/sqflite.dart';
|
||||||
|
// ignore: depend_on_referenced_packages
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import '../models/sleep.dart';
|
||||||
|
|
||||||
|
class DatabaseService {
|
||||||
|
DatabaseService._privateConstructor();
|
||||||
|
static final DatabaseService instance = DatabaseService._privateConstructor();
|
||||||
|
|
||||||
|
static Database? _database;
|
||||||
|
Future<Database> get database async => _database ??= await _initDatabase();
|
||||||
|
|
||||||
|
Future<Database> _initDatabase() async {
|
||||||
|
Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
||||||
|
String path = join(documentsDirectory.path, 'database.db');
|
||||||
|
return await openDatabase(path,
|
||||||
|
version: 1, onCreate: _onCreate, onOpen: _createTablesIfNotExists);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future _onCreate(Database db, int version) async {
|
||||||
|
await _createTablesIfNotExists(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future _createTablesIfNotExists(Database db) async {
|
||||||
|
await db.execute(_createMoodTable);
|
||||||
|
await db.execute(_createSleepTable);
|
||||||
|
await db.execute(_createRelapseTable);
|
||||||
|
await db.execute(_createWorkoutTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO use generic function?
|
||||||
|
Future<List<Mood>> getMoodRecords() async {
|
||||||
|
Database db = await instance.database;
|
||||||
|
var moodRecords = await db.query('mood');
|
||||||
|
List<Mood> moodList = moodRecords.isNotEmpty
|
||||||
|
? moodRecords.map((e) => Mood.fromDatabase(e)).toList()
|
||||||
|
: [];
|
||||||
|
return moodList;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<Sleep>> getSleepRecords() async {
|
||||||
|
Database db = await instance.database;
|
||||||
|
var sleepRecords = await db.query('sleep');
|
||||||
|
List<Sleep> sleepList = sleepRecords.isNotEmpty
|
||||||
|
? sleepRecords.map((e) => Sleep.fromDatabase(e)).toList()
|
||||||
|
: [];
|
||||||
|
return sleepList;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> addMood(Mood mood) async {
|
||||||
|
Database db = await instance.database;
|
||||||
|
return await db.insert('mood', mood.toMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> addSleep(Sleep sleep) async {
|
||||||
|
Database db = await instance.database;
|
||||||
|
return await db.insert('sleep', sleep.toMap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _createMoodTable = '''
|
||||||
|
CREATE TABLE IF NOT EXISTS mood(
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
value INTEGER,
|
||||||
|
date TEXT,
|
||||||
|
comment TEXT
|
||||||
|
)
|
||||||
|
''';
|
||||||
|
|
||||||
|
String _createSleepTable = '''
|
||||||
|
CREATE TABLE IF NOT EXISTS sleep(
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
value INTEGER,
|
||||||
|
date TEXT,
|
||||||
|
comment TEXT,
|
||||||
|
sleepedAtHour INTEGER,
|
||||||
|
sleepedAtMinute INTEGER,
|
||||||
|
wokeUpAtHour INTEGER,
|
||||||
|
wokeUpAtMinute INTEGER
|
||||||
|
)
|
||||||
|
''';
|
||||||
|
|
||||||
|
String _createRelapseTable = '''
|
||||||
|
CREATE TABLE IF NOT EXISTS relapse(
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
date TEXT,
|
||||||
|
comment TEXT,
|
||||||
|
reason TEXT
|
||||||
|
)
|
||||||
|
''';
|
||||||
|
|
||||||
|
String _createWorkoutTable = '''
|
||||||
|
CREATE TABLE IF NOT EXISTS workout(
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
date TEXT,
|
||||||
|
motivationBefore INTEGER,
|
||||||
|
commentBefore TEXT,
|
||||||
|
motivationAfter INTEGER,
|
||||||
|
commentAfter TEXT,
|
||||||
|
completed INTEGER
|
||||||
|
)
|
||||||
|
''';
|
|
@ -0,0 +1,63 @@
|
||||||
|
import 'package:smoke_cess_app/services/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) {
|
||||||
|
final List<TZDateTime> tzDateTimes = [];
|
||||||
|
final DateTime now = DateTime.now();
|
||||||
|
final Duration offset = now.timeZoneOffset;
|
||||||
|
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.year, now.month, now.day, selectedHours,
|
||||||
|
selectedMinutes, 0, 0, 0)
|
||||||
|
.add(Duration(days: i));
|
||||||
|
if (selectedDaysInt.contains(date.weekday) &&
|
||||||
|
date.isAfter(DateTime.now())) {
|
||||||
|
tzDateTimes.add(TZDateTime.local(date.year, date.month, date.day,
|
||||||
|
selectedHours, selectedMinutes, 0, 0, 0)
|
||||||
|
.subtract(offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tzDateTimes;
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
|
import 'package:smoke_cess_app/services/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 DarwinInitializationSettings initializationSettingsIOS =
|
||||||
|
DarwinInitializationSettings(
|
||||||
|
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> showNotification() async {
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
0,
|
||||||
|
'test',
|
||||||
|
'test',
|
||||||
|
//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: DarwinNotificationDetails(
|
||||||
|
sound: 'default.wav',
|
||||||
|
presentAlert: true,
|
||||||
|
presentBadge: true,
|
||||||
|
presentSound: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setAllNotifications() async {
|
||||||
|
List<TZDateTime> moodDates = await getDatesforMood();
|
||||||
|
List<TZDateTime> sleepDates = await getDatesforSleep();
|
||||||
|
int index = 0;
|
||||||
|
for (var date in moodDates) {
|
||||||
|
setNotification(index, "Mood", "Evaluate your mood", date);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
for (var date in sleepDates) {
|
||||||
|
setNotification(index, "Sleep", "Evaluate your sleep", date);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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: DarwinNotificationDetails(
|
||||||
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'package:smoke_cess_app/models/settings.dart';
|
||||||
|
import 'package:smoke_cess_app/services/json_service.dart';
|
||||||
|
|
||||||
|
//access group setting which was saved in local storage
|
||||||
|
Future<int?> getGroup() => _getIntSetting('group');
|
||||||
|
|
||||||
|
Future<List<String>?> getRelapseCategories() =>
|
||||||
|
_getStringListSetting('relapse_categories');
|
||||||
|
|
||||||
|
Future<List<String>?> getSleepQueryDaysCategories() =>
|
||||||
|
_getStringListSetting('sleep_query_days');
|
||||||
|
|
||||||
|
Future<int?> getSleepQueryHours() => _getIntSetting('sleep_query_hours');
|
||||||
|
Future<int?> getSleepQueryMinutes() => _getIntSetting('sleep_query_minutes');
|
||||||
|
|
||||||
|
Future<List<String>?> getMoodQueryDaysCategories() =>
|
||||||
|
_getStringListSetting('mood_query_days');
|
||||||
|
|
||||||
|
Future<int?> getMoodQueryHours() => _getIntSetting('mood_query_hours');
|
||||||
|
Future<int?> getMoodQueryMinutes() => _getIntSetting('mood_query_minutes');
|
||||||
|
|
||||||
|
Future<int?> getChessHours() => _getIntSetting('chess_hours');
|
||||||
|
Future<int?> getChessMinutes() => _getIntSetting('chess_minutes');
|
||||||
|
|
||||||
|
void _setStringSetting(String settingKey, String settingValue) =>
|
||||||
|
SharedPreferences.getInstance()
|
||||||
|
.then((pref) => pref.setString(settingKey, settingValue));
|
||||||
|
|
||||||
|
Future<String?> _getStringSetting(String settingKey) =>
|
||||||
|
SharedPreferences.getInstance().then((pref) => pref.getString(settingKey));
|
||||||
|
|
||||||
|
void _setIntSetting(String settingKey, int settingValue) =>
|
||||||
|
SharedPreferences.getInstance()
|
||||||
|
.then((pref) => pref.setInt(settingKey, settingValue));
|
||||||
|
|
||||||
|
Future<int?> _getIntSetting(String settingKey) =>
|
||||||
|
SharedPreferences.getInstance().then((pref) => pref.getInt(settingKey));
|
||||||
|
|
||||||
|
void _setStringListSetting(String settingKey, List<String> list) =>
|
||||||
|
SharedPreferences.getInstance()
|
||||||
|
.then((pref) => pref.setStringList(settingKey, list));
|
||||||
|
|
||||||
|
Future<List<String>?> _getStringListSetting(String settingKey) =>
|
||||||
|
SharedPreferences.getInstance()
|
||||||
|
.then((pref) => pref.getStringList(settingKey));
|
||||||
|
|
||||||
|
Future<void> loadSettingsFromLocalJSON() async {
|
||||||
|
Map<String, dynamic> configJSON = await loadLocalConfigJSON();
|
||||||
|
Settings settings = Settings.fromJson(configJSON);
|
||||||
|
saveSettings(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveSettings(Settings settings) {
|
||||||
|
_setIntSetting('group', settings.group);
|
||||||
|
_setStringListSetting('relapse_categories', settings.relapseCategories!);
|
||||||
|
_setStringListSetting('mood_query_days', settings.moodQuery.days!);
|
||||||
|
_setIntSetting('mood_query_hours', settings.moodQuery.hours);
|
||||||
|
_setIntSetting('mood_query_minutes', settings.moodQuery.minutes);
|
||||||
|
_setStringListSetting('sleep_query_days', settings.sleepQuery.days!);
|
||||||
|
_setIntSetting('sleep_query_hours', settings.sleepQuery.hours);
|
||||||
|
_setIntSetting('sleep_query_minutes', settings.sleepQuery.minutes);
|
||||||
|
if (settings.chessTime != null) {
|
||||||
|
_setIntSetting('chess_hours', settings.chessTime!.hours);
|
||||||
|
_setIntSetting('chess_minutes', settings.chessTime!.minutes);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:smoke_cess_app/models/mood.dart';
|
import 'package:smoke_cess_app/models/mood.dart';
|
||||||
import 'package:smoke_cess_app/service/database_service.dart';
|
import 'package:smoke_cess_app/services/database_service.dart';
|
||||||
import 'package:smoke_cess_app/widgets/slider.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/submit_form_button.dart';
|
||||||
import 'package:smoke_cess_app/widgets/text_formfield.dart';
|
import 'package:smoke_cess_app/widgets/text_formfield.dart';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:smoke_cess_app/models/sleep.dart';
|
import 'package:smoke_cess_app/models/sleep.dart';
|
||||||
import 'package:smoke_cess_app/service/database_service.dart';
|
import 'package:smoke_cess_app/services/database_service.dart';
|
||||||
import 'package:smoke_cess_app/widgets/elevated_card.dart';
|
import 'package:smoke_cess_app/widgets/elevated_card.dart';
|
||||||
import 'package:smoke_cess_app/widgets/slider.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/submit_form_button.dart';
|
||||||
|
|
Loading…
Reference in New Issue