Project import generated by Copybara.
Some checks are pending
Build and Deploy / build_windows (push) Waiting to run
Build and Deploy / build_android (push) Waiting to run
Build and Deploy / build_ipa (push) Waiting to run
Build and Deploy / build_linux (push) Waiting to run
Build and Deploy / build_macos (push) Waiting to run

GitOrigin-RevId: f2ddaed960bf57cab7cbe40fba212aa80c43571d
This commit is contained in:
Madari Developers 2025-01-08 08:45:54 +00:00
parent a297699b6c
commit 43e84608a0
4 changed files with 150 additions and 115 deletions

View file

@ -74,7 +74,7 @@ class StremioConnectionService extends BaseConnectionService {
final result = await http.get( final result = await http.get(
Uri.parse( Uri.parse(
"${_getAddonBaseURL(addon)}/meta/${(id as Meta).type}/${id.id}.json", "${_getAddonBaseURL(addon)}/meta/${id.type}/${id.id}.json",
), ),
); );
@ -341,7 +341,7 @@ class StremioConnectionService extends BaseConnectionService {
} }
final url = final url =
"${_getAddonBaseURL(addon)}/stream/${meta.type}/${Uri.encodeComponent(id.id)}.json"; "${_getAddonBaseURL(addon)}/stream/${meta.type}/${Uri.encodeComponent(id.currentVideo?.id ?? id.id)}.json";
final result = await Query( final result = await Query(
key: url, key: url,

View file

@ -323,6 +323,12 @@ class Meta extends LibraryItem {
return (releaseInfo_).toString(); return (releaseInfo_).toString();
} }
Video? get currentVideo {
return videos?.firstWhere((episode) {
return nextEpisode == episode.episode && nextSeason == episode.season;
});
}
Meta({ Meta({
this.imdbId, this.imdbId,
this.name, this.name,

View file

@ -51,15 +51,8 @@ class StremioCard extends StatelessWidget {
); );
} }
Video? get currentVideo {
return (item as Meta).videos?.firstWhere((episode) {
return (item as Meta).nextEpisode == episode.episode &&
(item as Meta).nextSeason == episode.season;
});
}
bool get isInFuture { bool get isInFuture {
final video = currentVideo; final video = (item as Meta).currentVideo;
return video != null && return video != null &&
video.firstAired != null && video.firstAired != null &&
video.firstAired!.isAfter(DateTime.now()); video.firstAired!.isAfter(DateTime.now());
@ -70,7 +63,7 @@ class StremioCard extends StatelessWidget {
return Container(); return Container();
} }
final video = currentVideo; final video = meta.currentVideo;
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
@ -91,10 +84,10 @@ class StremioCard extends StatelessWidget {
gradient: LinearGradient( gradient: LinearGradient(
colors: [ colors: [
Colors.black, Colors.black,
Colors.transparent, Colors.black54,
], ],
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomCenter, end: Alignment.bottomRight,
), ),
), ),
), ),
@ -121,10 +114,25 @@ class StremioCard extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Text("S${meta.nextSeason} E${meta.nextEpisode}"),
Text( Text(
"${meta.name}", "${meta.name}",
style: Theme.of(context).textTheme.bodyLarge, style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(
height: 4,
),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4),
),
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Text(
"S${meta.nextSeason} E${meta.nextEpisode}",
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
color: Colors.black,
),
),
), ),
Text( Text(
"${meta.nextEpisodeTitle}".trim(), "${meta.nextEpisodeTitle}".trim(),

View file

@ -169,32 +169,40 @@ class TraktService {
final Map<String, double> progress = {}; final Map<String, double> progress = {};
final result = await stremioService!.getBulkItem( final result = await stremioService!.getBulkItem(
continueWatching.map((movie) { continueWatching
if (movie['type'] == 'episode') { .sublist(0, 20)
progress[movie['show']['ids']['imdb']] = movie['progress']; .map((movie) {
try {
if (movie['type'] == 'episode') {
progress[movie['show']['ids']['imdb']] = movie['progress'];
return Meta( return Meta(
type: "series", type: "series",
id: movie['show']['ids']['imdb'], id: movie['show']['ids']['imdb'],
progress: movie['progress'], progress: movie['progress'],
nextSeason: movie['episode']['season'], nextSeason: movie['episode']['season'],
nextEpisode: movie['episode']['number'], nextEpisode: movie['episode']['number'],
nextEpisodeTitle: movie['episode']['title'], nextEpisodeTitle: movie['episode']['title'],
); );
} }
final imdb = movie['movie']['ids']['imdb']; final imdb = movie['movie']['ids']['imdb'];
progress[imdb] = movie['progress']; progress[imdb] = movie['progress'];
return Meta( return Meta(
type: "movie", type: "movie",
id: imdb, id: imdb,
progress: movie['progress'], progress: movie['progress'],
); );
}).toList(), } catch (e) {
return null;
}
})
.whereType<Meta>()
.toList(),
); );
return result.sublist(0, 20).map((res) { return result.map((res) {
Meta returnValue = res as Meta; Meta returnValue = res as Meta;
if (progress.containsKey(res.id)) { if (progress.containsKey(res.id)) {
@ -232,8 +240,6 @@ class TraktService {
); );
if (scheduleResponse.statusCode != 200) { if (scheduleResponse.statusCode != 200) {
print(scheduleResponse.body);
print(scheduleResponse.statusCode);
print('Failed to fetch upcoming schedule'); print('Failed to fetch upcoming schedule');
throw Error(); throw Error();
} }
@ -278,14 +284,21 @@ class TraktService {
final watchlistItems = json.decode(watchlistResponse.body) as List; final watchlistItems = json.decode(watchlistResponse.body) as List;
final result = await stremioService!.getBulkItem( final result = await stremioService!.getBulkItem(
watchlistItems.map((item) { watchlistItems
final type = item['type']; .map((item) {
final imdb = item[type]['ids']['imdb']; try {
return Meta( final type = item['type'];
type: type, final imdb = item[type]['ids']['imdb'];
id: imdb, return Meta(
); type: type,
}).toList(), id: imdb,
);
} catch (e) {
return null;
}
})
.whereType<Meta>()
.toList(),
); );
return result; return result;
@ -363,13 +376,20 @@ class TraktService {
json.decode(recommendationsResponse.body) as List; json.decode(recommendationsResponse.body) as List;
final result = await stremioService!.getBulkItem( final result = await stremioService!.getBulkItem(
recommendedMovies.map((movie) { recommendedMovies
final imdb = movie['ids']['imdb']; .map((movie) {
return Meta( try {
type: "movie", final imdb = movie['ids']['imdb'];
id: imdb, return Meta(
); type: "movie",
}).toList(), id: imdb,
);
} catch (e) {
return null;
}
})
.whereType<Meta>()
.toList(),
); );
return result; return result;
@ -478,7 +498,6 @@ class TraktService {
); );
if (response.statusCode != 201) { if (response.statusCode != 201) {
print(response.statusCode);
throw Exception('Failed to pause scrobbling'); throw Exception('Failed to pause scrobbling');
} }
} catch (e, stack) { } catch (e, stack) {
@ -500,10 +519,6 @@ class TraktService {
}, },
}; };
} else { } else {
if (meta.nextEpisode == null && meta.nextSeason == null) {
throw ArgumentError("");
}
return { return {
"show": { "show": {
"title": meta.name, "title": meta.name,
@ -554,33 +569,45 @@ class TraktService {
return []; return [];
} }
if (meta.type == "series") { try {
final response = await http.get( if (meta.type == "series") {
Uri.parse("$_baseUrl/sync/playback/episodes"), final response = await http.get(
headers: headers, Uri.parse("$_baseUrl/sync/playback/episodes"),
); headers: headers,
);
if (response.statusCode != 200) { if (response.statusCode != 200) {
return []; return [];
}
final body = jsonDecode(response.body) as List;
final List<TraktProgress> result = [];
for (final item in body) {
if (item["type"] != "episode") {
continue;
} }
final isShow = item["show"]["ids"]["imdb"] == (meta.imdbId ?? meta.id); final body = jsonDecode(response.body) as List;
final currentEpisode = item["episode"]["number"]; final List<TraktProgress> result = [];
final currentSeason = item["episode"]["season"];
if (isShow && meta.nextEpisode != null && meta.nextSeason != null) { for (final item in body) {
if (meta.nextSeason == currentSeason && if (item["type"] != "episode") {
meta.nextEpisode == currentEpisode) { continue;
}
final isShow =
item["show"]["ids"]["imdb"] == (meta.imdbId ?? meta.id);
final currentEpisode = item["episode"]["number"];
final currentSeason = item["episode"]["season"];
if (isShow && meta.nextEpisode != null && meta.nextSeason != null) {
if (meta.nextSeason == currentSeason &&
meta.nextEpisode == currentEpisode) {
result.add(
TraktProgress(
id: meta.id,
progress: item["progress"]!,
episode: currentEpisode,
season: currentSeason,
),
);
}
} else if (isShow) {
result.add( result.add(
TraktProgress( TraktProgress(
id: meta.id, id: meta.id,
@ -590,45 +617,39 @@ class TraktService {
), ),
); );
} }
} else if (isShow) {
result.add(
TraktProgress(
id: meta.id,
progress: item["progress"]!,
episode: currentEpisode,
season: currentSeason,
),
);
}
}
return result;
} else {
final response = await http.get(
Uri.parse("$_baseUrl/sync/playback/movies"),
headers: headers,
);
if (response.statusCode != 200) {
return [];
}
final body = jsonDecode(response.body) as List;
for (final item in body) {
if (item["type"] != "movie") {
continue;
} }
if (item["movie"]["ids"]["imdb"] == (meta.imdbId ?? meta.id)) { return result;
return [ } else {
TraktProgress( final response = await http.get(
id: item["movie"]["ids"]["imdb"], Uri.parse("$_baseUrl/sync/playback/movies"),
progress: item["progress"], headers: headers,
), );
];
if (response.statusCode != 200) {
return [];
}
final body = jsonDecode(response.body) as List;
for (final item in body) {
if (item["type"] != "movie") {
continue;
}
if (item["movie"]["ids"]["imdb"] == (meta.imdbId ?? meta.id)) {
return [
TraktProgress(
id: item["movie"]["ids"]["imdb"],
progress: item["progress"],
),
];
}
} }
} }
} catch (e) {
print(e);
return [];
} }
return []; return [];