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> _messages = { EncouragementType.general: [], EncouragementType.start: [], EncouragementType.distraction: [], EncouragementType.complete: [], EncouragementType.earlyStop: [], }; final Random _random = Random(); /// Load encouragement messages from assets Future 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) { // Load categorized messages _loadCategorizedMessages(jsonData); } else if (jsonData is List) { // Load legacy format (list of general messages) _messages[EncouragementType.general] = jsonData.cast(); // 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 jsonData) { // Load general messages if (jsonData.containsKey('general') && jsonData['general'] is List) { _messages[EncouragementType.general] = (jsonData['general'] as List).cast(); } // Load start messages if (jsonData.containsKey('start') && jsonData['start'] is List) { _messages[EncouragementType.start] = (jsonData['start'] as List).cast(); } // Load distraction messages if (jsonData.containsKey('distraction') && jsonData['distraction'] is List) { _messages[EncouragementType.distraction] = (jsonData['distraction'] as List).cast(); } // Load complete messages if (jsonData.containsKey('complete') && jsonData['complete'] is List) { _messages[EncouragementType.complete] = (jsonData['complete'] as List).cast(); } // Load early stop messages if (jsonData.containsKey('earlyStop') && jsonData['earlyStop'] is List) { _messages[EncouragementType.earlyStop] = (jsonData['earlyStop'] as List).cast(); } // 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 getAllMessages([EncouragementType type = EncouragementType.general]) { return List.from(_messages[type] ?? []); } /// Get all messages for all types (for testing) Map> getAllMessagesByType() { return Map.from(_messages); } }