chore: init repository with project sources
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import '../../../core/status.dart';
|
||||
|
||||
class EpisodeItem {
|
||||
final int id;
|
||||
final int episodeNumber;
|
||||
final int seasonNumber;
|
||||
final String showName;
|
||||
final String? name;
|
||||
final ItemStatus status;
|
||||
final String? resolution;
|
||||
final int? firstAirYear;
|
||||
final String? showJson;
|
||||
final String? showStatus;
|
||||
final bool? showCliffhanger;
|
||||
final String? posterPath;
|
||||
|
||||
EpisodeItem({
|
||||
required this.id,
|
||||
required this.episodeNumber,
|
||||
required this.seasonNumber,
|
||||
required this.showName,
|
||||
this.name,
|
||||
required this.status,
|
||||
this.resolution,
|
||||
this.firstAirYear,
|
||||
this.showJson,
|
||||
this.showStatus,
|
||||
this.showCliffhanger,
|
||||
this.posterPath,
|
||||
});
|
||||
|
||||
factory EpisodeItem.fromJson(Map<String, dynamic> j) => EpisodeItem(
|
||||
id: j['id'] as int,
|
||||
episodeNumber: j['episode_number'] as int,
|
||||
seasonNumber: j['season_number'] as int,
|
||||
showName: j['show_name'] as String,
|
||||
name: j['name'] as String?,
|
||||
status: statusFromString(j['status'] as String?),
|
||||
resolution: j['resolution'] as String?,
|
||||
firstAirYear: j['first_air_year'] as int?,
|
||||
showJson: j['show_json'] as String?,
|
||||
showStatus: j['show_status'] as String?,
|
||||
showCliffhanger: _parseBool(j['show_cliffhanger']),
|
||||
posterPath: j['poster_path'] as String?,
|
||||
);
|
||||
|
||||
static bool? _parseBool(dynamic v) {
|
||||
if (v == null) return null;
|
||||
if (v is bool) return v;
|
||||
if (v is num) return v != 0;
|
||||
if (v is String) {
|
||||
final s = v.toLowerCase();
|
||||
return s == '1' || s == 'true' || s == 'yes';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../../shared/providers.dart';
|
||||
import '../../../core/status.dart';
|
||||
import 'episode_model.dart';
|
||||
|
||||
final episodeFilterProvider = StateProvider<ItemStatus?>((_) => null);
|
||||
|
||||
final seriesGroupedProvider =
|
||||
FutureProvider.autoDispose<SeriesGroupedData>((ref) async {
|
||||
final backend = ref.watch(backendApiProvider);
|
||||
final st = ref.watch(episodeFilterProvider);
|
||||
final rows = await backend.getEpisodes(status: st?.name, limit: 5000);
|
||||
final items = rows
|
||||
.map(EpisodeItem.fromJson)
|
||||
.where((e) => e.seasonNumber > 0)
|
||||
.toList();
|
||||
return SeriesGroupedData.fromEpisodes(items);
|
||||
});
|
||||
|
||||
class SeriesGroupedData {
|
||||
final Map<String, Map<int, List<EpisodeItem>>>
|
||||
data; // showName -> season -> episodes
|
||||
SeriesGroupedData(this.data);
|
||||
|
||||
factory SeriesGroupedData.fromEpisodes(List<EpisodeItem> items) {
|
||||
final map = <String, Map<int, List<EpisodeItem>>>{};
|
||||
for (final e in items) {
|
||||
final bySeason =
|
||||
map.putIfAbsent(e.showName, () => <int, List<EpisodeItem>>{});
|
||||
final list = bySeason.putIfAbsent(e.seasonNumber, () => <EpisodeItem>[]);
|
||||
list.add(e);
|
||||
}
|
||||
for (final bySeason in map.values) {
|
||||
for (final eps in bySeason.values) {
|
||||
eps.sort((a, b) => a.episodeNumber.compareTo(b.episodeNumber));
|
||||
}
|
||||
}
|
||||
return SeriesGroupedData(map);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user