import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../data/services/unsplash_service.dart'; import '../../providers.dart'; /// Renders a securely rotating background using Unsplash API. class UnsplashBackground extends ConsumerStatefulWidget { const UnsplashBackground({super.key}); @override ConsumerState createState() => _UnsplashBackgroundState(); } class _UnsplashBackgroundState extends ConsumerState { List _urls = []; int _currentIndex = 0; Timer? _rotationTimer; String? _lastKeyword; int? _lastRotationHours; @override void initState() { super.initState(); _initDataAndTimer(); } void _initDataAndTimer() async { final settings = ref.read(settingsProvider); _lastKeyword = settings.unsplashKeyword; _lastRotationHours = settings.unsplashRotationHours; await _fetchImages(settings.unsplashKeyword); _startTimer(settings.unsplashRotationHours); } Future _fetchImages(String keyword) async { final urls = await UnsplashService.instance.fetchLandscapeBackgrounds(keyword); if (urls.isNotEmpty && mounted) { setState(() { _urls = urls; _currentIndex = 0; }); } } void _startTimer(int hours) { _rotationTimer?.cancel(); if (hours <= 0) return; _rotationTimer = Timer.periodic(Duration(hours: hours), (_) { if (_urls.isNotEmpty && mounted) { setState(() { _currentIndex = (_currentIndex + 1) % _urls.length; }); } }); } @override void dispose() { _rotationTimer?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { final settings = ref.watch(settingsProvider); // Watch for config changes if (settings.unsplashKeyword != _lastKeyword) { _lastKeyword = settings.unsplashKeyword; // Re-fetch images organically _fetchImages(settings.unsplashKeyword); } if (settings.unsplashRotationHours != _lastRotationHours) { _lastRotationHours = settings.unsplashRotationHours; _startTimer(settings.unsplashRotationHours); } if (!settings.useUnsplashBackground || _urls.isEmpty) { return const SizedBox.shrink(); // Fallback to flat background handled underneath } return AnimatedSwitcher( duration: const Duration(seconds: 3), transitionBuilder: (child, animation) => FadeTransition(opacity: animation, child: child), child: Image.network( _urls[_currentIndex], key: ValueKey(_urls[_currentIndex]), fit: BoxFit.cover, width: double.infinity, height: double.infinity, // Soft opacity behind the MainScreen's dark glass vignette color: Colors.black.withValues(alpha: 0.5), colorBlendMode: BlendMode.darken, ), ); } }