Files
Tracker/lib/providers/scripture_provider.dart

128 lines
3.9 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/scripture.dart';
import '../models/cycle_entry.dart';
// For IterableExtension
// State for ScriptureProvider
class ScriptureState {
final Scripture? currentScripture;
final CyclePhase? currentPhase;
final int currentIndex; // Index within the phase-specific list
final int? maxIndex; // Max number of scriptures for the current phase
ScriptureState({
this.currentScripture,
this.currentPhase,
this.currentIndex = 0,
this.maxIndex,
});
ScriptureState copyWith({
Scripture? currentScripture,
CyclePhase? currentPhase,
int? currentIndex,
int? maxIndex,
}) {
return ScriptureState(
currentScripture: currentScripture ?? this.currentScripture,
currentPhase: currentPhase ?? this.currentPhase,
currentIndex: currentIndex ?? this.currentIndex,
maxIndex: maxIndex ?? this.maxIndex,
);
}
}
// StateNotifier for ScriptureProvider
class ScriptureNotifier extends StateNotifier<ScriptureState> {
final ScriptureDatabase _scriptureDatabase;
ScriptureNotifier(this._scriptureDatabase) : super(ScriptureState()) {
// We don't initialize here directly, as we need the phase from other providers.
// Initialization will be triggered by the UI.
}
// Initialize/refresh scripture for a given phase
// This should be called by the consuming widget when the phase changes or on initial load.
Future<void> initializeScripture(CyclePhase phase) async {
// Only re-initialize if the phase has changed or no scripture is currently set
if (state.currentPhase != phase || state.currentScripture == null) {
final scriptureCount =
_scriptureDatabase.getScriptureCountForPhase(phase.name);
if (scriptureCount > 0) {
// Use day of year to get a stable initial scripture for the day
final dayOfYear = DateTime.now()
.difference(DateTime(DateTime.now().year, 1, 1))
.inDays;
final initialIndex = dayOfYear % scriptureCount;
state = state.copyWith(
currentPhase: phase,
currentIndex: initialIndex,
maxIndex: scriptureCount,
currentScripture: _scriptureDatabase.getScriptureForPhaseByIndex(
phase.name, initialIndex),
);
} else {
state = state.copyWith(
currentPhase: phase,
currentScripture: null,
currentIndex: 0,
maxIndex: 0,
);
}
}
}
void getNextScripture() {
if (state.currentPhase == null ||
state.maxIndex == null ||
state.maxIndex == 0) {
return;
}
final nextIndex = (state.currentIndex + 1) % state.maxIndex!;
_updateScripture(nextIndex);
}
void getPreviousScripture() {
if (state.currentPhase == null ||
state.maxIndex == null ||
state.maxIndex == 0) {
return;
}
final prevIndex =
(state.currentIndex - 1 + state.maxIndex!) % state.maxIndex!;
_updateScripture(prevIndex);
}
void getRandomScripture() {
if (state.currentPhase == null ||
state.maxIndex == null ||
state.maxIndex == 0) {
return;
}
// Use a proper random number generator for better randomness
final randomIndex = DateTime.now().microsecondsSinceEpoch %
state.maxIndex!; // Still using timestamp for simplicity
_updateScripture(randomIndex);
}
void _updateScripture(int newIndex) {
if (state.currentPhase == null) return;
final newScripture = _scriptureDatabase.getScriptureForPhaseByIndex(
state.currentPhase!.name, newIndex);
state = state.copyWith(
currentIndex: newIndex,
currentScripture: newScripture,
);
}
}
final scriptureDatabaseProvider = Provider((ref) => ScriptureDatabase());
final scriptureProvider =
StateNotifierProvider<ScriptureNotifier, ScriptureState>((ref) {
return ScriptureNotifier(ref.watch(scriptureDatabaseProvider));
});