Files
ReelShort/lib/pages/discover/ranking_logic.dart
T

77 lines
2.2 KiB
Dart

// Author: fruit.com.cn
import 'package:flutter/foundation.dart';
import '../../core/data/models/drama.dart';
import '../../core/data/models/home_feed.dart';
/// Ranking boards backed by the feed sections the server already returns.
enum RankingBoard { hot, newReleases }
/// One ranked title; rank is one-based and mirrors server section order.
class RankingEntry {
const RankingEntry({required this.rank, required this.drama});
final int rank;
final Drama drama;
}
/// Keeps the active board and turns real feed sections into ranked entries.
///
/// The backend does not expose a dedicated ranking endpoint, so this class
/// never invents scores: it preserves the order of the `hot` and `new`
/// sections and only falls back to the catalog when a section is absent.
class RankingLogic extends ChangeNotifier {
RankingLogic({required this.sections, required this.fallback});
static const hotSectionCode = 'hot';
static const newSectionCode = 'new';
List<FeedSection> sections;
List<Drama> fallback;
RankingBoard _board = RankingBoard.hot;
RankingBoard get board => _board;
List<RankingEntry> get entries {
final sectionCode = _board == RankingBoard.hot
? hotSectionCode
: newSectionCode;
final source = _sectionDramas(sectionCode);
final dramas = source.isEmpty ? fallback : source;
final seen = <String>{};
final unique = [
for (final drama in dramas)
if (seen.add(drama.id)) drama,
];
return [
for (var index = 0; index < unique.length; index++)
RankingEntry(rank: index + 1, drama: unique[index]),
];
}
/// Switches boards and notifies only when the visible source changes.
void select(RankingBoard next) {
if (_board == next) return;
_board = next;
notifyListeners();
}
/// Applies refreshed feed data without rebuilding the page state.
void updateSources({
required List<FeedSection> sections,
required List<Drama> fallback,
}) {
this.sections = sections;
this.fallback = fallback;
notifyListeners();
}
List<Drama> _sectionDramas(String code) {
for (final section in sections) {
if (section.code == code) return section.dramas;
}
return const [];
}
}