Files
FocusBuddy/lib/services/encouragement_service.dart
ytc1012 0195cdf54b 优化
2025-11-26 16:32:47 +08:00

156 lines
5.5 KiB
Dart

import 'dart:convert';
import 'dart:math';
import 'package:flutter/services.dart';
/// Enum representing different encouragement message types
enum EncouragementType {
general, // General encouragement messages
start, // When starting a focus session
distraction, // When user gets distracted
complete, // When completing a focus session
earlyStop, // When stopping early
}
/// Service to manage encouragement messages for different scenarios
class EncouragementService {
// Map of encouragement types to their messages
final Map<EncouragementType, List<String>> _messages = {
EncouragementType.general: [],
EncouragementType.start: [],
EncouragementType.distraction: [],
EncouragementType.complete: [],
EncouragementType.earlyStop: [],
};
final Random _random = Random();
/// Load encouragement messages from assets
Future<void> loadMessages() async {
try {
final String jsonString =
await rootBundle.loadString('assets/encouragements.json');
final dynamic jsonData = json.decode(jsonString);
// Check if the JSON is a map (new format with categories)
if (jsonData is Map<String, dynamic>) {
// Load categorized messages
_loadCategorizedMessages(jsonData);
} else if (jsonData is List<dynamic>) {
// Load legacy format (list of general messages)
_messages[EncouragementType.general] = jsonData.cast<String>();
// Initialize other categories with default messages
_initializeDefaultMessages();
} else {
// Invalid format, use defaults
_initializeDefaultMessages();
}
} catch (e) {
// Fallback to default messages if file can't be loaded
_initializeDefaultMessages();
}
}
/// Load categorized messages from JSON map
void _loadCategorizedMessages(Map<String, dynamic> jsonData) {
// Load general messages
if (jsonData.containsKey('general') && jsonData['general'] is List) {
_messages[EncouragementType.general] = (jsonData['general'] as List).cast<String>();
}
// Load start messages
if (jsonData.containsKey('start') && jsonData['start'] is List) {
_messages[EncouragementType.start] = (jsonData['start'] as List).cast<String>();
}
// Load distraction messages
if (jsonData.containsKey('distraction') && jsonData['distraction'] is List) {
_messages[EncouragementType.distraction] = (jsonData['distraction'] as List).cast<String>();
}
// Load complete messages
if (jsonData.containsKey('complete') && jsonData['complete'] is List) {
_messages[EncouragementType.complete] = (jsonData['complete'] as List).cast<String>();
}
// Load early stop messages
if (jsonData.containsKey('earlyStop') && jsonData['earlyStop'] is List) {
_messages[EncouragementType.earlyStop] = (jsonData['earlyStop'] as List).cast<String>();
}
// Ensure all categories have at least some messages
_ensureAllCategoriesHaveMessages();
}
/// Initialize default messages for all categories
void _initializeDefaultMessages() {
_messages[EncouragementType.general] = [
"Showing up is half the battle.",
"Every minute counts.",
"You're learning, not failing.",
"Gentleness is strength.",
"Progress over perfection.",
];
_messages[EncouragementType.start] = [
"You've got this! Let's begin.",
"Ready to focus? Let's do this.",
"Every moment is a fresh start.",
"Let's make this session count.",
"You're already making progress by showing up.",
];
_messages[EncouragementType.distraction] = [
"It's okay to get distracted. Let's gently come back.",
"No guilt here! Let's try again.",
"Distractions happen to everyone. Let's refocus.",
"You're doing great by noticing and coming back.",
"Gentle reminder: you can always start again.",
];
_messages[EncouragementType.complete] = [
"🎉 Congratulations! You did it!",
"Great job completing your focus session!",
"You should be proud of yourself!",
"That was amazing! Well done.",
"You're making wonderful progress!",
];
_messages[EncouragementType.earlyStop] = [
"It's okay to stop early. You tried, and that's what matters.",
"Every effort counts, even if it's shorter than planned.",
"You did your best, and that's enough.",
"Rest when you need to. We'll be here when you're ready.",
"Progress, not perfection. You're doing great.",
];
}
/// Ensure all categories have at least some messages
void _ensureAllCategoriesHaveMessages() {
// If any category is empty, use general messages as fallback
for (final type in EncouragementType.values) {
if (_messages[type]?.isEmpty ?? true) {
_messages[type] = List.from(_messages[EncouragementType.general]!);
}
}
}
/// Get a random encouragement message for a specific type
String getRandomMessage([EncouragementType type = EncouragementType.general]) {
final messages = _messages[type] ?? [];
if (messages.isEmpty) {
return "You're doing great!";
}
return messages[_random.nextInt(messages.length)];
}
/// Get all messages for a specific type (for testing)
List<String> getAllMessages([EncouragementType type = EncouragementType.general]) {
return List.from(_messages[type] ?? []);
}
/// Get all messages for all types (for testing)
Map<EncouragementType, List<String>> getAllMessagesByType() {
return Map.from(_messages);
}
}