203 lines
7.0 KiB
Dart
203 lines
7.0 KiB
Dart
|
import 'dart:convert';
|
||
|
import 'dart:ui';
|
||
|
|
||
|
import 'package:intl/intl.dart';
|
||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||
|
|
||
|
import '../definitions/color_pair.dart';
|
||
|
|
||
|
class PreferencesService {
|
||
|
static const _keyColor1 = 'color1';
|
||
|
static const _keyColor2 = 'color2';
|
||
|
static const _keyDiaryEntries = 'diaryEntries';
|
||
|
static const _keyPin = 'userPin';
|
||
|
static const _keyPinEnabled = 'pinEnabled';
|
||
|
|
||
|
// Helper method to save a ColorPair preference
|
||
|
Future<void> saveColorPair(ColorPair colorPair) async {
|
||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||
|
await prefs.setString(_keyColor1, colorPair.backgroundColor.value.toString());
|
||
|
await prefs.setString(_keyColor2, colorPair.textColor.value.toString());
|
||
|
}
|
||
|
|
||
|
// Helper method to load the ColorPair preference
|
||
|
Future<ColorPair> loadColorPair() async {
|
||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||
|
final String? color1 = prefs.getString(_keyColor1);
|
||
|
final String? color2 = prefs.getString(_keyColor2);
|
||
|
|
||
|
if (color1 != null && color2 != null) {
|
||
|
return ColorPair(
|
||
|
name: "Custom", // You might want to handle naming differently
|
||
|
textColor: Color(int.parse(color2)),
|
||
|
backgroundColor: Color(int.parse(color1)),
|
||
|
);
|
||
|
}
|
||
|
return colorPairs[0]; // Return null if no color pair is set
|
||
|
}
|
||
|
|
||
|
// Get the diary entry for the current date
|
||
|
Future<DiaryEntry?> getDiaryEntryByCurrentDate() async {
|
||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||
|
final String diaryEntriesJson = prefs.getString(_keyDiaryEntries) ?? '{}';
|
||
|
final Map<String, dynamic> diaryEntriesMap = json.decode(diaryEntriesJson);
|
||
|
|
||
|
String todayKey = DateTime.now().toIso8601String().split('T')[0];
|
||
|
|
||
|
if (diaryEntriesMap.containsKey(todayKey)) {
|
||
|
final Map<String, dynamic> entryData = diaryEntriesMap[todayKey];
|
||
|
final List<String> texts = List<String>.from(entryData['texts']);
|
||
|
return DiaryEntry(
|
||
|
date: DateTime.parse(todayKey),
|
||
|
percentValue: entryData['percentValue'],
|
||
|
texts: texts,
|
||
|
);
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
// Get the diary entry by a given date
|
||
|
Future<DiaryEntry?> getDiaryEntryByDate(DateTime date) async {
|
||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||
|
final String diaryEntriesJson = prefs.getString(_keyDiaryEntries) ?? '{}';
|
||
|
final Map<String, dynamic> diaryEntriesMap = json.decode(diaryEntriesJson);
|
||
|
|
||
|
String dateKey = date.toIso8601String().split('T')[0];
|
||
|
|
||
|
if (diaryEntriesMap.containsKey(dateKey)) {
|
||
|
final Map<String, dynamic> entryData = diaryEntriesMap[dateKey];
|
||
|
final List<String> texts = List<String>.from(entryData['texts']);
|
||
|
return DiaryEntry(
|
||
|
date: DateTime.parse(dateKey),
|
||
|
percentValue: entryData['percentValue'],
|
||
|
texts: texts,
|
||
|
);
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
// Save a diary entry
|
||
|
Future<void> saveDiaryEntry(DiaryEntry entry) async {
|
||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||
|
final Map<String, dynamic> diaryEntriesMap = json.decode(prefs.getString(_keyDiaryEntries) ?? '{}');
|
||
|
|
||
|
// Use the date as the ID for the diary entry
|
||
|
final String dateKey = entry.date.toIso8601String().split('T')[0];
|
||
|
|
||
|
// If the entry is new or the date is older than two days, add or update the text
|
||
|
if (!diaryEntriesMap.containsKey(dateKey) || DateTime.now().difference(entry.date).inDays > 2) {
|
||
|
final List<String> texts = diaryEntriesMap[dateKey] != null ? List<String>.from(diaryEntriesMap[dateKey]['texts']) : [];
|
||
|
texts.addAll(entry.texts);
|
||
|
diaryEntriesMap[dateKey] = {
|
||
|
'percentValue': entry.percentValue,
|
||
|
'texts': texts,
|
||
|
};
|
||
|
} else {
|
||
|
// For an existing entry less than two days old, update the percent value and overwrite the text
|
||
|
diaryEntriesMap[dateKey] = {
|
||
|
'percentValue': entry.percentValue,
|
||
|
'texts': entry.texts,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
await prefs.setString(_keyDiaryEntries, json.encode(diaryEntriesMap));
|
||
|
}
|
||
|
|
||
|
// Load diary entries
|
||
|
Future<List<DiaryEntry>> loadDiaryEntries() async {
|
||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||
|
final String diaryEntriesJson = prefs.getString(_keyDiaryEntries) ?? '{}';
|
||
|
final Map<String, dynamic> diaryEntriesMap = json.decode(diaryEntriesJson);
|
||
|
|
||
|
return diaryEntriesMap.entries.map((entry) {
|
||
|
final List<String> texts = List<String>.from(entry.value['texts']);
|
||
|
return DiaryEntry(
|
||
|
date: DateTime.parse(entry.key),
|
||
|
percentValue: entry.value['percentValue'],
|
||
|
texts: texts,
|
||
|
);
|
||
|
}).toList();
|
||
|
}
|
||
|
|
||
|
// Method to calculate the streak of daily diary entries
|
||
|
|
||
|
Future<int> calculateStreak() async {
|
||
|
final allEntries = await loadDiaryEntries();
|
||
|
// Sort the entries by date in descending order
|
||
|
allEntries.sort((a, b) => b.date.compareTo(a.date));
|
||
|
|
||
|
int streakCount = 0;
|
||
|
DateTime currentDate = DateTime.now();
|
||
|
// Use a set to store the dates for faster lookup
|
||
|
Set<String> entryDates = allEntries.map((entry) => DateFormat('yyyy-MM-dd').format(entry.date)).toSet();
|
||
|
|
||
|
// Check for today's entry first
|
||
|
if (!entryDates.contains(DateFormat('yyyy-MM-dd').format(currentDate))) {
|
||
|
return 0; // If today's entry is missing, streak is broken
|
||
|
}
|
||
|
|
||
|
while (entryDates.contains(DateFormat('yyyy-MM-dd').format(currentDate))) {
|
||
|
streakCount++;
|
||
|
currentDate = currentDate.subtract(const Duration(days: 1)); // Move to the previous day
|
||
|
}
|
||
|
|
||
|
return streakCount;
|
||
|
}
|
||
|
|
||
|
// Set PIN method
|
||
|
Future<void> setPin(int pin) async {
|
||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||
|
await prefs.setInt(_keyPin, pin);
|
||
|
await prefs.setBool(_keyPinEnabled, true); // Automatically enable PIN on setting
|
||
|
}
|
||
|
|
||
|
// Check PIN method
|
||
|
Future<bool> checkPin(int pin) async {
|
||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||
|
int savedPin = prefs.getInt(_keyPin) ?? -1; // Default to -1 if not set
|
||
|
return savedPin == pin;
|
||
|
}
|
||
|
|
||
|
// Check if PIN is enabled
|
||
|
Future<bool> isPinEnabled() async {
|
||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||
|
return prefs.getBool(_keyPinEnabled) ?? false; // Return false if not set
|
||
|
}
|
||
|
|
||
|
// Enable PIN
|
||
|
Future<void> enablePin() async {
|
||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||
|
if (prefs.getInt(_keyPin) != null) {
|
||
|
// Ensure PIN exists before enabling
|
||
|
await prefs.setBool(_keyPinEnabled, true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Disable PIN
|
||
|
Future<void> disablePin() async {
|
||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||
|
await prefs.setBool(_keyPinEnabled, false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Helper class to store color preferences
|
||
|
class ColorPreference {
|
||
|
final Color? color1;
|
||
|
final Color? color2;
|
||
|
|
||
|
ColorPreference({this.color1, this.color2});
|
||
|
}
|
||
|
|
||
|
// Diary entry data model
|
||
|
class DiaryEntry {
|
||
|
final DateTime date;
|
||
|
final int percentValue;
|
||
|
final List<String> texts;
|
||
|
|
||
|
DiaryEntry({
|
||
|
required this.date,
|
||
|
required this.percentValue,
|
||
|
required this.texts,
|
||
|
});
|
||
|
}
|