107 lines
3.2 KiB
Dart
107 lines
3.2 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
|
|
|
import '../models/app_settings.dart';
|
|
import 'supabase_provider.dart';
|
|
|
|
/// Fetches the Ramadan configuration from app_settings.
|
|
final ramadanConfigProvider = FutureProvider<RamadanConfig>((ref) async {
|
|
final client = ref.watch(supabaseClientProvider);
|
|
final data = await client
|
|
.from('app_settings')
|
|
.select()
|
|
.eq('key', 'ramadan_mode')
|
|
.maybeSingle();
|
|
if (data == null) return RamadanConfig(enabled: false, autoDetect: true);
|
|
final setting = AppSetting.fromMap(data);
|
|
return RamadanConfig.fromJson(setting.value);
|
|
});
|
|
|
|
/// Whether Ramadan mode is currently active.
|
|
/// Combines manual toggle with auto-detection via Hijri calendar approximation.
|
|
final isRamadanActiveProvider = Provider<bool>((ref) {
|
|
final config = ref.watch(ramadanConfigProvider).valueOrNull;
|
|
if (config == null) return false;
|
|
|
|
// Manual override takes priority
|
|
if (config.enabled) return true;
|
|
|
|
// Auto-detect based on approximate Hijri calendar
|
|
if (config.autoDetect) {
|
|
return isApproximateRamadan(DateTime.now());
|
|
}
|
|
|
|
return false;
|
|
});
|
|
|
|
/// Approximate Ramadan detection using a simplified Hijri calendar calculation.
|
|
/// Ramadan moves ~11 days earlier each Gregorian year.
|
|
/// This provides a reasonable approximation; for exact dates, a Hijri calendar
|
|
/// package could be used.
|
|
bool isApproximateRamadan(DateTime now) {
|
|
// Known Ramadan start dates (approximate):
|
|
// 2025: Feb 28 - Mar 30
|
|
// 2026: Feb 17 - Mar 19
|
|
// 2027: Feb 7 - Mar 8
|
|
// 2028: Jan 27 - Feb 25
|
|
final ramadanWindows = {
|
|
2025: (start: DateTime(2025, 2, 28), end: DateTime(2025, 3, 30)),
|
|
2026: (start: DateTime(2026, 2, 17), end: DateTime(2026, 3, 19)),
|
|
2027: (start: DateTime(2027, 2, 7), end: DateTime(2027, 3, 8)),
|
|
2028: (start: DateTime(2028, 1, 27), end: DateTime(2028, 2, 25)),
|
|
};
|
|
|
|
final window = ramadanWindows[now.year];
|
|
if (window != null) {
|
|
return !now.isBefore(window.start) && !now.isAfter(window.end);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
final ramadanControllerProvider = Provider<RamadanController>((ref) {
|
|
final client = ref.watch(supabaseClientProvider);
|
|
return RamadanController(client);
|
|
});
|
|
|
|
class RamadanController {
|
|
RamadanController(this._client);
|
|
|
|
final SupabaseClient _client;
|
|
|
|
Future<void> setEnabled(bool enabled) async {
|
|
final current = await _client
|
|
.from('app_settings')
|
|
.select()
|
|
.eq('key', 'ramadan_mode')
|
|
.maybeSingle();
|
|
|
|
final value = current != null
|
|
? Map<String, dynamic>.from(current['value'] as Map)
|
|
: <String, dynamic>{'auto_detect': true};
|
|
value['enabled'] = enabled;
|
|
|
|
await _client.from('app_settings').upsert({
|
|
'key': 'ramadan_mode',
|
|
'value': value,
|
|
});
|
|
}
|
|
|
|
Future<void> setAutoDetect(bool autoDetect) async {
|
|
final current = await _client
|
|
.from('app_settings')
|
|
.select()
|
|
.eq('key', 'ramadan_mode')
|
|
.maybeSingle();
|
|
|
|
final value = current != null
|
|
? Map<String, dynamic>.from(current['value'] as Map)
|
|
: <String, dynamic>{'enabled': false};
|
|
value['auto_detect'] = autoDetect;
|
|
|
|
await _client.from('app_settings').upsert({
|
|
'key': 'ramadan_mode',
|
|
'value': value,
|
|
});
|
|
}
|
|
}
|