import 'dart:convert'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:http/http.dart' as http; import 'package:hive_flutter/hive_flutter.dart'; /// Service for fetching Islamic-themed photos from Unsplash. /// Implements aggressive caching to minimize API usage (1 request/day). class UnsplashService { static const String _baseUrl = 'https://api.unsplash.com'; static const String _cacheBoxName = 'unsplash_cache'; static const String _cacheKey = 'cached_photo'; static const String _cacheTimestampKey = 'cached_timestamp'; static const Duration _cacheTTL = Duration(hours: 24); static final UnsplashService instance = UnsplashService._(); UnsplashService._(); // In-memory cache for the current session Map? _memoryCache; /// Get a cached or fresh Islamic photo. /// Returns a map with keys: 'imageUrl', 'photographerName', 'photographerUrl', 'unsplashUrl' Future?> getIslamicPhoto() async { // 1. Check memory cache if (_memoryCache != null) return _memoryCache; // 2. Check Hive cache final box = await Hive.openBox(_cacheBoxName); final cachedData = box.get(_cacheKey); final cachedTimestamp = box.get(_cacheTimestampKey); if (cachedData != null && cachedTimestamp != null) { final cachedTime = DateTime.fromMillisecondsSinceEpoch(cachedTimestamp); if (DateTime.now().difference(cachedTime) < _cacheTTL) { _memoryCache = Map.from(json.decode(cachedData)); return _memoryCache; } } // 3. Fetch from API final photo = await _fetchFromApi(); if (photo != null) { // Cache in Hive await box.put(_cacheKey, json.encode(photo)); await box.put(_cacheTimestampKey, DateTime.now().millisecondsSinceEpoch); _memoryCache = photo; } return photo; } Future?> _fetchFromApi() async { final accessKey = dotenv.env['UNSPLASH_ACCESS_KEY']; if (accessKey == null || accessKey.isEmpty || accessKey == 'YOUR_ACCESS_KEY_HERE') { return null; } try { final queries = ['masjid', 'kaabah', 'mosque', 'islamic architecture']; // Rotate query based on the day of year for variety final dayOfYear = DateTime.now().difference(DateTime(DateTime.now().year, 1, 1)).inDays; final query = queries[dayOfYear % queries.length]; final response = await http.get( Uri.parse('$_baseUrl/photos/random?query=$query&orientation=portrait&content_filter=high'), headers: {'Authorization': 'Client-ID $accessKey'}, ); if (response.statusCode == 200) { final data = json.decode(response.body); return { 'imageUrl': data['urls']?['regular'] ?? '', 'photographerName': data['user']?['name'] ?? 'Unknown', 'photographerUrl': data['user']?['links']?['html'] ?? '', 'unsplashUrl': data['links']?['html'] ?? '', }; } } catch (e) { // Silent fallback — show the equalizer without background } return null; } }