static const String _longestStreakKey = 'longest_login_streak';
static Future updateLoginStreak() async {
final prefs = await SharedPreferences.getInstance();
final now = DateTime.now().toUtc(); // or DateTime.now() for local
final today = DateTime(now.year, now.month, now.day);
final lastLoginMillis = prefs.getInt(_lastLoginKey);
final currentStreak = prefs.getInt(_streakKey) ?? 0;
var longestStreak = prefs.getInt(_longestStreakKey) ?? 0;
DateTime? lastDate;
if (lastLoginMillis != null) {
lastDate = DateTime.fromMillisecondsSinceEpoch(lastLoginMillis, isUtc: true);
lastDate = DateTime(lastDate.year, lastDate.month, lastDate.day);
}
int newStreak;
if (lastDate == null) {
newStreak = 1;
} else if (today.difference(lastDate).inDays == 0) {
newStreak = currentStreak;
} else if (today.difference(lastDate).inDays == 1) {
newStreak = currentStreak + 1;
} else {
newStreak = 1;
}
if (newStreak > longestStreak) {
longestStreak = newStreak;
await prefs.setInt(_longestStreakKey, longestStreak);
}
await prefs.setInt(_lastLoginKey, today.millisecondsSinceEpoch);
await prefs.setInt(_streakKey, newStreak);
return newStreak;
}
static Future getLongestStreak() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getInt(_longestStreakKey) ?? 0;
}
Core Concepts
The streak logic relies on comparing the current login date with the last recorded login date.
Same Day: If the current login is on the same calendar day as the last one, the streak counter remains unchanged.
Consecutive Day: If the current login is exactly one day after the last one, the streak counter is incremented, and the last login date is updated.
Broken Streak: If more than a day has passed since the last login, the streak is broken, and the counter is reset to 1.
First Login: If there is no previous login record, the streak is initialized to 1, and the current date is saved.
And calculate the longest day streak