added Information-Field to TV Shows

This commit is contained in:
2026-02-02 14:46:05 +01:00
parent a78501a6a4
commit a6bd718157
4 changed files with 80 additions and 2 deletions
@@ -15,6 +15,7 @@ class EpisodeItem {
final String? posterPath;
final int? showId;
final String? downloadPath;
final String? showInformation;
EpisodeItem({
required this.id,
@@ -31,6 +32,7 @@ class EpisodeItem {
this.posterPath,
this.showId,
this.downloadPath,
this.showInformation,
});
factory EpisodeItem.fromJson(Map<String, dynamic> j) => EpisodeItem(
@@ -48,6 +50,7 @@ class EpisodeItem {
posterPath: j['poster_path'] as String?,
showId: (j['show_id'] as num?)?.toInt(),
downloadPath: j['download_path'] as String?,
showInformation: j['show_information'] as String?,
);
static bool? _parseBool(dynamic v) {
@@ -46,7 +46,10 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
String? _origResolution;
String? _origDownloadPath;
bool? _origCliffhanger;
String? _information;
String? _origInformation;
late final TextEditingController _downloadCtrl;
late final TextEditingController _infoCtrl;
String? _overview;
List<Map<String, dynamic>> _cast = const [];
List<Map<String, dynamic>> _crew = const [];
@@ -63,6 +66,13 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
setState(() => _downloadPath = v);
}
});
_infoCtrl = TextEditingController(text: _information ?? '');
_infoCtrl.addListener(() {
final v = _infoCtrl.text;
if (v != (_information ?? '')) {
setState(() => _information = v);
}
});
// Quick-fill from seasonsEps for instant UI while fetching real data
if (widget.seasonsEps != null && widget.seasonsEps!.isNotEmpty) {
final map = <int, List<EpisodeItem>>{};
@@ -93,6 +103,13 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
_load();
}
@override
void dispose() {
_downloadCtrl.dispose();
_infoCtrl.dispose();
super.dispose();
}
Future<void> _load() async {
try {
int? showId = widget.showId;
@@ -120,13 +137,18 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
_resolution ??= first.resolution;
_downloadPath ??= first.downloadPath;
_cliffhanger ??= first.showCliffhanger;
_information ??= first.showInformation;
_showId ??= first.showId ?? showId;
_origResolution ??= _resolution;
_origDownloadPath ??= _downloadPath;
_origCliffhanger ??= _cliffhanger;
_origInformation ??= _information;
if (_downloadCtrl.text != (_downloadPath ?? '')) {
_downloadCtrl.text = _downloadPath ?? '';
}
if (_infoCtrl.text != (_information ?? '')) {
_infoCtrl.text = _information ?? '';
}
if (first.showJson != null && first.showJson!.isNotEmpty) {
try {
final m = jsonDecode(first.showJson!) as Map<String, dynamic>;
@@ -178,12 +200,14 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
futures.add(api.setStatus(type: 'episode', refId: epId, status: st.name));
});
// show meta
if (_showId != null && (_resolution != _origResolution || _downloadPath != _origDownloadPath || _cliffhanger != _origCliffhanger)) {
final infoChanged = _information != _origInformation;
if (_showId != null && (_resolution != _origResolution || _downloadPath != _origDownloadPath || _cliffhanger != _origCliffhanger || infoChanged)) {
futures.add(api.setShowMeta(
showId: _showId!,
resolution: _resolution,
downloadPath: _downloadPath,
cliffhanger: _cliffhanger,
information: infoChanged ? _information : null,
));
}
await Future.wait(futures);
@@ -202,6 +226,7 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
_origResolution = _resolution;
_origDownloadPath = _downloadPath;
_origCliffhanger = _cliffhanger;
_origInformation = _information;
});
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Gespeichert')));
}
@@ -240,6 +265,7 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
posterPath: it.posterPath,
showId: it.showId,
downloadPath: it.downloadPath,
showInformation: it.showInformation,
))
.toList()
: e.value,
@@ -257,7 +283,8 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
final dirty = _pending.isNotEmpty ||
_resolution != _origResolution ||
_downloadPath != _origDownloadPath ||
_cliffhanger != _origCliffhanger;
_cliffhanger != _origCliffhanger ||
_information != _origInformation;
return PopScope(
canPop: true,
onPopInvokedWithResult: (didPop, result) async {
@@ -535,6 +562,18 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
focusedBorder: UnderlineInputBorder(borderSide: BorderSide(color: Colors.white)),
),
),
const SizedBox(height: 8),
TextField(
controller: _infoCtrl,
style: const TextStyle(color: Colors.white),
maxLines: 3,
decoration: const InputDecoration(
labelText: 'Information',
labelStyle: TextStyle(color: Colors.white70),
enabledBorder: UnderlineInputBorder(borderSide: BorderSide(color: Colors.white54)),
focusedBorder: UnderlineInputBorder(borderSide: BorderSide(color: Colors.white)),
),
),
Row(
children: [
Checkbox(