mirror of
https://github.com/madari-media/madari-oss.git
synced 2026-05-07 16:49:36 +00:00
fix: trakt integration is fixed
This commit is contained in:
parent
0e97a8ae61
commit
6c87e5a1d9
5 changed files with 61 additions and 35 deletions
|
|
@ -502,9 +502,7 @@ class StremioConnectionService extends BaseConnectionService {
|
|||
|
||||
try {
|
||||
streamTitle = utf8.decode(streamTitle.runes.toList());
|
||||
} catch (e) {
|
||||
_logger.warning('Failed to decode stream title', e);
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
String? streamDescription = item.description;
|
||||
|
||||
|
|
@ -512,9 +510,7 @@ class StremioConnectionService extends BaseConnectionService {
|
|||
streamDescription = item.description != null
|
||||
? utf8.decode((item.description!).runes.toList())
|
||||
: null;
|
||||
} catch (e) {
|
||||
_logger.warning('Failed to decode stream description', e);
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
String title = meta.name ?? item.title ?? "No title";
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:flutter/cupertino.dart';
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:madari_client/features/connections/service/base_connection_service.dart';
|
||||
import 'package:madari_client/features/doc_viewer/container/video_viewer/tv_controls.dart';
|
||||
import 'package:madari_client/features/watch_history/service/base_watch_history.dart';
|
||||
|
|
@ -52,6 +53,7 @@ class _VideoViewerState extends State<VideoViewer> {
|
|||
),
|
||||
);
|
||||
late final GlobalKey<VideoState> key = GlobalKey<VideoState>();
|
||||
final Logger _logger = Logger('VideoPlayer');
|
||||
|
||||
double get currentProgressInPercentage {
|
||||
final duration = player.state.duration.inSeconds;
|
||||
|
|
@ -61,10 +63,11 @@ class _VideoViewerState extends State<VideoViewer> {
|
|||
|
||||
Future<List<TraktProgress>>? traktProgress;
|
||||
|
||||
saveWatchHistory() {
|
||||
Future<void> saveWatchHistory() async {
|
||||
final duration = player.state.duration.inSeconds;
|
||||
|
||||
if (duration < 30) {
|
||||
_logger.info('Video is too short to track.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -72,29 +75,34 @@ class _VideoViewerState extends State<VideoViewer> {
|
|||
final progress = duration > 0 ? (position / duration * 100).round() : 0;
|
||||
|
||||
if (progress == 0) {
|
||||
_logger.info('No progress to save.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (widget.meta is types.Meta) {
|
||||
if (widget.meta is types.Meta && TraktService.instance != null) {
|
||||
try {
|
||||
if (player.state.playing) {
|
||||
TraktService.instance!.startScrobbling(
|
||||
_logger.info('Starting scrobbling...');
|
||||
await TraktService.instance!.startScrobbling(
|
||||
meta: widget.meta as types.Meta,
|
||||
progress: currentProgressInPercentage,
|
||||
);
|
||||
} else {
|
||||
TraktService.instance!.stopScrobbling(
|
||||
_logger.info('Stopping scrobbling...');
|
||||
await TraktService.instance!.stopScrobbling(
|
||||
meta: widget.meta as types.Meta,
|
||||
progress: currentProgressInPercentage,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
print(e);
|
||||
_logger.severe('Error during scrobbling: $e');
|
||||
TraktService.instance!.debugLogs.add(e.toString());
|
||||
}
|
||||
} else {
|
||||
_logger.warning('Meta is not valid or TraktService is not initialized.');
|
||||
}
|
||||
|
||||
zeeeWatchHistory!.saveWatchHistory(
|
||||
await zeeeWatchHistory!.saveWatchHistory(
|
||||
history: WatchHistory(
|
||||
id: _source.id,
|
||||
progress: progress,
|
||||
|
|
@ -172,7 +180,7 @@ class _VideoViewerState extends State<VideoViewer> {
|
|||
|
||||
bool canCallOnce = false;
|
||||
|
||||
setDurationFromTrakt() async {
|
||||
Future<void> setDurationFromTrakt() async {
|
||||
if (player.state.duration.inSeconds < 2) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -202,8 +210,8 @@ class _VideoViewerState extends State<VideoViewer> {
|
|||
),
|
||||
);
|
||||
|
||||
player.seek(duration);
|
||||
player.play();
|
||||
await player.seek(duration);
|
||||
await player.play();
|
||||
}
|
||||
|
||||
List<StreamSubscription> listener = [];
|
||||
|
|
@ -230,9 +238,10 @@ class _VideoViewerState extends State<VideoViewer> {
|
|||
}
|
||||
}
|
||||
|
||||
_duration = player.stream.duration.listen((item) {
|
||||
_duration = player.stream.duration.listen((item) async {
|
||||
if (item.inSeconds != 0) {
|
||||
setDurationFromTrakt();
|
||||
await setDurationFromTrakt();
|
||||
await saveWatchHistory();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -283,6 +292,8 @@ class _VideoViewerState extends State<VideoViewer> {
|
|||
}
|
||||
|
||||
loadFile() async {
|
||||
_logger.info('Loading file for source: ${_source.id}');
|
||||
|
||||
final item = await zeeeWatchHistory!.getItemWatchHistory(
|
||||
ids: [
|
||||
WatchHistoryGetRequest(
|
||||
|
|
@ -335,6 +346,8 @@ class _VideoViewerState extends State<VideoViewer> {
|
|||
late StreamSubscription<dynamic> _duration;
|
||||
|
||||
onLibrarySelect() async {
|
||||
_logger.info('Library selection triggered.');
|
||||
|
||||
controller.player.pause();
|
||||
|
||||
final result = await showCupertinoDialog(
|
||||
|
|
@ -367,6 +380,8 @@ class _VideoViewerState extends State<VideoViewer> {
|
|||
|
||||
@override
|
||||
void dispose() {
|
||||
_logger.info('Disposing VideoViewer...');
|
||||
|
||||
SystemChrome.setPreferredOrientations([
|
||||
DeviceOrientation.portraitUp,
|
||||
DeviceOrientation.portraitDown,
|
||||
|
|
@ -441,8 +456,8 @@ class _VideoViewerState extends State<VideoViewer> {
|
|||
switch (styleName.toLowerCase()) {
|
||||
case 'italic':
|
||||
return FontStyle.italic;
|
||||
case 'normal': // Explicitly handle 'normal' (good practice)
|
||||
default: // Default case for any other string or null
|
||||
case 'normal':
|
||||
default:
|
||||
return FontStyle.normal;
|
||||
}
|
||||
}
|
||||
|
|
@ -521,6 +536,8 @@ class _VideoViewerState extends State<VideoViewer> {
|
|||
}
|
||||
|
||||
onSubtitleSelect() {
|
||||
_logger.info('Subtitle selection triggered.');
|
||||
|
||||
showCupertinoModalPopup(
|
||||
context: context,
|
||||
builder: (ctx) => Card(
|
||||
|
|
@ -573,6 +590,8 @@ class _VideoViewerState extends State<VideoViewer> {
|
|||
}
|
||||
|
||||
onAudioSelect() {
|
||||
_logger.info('Audio track selection triggered.');
|
||||
|
||||
showCupertinoModalPopup(
|
||||
context: context,
|
||||
builder: (ctx) => Card(
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ class TraktContainerState extends State<TraktContainer> {
|
|||
|
||||
final _scrollController = ScrollController();
|
||||
|
||||
StreamSubscription<List<String>>? _steam;
|
||||
|
||||
bool get _isBottom {
|
||||
if (!_scrollController.hasClients) return false;
|
||||
final maxScroll = _scrollController.position.maxScrollExtent;
|
||||
|
|
@ -45,6 +47,14 @@ class TraktContainerState extends State<TraktContainer> {
|
|||
_logger.info('Initializing TraktContainerState');
|
||||
_loadData();
|
||||
|
||||
_steam = TraktService.instance?.refetchKey.stream.listen((item) {
|
||||
if (item.contains(widget.loadId)) {
|
||||
_logger.info("refreshing widget ${widget.loadId}");
|
||||
_cachedItems = [];
|
||||
_loadData();
|
||||
}
|
||||
});
|
||||
|
||||
_scrollController.addListener(() {
|
||||
if (_isBottom) {
|
||||
_loadData(isLoadMore: true);
|
||||
|
|
@ -56,6 +66,7 @@ class TraktContainerState extends State<TraktContainer> {
|
|||
void dispose() {
|
||||
_logger.info('Disposing TraktContainerState');
|
||||
_scrollController.dispose();
|
||||
_steam?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -761,10 +761,16 @@ class TraktService {
|
|||
_cache.remove('$_baseUrl/sync/watched/shows');
|
||||
_cache.remove('$_baseUrl/sync/playback');
|
||||
|
||||
refetchKey.add([
|
||||
final keys = [
|
||||
"continue_watching",
|
||||
if (meta.type == "series") "up_next_series",
|
||||
]);
|
||||
];
|
||||
|
||||
refetchKey.add(keys);
|
||||
|
||||
_logger.info(
|
||||
"pushing refetch key ${keys.join(", ")} still in cache ${_cache.keys.join(", ")}",
|
||||
);
|
||||
} catch (e, stack) {
|
||||
_logger.severe('Error stopping scrobbling: $e', stack);
|
||||
rethrow;
|
||||
|
|
|
|||
|
|
@ -78,13 +78,10 @@ class _StremioItemPageState extends State<StremioItemPage> {
|
|||
);
|
||||
|
||||
if (mounted) {
|
||||
final season = widget.meta?.nextSeason == null
|
||||
? ""
|
||||
: "S${widget.meta?.nextSeason}";
|
||||
|
||||
final episode = widget.meta?.nextEpisode == null
|
||||
? ""
|
||||
: "E${widget.meta?.nextEpisode}";
|
||||
final videoEpisode =
|
||||
widget.meta?.currentVideo?.episode ?? widget.meta?.nextEpisode;
|
||||
final videoSeason =
|
||||
widget.meta?.currentVideo?.season ?? widget.meta?.nextSeason;
|
||||
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
|
|
@ -98,7 +95,8 @@ class _StremioItemPageState extends State<StremioItemPage> {
|
|||
icon: const Icon(Icons.close),
|
||||
),
|
||||
title: Text(
|
||||
"Streams $season $episode".trim(),
|
||||
"Streams ${videoSeason != null ? "S$videoSeason" : ""} ${videoEpisode != null ? " E$videoEpisode" : ""}"
|
||||
.trim(),
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
|
|
@ -110,12 +108,8 @@ class _StremioItemPageState extends State<StremioItemPage> {
|
|||
: null,
|
||||
service: widget.service!,
|
||||
id: widget.meta as LibraryItem,
|
||||
season: (widget.meta?.currentVideo?.season ??
|
||||
widget.meta?.nextSeason)
|
||||
?.toString(),
|
||||
episode: (widget.meta?.currentVideo?.episode ??
|
||||
widget.meta?.nextEpisode)
|
||||
?.toString(),
|
||||
season: videoSeason?.toString(),
|
||||
episode: videoEpisode?.toString(),
|
||||
shouldPop: false,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
Loading…
Reference in a new issue