71 lines
1.8 KiB
Dart
71 lines
1.8 KiB
Dart
// Author: fruit.com.cn
|
|
|
|
import 'dart:async';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
import '../../core/data/models/watch_progress.dart';
|
|
import '../../core/data/repositories/watch_history_repository.dart';
|
|
|
|
/// Home browse channel, backed only by data already present in the catalogue.
|
|
enum HomeChannel { hot, free, newReleases, ranking }
|
|
|
|
/// Local UI state for the browse-first home page.
|
|
class HomeBrowseLogic extends ChangeNotifier {
|
|
HomeBrowseLogic({required this.history}) {
|
|
unawaited(refreshRecent());
|
|
}
|
|
|
|
static const int recentLimit = 20;
|
|
|
|
final WatchHistoryRepository history;
|
|
HomeChannel channel = HomeChannel.hot;
|
|
List<WatchProgress> recent = const [];
|
|
bool loadingRecent = false;
|
|
bool _disposed = false;
|
|
|
|
/// First unfinished record with a real position.
|
|
WatchProgress? get primaryRecord {
|
|
for (final record in recent) {
|
|
if (!record.finished && record.hasPosition) return record;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// Changes the selected browse channel without triggering network work.
|
|
void selectChannel(HomeChannel value) {
|
|
if (channel == value) return;
|
|
channel = value;
|
|
_notify();
|
|
}
|
|
|
|
/// Reloads continuation data; signed-out reads simply return an empty list.
|
|
Future<void> refreshRecent() async {
|
|
loadingRecent = true;
|
|
_notify();
|
|
try {
|
|
recent = await history.recent(limit: recentLimit);
|
|
} catch (_) {
|
|
recent = const [];
|
|
} finally {
|
|
loadingRecent = false;
|
|
_notify();
|
|
}
|
|
}
|
|
|
|
/// Refreshes continuation data when the home tab becomes visible again.
|
|
void syncPage({required bool active, required bool wasActive}) {
|
|
if (active && !wasActive) unawaited(refreshRecent());
|
|
}
|
|
|
|
void _notify() {
|
|
if (!_disposed) notifyListeners();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_disposed = true;
|
|
super.dispose();
|
|
}
|
|
}
|