Schedule: On Jellyfin only when the episode itself is there; Aired · not on Jellyfin yet otherwise
For shows AnimeFlow doesn't track, the app now looks the episode up in the
linked Jellyfin (one /Shows/{id}/Episodes per series, 3 min memo; TVDB
number via anilist_map offsets). No linked account: a neutral Aired.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cc45b86271
commit
884f208330
7 files changed
+197
-18
No files matched your search
@@ -80,6 +80,36 @@ void main() {
|
||||
expect(out.single.season, 6);
|
||||
});
|
||||
|
||||
test('confirmOnJellyfin: the episode (with the run offset) must be on Jellyfin', () {
|
||||
final lib = AnimeFlowLibraryItem.fromJson({
|
||||
'jellyfin_series_id': 'jfJ',
|
||||
'name': 'JoJo',
|
||||
'anilist_map': [
|
||||
{'season': 6, 'anilist_id': 210482, 'first_episode': 13, 'offset': 12},
|
||||
],
|
||||
});
|
||||
final matched = matchSchedule(
|
||||
[
|
||||
airing(210482, 1, DateTime(2026, 10, 1, 18)), // S6E13: there
|
||||
airing(210482, 2, DateTime(2026, 10, 8, 11)), // S6E14: not yet
|
||||
airing(172192, 3, DateTime(2026, 10, 6, 18)), // series not looked up
|
||||
],
|
||||
schedule: const [],
|
||||
library: [
|
||||
lib,
|
||||
const AnimeFlowLibraryItem(jellyfinSeriesId: 'jfR', name: 'Returner', anilistIds: {2: 172192}),
|
||||
],
|
||||
now: now,
|
||||
);
|
||||
expect(matched.map((e) => e.jellyfinEpisode), [13, 14, 3]);
|
||||
final out = confirmOnJellyfin(matched, {
|
||||
'jfJ': {(6, 12), (6, 13), (1, 14)},
|
||||
});
|
||||
expect(out.map((e) => e.status),
|
||||
[ScheduleStatus.inLibrary, ScheduleStatus.notOnJellyfin, ScheduleStatus.aired]);
|
||||
expect(out[1].jellyfinSeriesId, 'jfJ');
|
||||
});
|
||||
|
||||
test("AnimeFlow's anilist_episode wins over TVDB numbering (split cour)", () {
|
||||
// S2E13 in TVDB is part 2 (AniList 300) episode 1.
|
||||
final out = matchSchedule(
|
||||
|
||||
@@ -8,6 +8,7 @@ import 'package:watch_together/src/jellyfin/accounts.dart';
|
||||
import 'package:watch_together/src/schedule/anilist.dart';
|
||||
import 'package:watch_together/src/schedule/animeflow.dart';
|
||||
import 'package:watch_together/src/schedule/schedule_model.dart';
|
||||
import 'package:watch_together/src/schedule/ui/schedule_actions.dart';
|
||||
import 'package:watch_together/src/schedule/ui/schedule_page.dart';
|
||||
import 'package:watch_together/src/screens/home/picked_media.dart';
|
||||
|
||||
@@ -434,6 +435,51 @@ void main() {
|
||||
await done(tester);
|
||||
});
|
||||
|
||||
testWidgets('untracked on Jellyfin: episode lookup, aired-not-there has no Play', (tester) async {
|
||||
final jf = FakeJf();
|
||||
final accounts = JellyfinAccounts(
|
||||
store: MemoryJellyfinStore({
|
||||
'accounts': jsonEncode([
|
||||
{
|
||||
'serverId': 'srv',
|
||||
'serverName': 'Home',
|
||||
'urls': ['http://jf.test'],
|
||||
'userId': 'uid',
|
||||
'userName': 'me',
|
||||
'token': 'tok',
|
||||
},
|
||||
]),
|
||||
}),
|
||||
httpFactory: () => jf,
|
||||
deviceName: 'Test',
|
||||
);
|
||||
final eps = await tester.runAsync(() => jellyfinEpisodeNumbers(accounts, flow, 'jf7'));
|
||||
expect(eps, {(1, 2), (1, 3)});
|
||||
await tester.runAsync(() => jellyfinEpisodeNumbers(accounts, flow, 'jf7'));
|
||||
expect(jf.seen.where((u) => u.path.endsWith('/Episodes')), hasLength(1), reason: 'memoised');
|
||||
final none = JellyfinAccounts(store: MemoryJellyfinStore(), deviceName: 'Test');
|
||||
expect(await tester.runAsync(() => jellyfinEpisodeNumbers(none, flow, 'jf7')), isNull);
|
||||
|
||||
await pumpPage(
|
||||
tester,
|
||||
snap: () => snapshot(
|
||||
list: [
|
||||
ScheduleEntry(
|
||||
airing: airing(777, 'Clover', 2, day(0, 9)),
|
||||
status: ScheduleStatus.notOnJellyfin,
|
||||
season: 1,
|
||||
jellyfinEpisode: 2,
|
||||
jellyfinSeriesId: 'jfC',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
expect(card(777, 2), findsOneWidget);
|
||||
expect(find.text('aired · not on Jellyfin yet'), findsOneWidget);
|
||||
expect(action(777, 2), findsNothing);
|
||||
await done(tester);
|
||||
});
|
||||
|
||||
testWidgets('solo: the button says Play and works', (tester) async {
|
||||
await pumpPage(tester, solo: true);
|
||||
expect(find.text('Put it up'), findsNothing);
|
||||
|
||||
Reference in new issue
Block a user