Files
2025-04-18 10:16:03 +02:00

565 lines
16 KiB
Dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:multimedia/widgets/tvshows/details/companies_box.dart';
import 'package:multimedia/widgets/tvshows/details/countries_box.dart';
import 'package:multimedia/widgets/tvshows/details/crew_box.dart';
import 'package:multimedia/widgets/tvshows/details/cast_box.dart';
import 'package:multimedia/widgets/tvshows/details/genre_box.dart';
import 'package:multimedia/widgets/tvshows/details/overview_box.dart';
import 'package:multimedia/widgets/tvshows/details/seasons.dart';
import 'package:multimedia/widgets/tvshows/details/settings_box.dart';
import 'package:multimedia/data/tvshows.dart';
import 'package:logger/logger.dart';
import 'package:multimedia/log_printer.dart';
// ignore: must_be_immutable
class TVShowDetailsScreen extends StatelessWidget {
TVShowDetailsScreen({
super.key,
required this.tvShow,
});
final TVShow tvShow;
late int maxSeason;
late List<EpisodeCount> episodeCount;
late TVShow tvShowDetails;
Logger logger = getLogger();
Future<http.Response> testPost(String data) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String? dbProtocol = prefs.getString('dbProtocol');
String? dbHost = prefs.getString('dbHost');
String? dbPath = prefs.getString('dbPath');
Uri url = Uri(
scheme: dbProtocol,
host: dbHost,
path: dbPath,
);
final r = http.post(
url,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(
<String, String>{
'module': 'tvshow',
'function': 'test',
'title': data,
},
),
);
return r;
}
Future<TVShow> loadTVShowDetails(int tvshowID) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String? dbProtocol = prefs.getString('dbProtocol');
String? dbHost = prefs.getString('dbHost');
String? dbPath = prefs.getString('dbPath');
Uri url = Uri(
scheme: dbProtocol,
host: dbHost,
path: dbPath,
queryParameters: {
'module': 'tvshow',
'function': 'getDetails',
'tvshowID': tvshowID.toString(),
},
);
final response = await http.get(url);
//LATER bool? error;
//LATER String? errorMessage;
String? mSeason;
Map<String, dynamic> tvshows = json.decode(response.body);
//LATER error = tvshows['error'];
//LATER errorMessage = tvshows['errmsg'];
mSeason = tvshows['maxSeason'];
var tvshowList = tvshows['tvshows'];
var episodeList = tvshows['episodeCount'];
if (mSeason != null) {
if (int.tryParse(mSeason) != null) {
maxSeason = int.parse(mSeason);
}
}
List<TVShow> tvshowsTmp =
await tvshowList.map<TVShow>((json) => TVShow.fromJson(json)).toList();
List<EpisodeCount> episodecountTmp = await episodeList
.map<EpisodeCount>((json) => EpisodeCount.fromJson(json))
.toList();
episodeCount = episodecountTmp;
if (tvshowsTmp.isNotEmpty) {
tvShowDetails = tvshowsTmp[0];
}
return tvshowsTmp[0];
}
Widget generateLists(BuildContext context) {
double width = MediaQuery.of(context).size.width;
if (width < 750) {
return Table(
children: [
TableRow(
children: [
Padding(
padding: const EdgeInsets.only(
left: 10.0,
right: 10.0,
top: 10.0,
bottom: 5.0,
),
child: TVShowDetailsCastBox(
cast: tvShowDetails.cast,
),
),
],
),
TableRow(
children: [
Padding(
padding: const EdgeInsets.only(
left: 10.0,
right: 10.0,
top: 5.0,
bottom: 5.0,
),
child: TVShowDetailsCrewBox(
crew: tvShowDetails.crew,
),
),
],
),
TableRow(
children: [
Padding(
padding: const EdgeInsets.only(
left: 10.0,
right: 10.0,
top: 5.0,
bottom: 5.0,
),
child: TVShowDetailsGenreBox(
genre: tvShowDetails.genre,
),
),
],
),
TableRow(
children: [
Padding(
padding: const EdgeInsets.only(
left: 10.0,
right: 10.0,
top: 5.0,
bottom: 5.0,
),
child: TVShowDetailsCompaniesBox(
companies: tvShowDetails.productionCompanies,
),
),
],
),
TableRow(
children: [
Padding(
padding: const EdgeInsets.only(
left: 10.0,
right: 10.0,
top: 5.0,
bottom: 10.0,
),
child: TVShowDetailsCountriesBox(
countries: tvShowDetails.originCountries,
),
),
],
),
],
);
}
if (width < 1000) {
return Table(
children: [
TableRow(
children: [
Padding(
padding: const EdgeInsets.only(
left: 10.0,
right: 5.0,
top: 10.0,
bottom: 5.0,
),
child: TVShowDetailsCastBox(
cast: tvShowDetails.cast,
),
),
Padding(
padding: const EdgeInsets.only(
left: 5.0,
right: 5.0,
top: 5.0,
bottom: 5.0,
),
child: TVShowDetailsCrewBox(
crew: tvShowDetails.crew,
),
),
Padding(
padding: const EdgeInsets.only(
left: 5.0,
right: 10.0,
top: 5.0,
bottom: 5.0,
),
child: TVShowDetailsGenreBox(
genre: tvShowDetails.genre,
),
),
],
),
TableRow(
children: [
Padding(
padding: const EdgeInsets.only(
left: 10.0,
right: 5.0,
top: 5.0,
bottom: 10.0,
),
child: TVShowDetailsCompaniesBox(
companies: tvShowDetails.productionCompanies,
),
),
Padding(
padding: const EdgeInsets.only(
left: 5.0,
right: 10.0,
top: 5.0,
bottom: 10.0,
),
child: TVShowDetailsCountriesBox(
countries: tvShowDetails.originCountries,
),
),
const Text(''),
],
),
],
);
}
return Table(
children: [
TableRow(
children: [
Padding(
padding: const EdgeInsets.only(
left: 10.0,
right: 5.0,
top: 5.0,
bottom: 5.0,
),
child: TVShowDetailsCastBox(
cast: tvShowDetails.cast,
),
),
Padding(
padding: const EdgeInsets.only(
left: 5.0,
right: 5.0,
top: 5.0,
bottom: 5.0,
),
child: TVShowDetailsCrewBox(
crew: tvShowDetails.crew,
),
),
Padding(
padding: const EdgeInsets.only(
left: 5.0,
right: 5.0,
top: 5.0,
bottom: 5.0,
),
child: TVShowDetailsGenreBox(
genre: tvShowDetails.genre,
),
),
Padding(
padding: const EdgeInsets.only(
left: 5.0,
right: 5.0,
top: 5.0,
bottom: 5.0,
),
child: TVShowDetailsCompaniesBox(
companies: tvShowDetails.productionCompanies,
),
),
Padding(
padding: const EdgeInsets.only(
left: 5.0,
right: 10.0,
top: 5.0,
bottom: 5.0,
),
child: TVShowDetailsCountriesBox(
countries: tvShowDetails.originCountries,
),
),
],
),
],
);
}
bool save() {
updateTVShow();
return true;
}
Future<bool> updateTVShow() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String? dbProtocol = prefs.getString('dbProtocol');
String? dbHost = prefs.getString('dbHost');
String? dbPath = prefs.getString('dbPath');
Uri url = Uri(
scheme: dbProtocol,
host: dbHost,
path: dbPath,
);
var seasonState = jsonEncode(tvShowDetails.seasonStatus.map((e) => e.toJson()).toList());
try {
/*final r =*/ await http.post(
url,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(
<String, dynamic>{
'module': 'tvshow',
'function': 'update',
'seriesID': tvShowDetails.seriesID.toString(),
'seriesName': tvShowDetails.seriesName,
'overview': tvShowDetails.overview,
'firstAired':
DateFormat('yyyy-MM-dd').format(tvShowDetails.firstAired),
'resolution': tvShowDetails.resolution,
'cliffhanger': tvShowDetails.cliffhanger.toString(),
'status': tvShowDetails.status.toString(),
'backdropPath': tvShowDetails.backdropPath,
'seriesState': tvShowDetails.seriesState.toString(),
'languages': tvShowDetails.languages,
'networks': tvShowDetails.networks,
'productionCompanies': tvShowDetails.productionCompanies,
'voteAverage': tvShowDetails.voteAverage.toString(),
'voteCount': tvShowDetails.voteCount.toString(),
'cast': tvShowDetails.cast,
'crew': tvShowDetails.crew,
'genre': tvShowDetails.genre,
'download': tvShowDetails.download,
'localPath': tvShowDetails.localPath,
'seasons': seasonState,
},
),
);
} catch (e) {
logger.e(e.toString());
}
return true;
}
void settingsChanged(
String download, String localPath, String resolution, int cliffhanger) {
tvShowDetails.download = download;
tvShowDetails.localPath = localPath;
tvShowDetails.resolution = resolution;
tvShowDetails.cliffhanger = cliffhanger;
}
void stateChanged(List<Season> seasonStatus) {
tvShowDetails.seasonStatus = seasonStatus;
bool hasInit = false;
bool hasProg = false;
bool hasDone = false;
for (var season in tvShowDetails.seasonStatus) {
var episodeList = season.state.split(',');
for (var s in episodeList) {
var states = s.split('|');
if (states[1] == '1') {
hasInit = true;
}
if (states[1] == '2') {
hasProg = true;
}
if (states[1] == '3') {
hasDone = true;
}
}
}
if (hasProg) {
tvShowDetails.seriesState = 2;
} else if (hasInit) {
tvShowDetails.seriesState = 1;
} else if (hasDone) {
tvShowDetails.seriesState = 3;
}
}
@override
Widget build(BuildContext context) {
String firstAiredYear = tvShow.firstAired.toString().substring(0, 4);
return Scaffold(
appBar: AppBar(
title: Text("${tvShow.seriesName} ($firstAiredYear)"),
actions: [
IconButton(
icon: const Icon(Icons.check_circle_outline),
tooltip: 'Save changes',
onPressed: () {
if (save()) {
Navigator.pop(context, tvShowDetails);
}
},
),
IconButton(
icon: const Icon(Icons.highlight_off),
tooltip: 'Revert changes',
onPressed: () {
Navigator.pop(context, null);
},
),
const VerticalDivider(
width: 10,
thickness: 3,
indent: 0,
endIndent: 0,
color: Colors.grey,
),
IconButton(
icon: const Icon(Icons.update_outlined),
tooltip: 'Update movie',
onPressed: () {
//todo
},
),
IconButton(
icon: const Icon(Icons.delete_outline),
color: Colors.red,
tooltip: 'Delete movie',
onPressed: () {
//todo
},
),
],
),
body: FutureBuilder<Object>(
future: loadTVShowDetails(tvShow.seriesID),
builder: (context, data) {
if (data.hasData) {
String url =
'http://image.tmdb.org/t/p/original${tvShowDetails.backdropPath}';
return Stack(children: [
Container(
decoration: BoxDecoration(
image: tvShowDetails.backdropPath.isNotEmpty
? DecorationImage(
image: NetworkImage(url),
fit: BoxFit.cover,
)
: null,
),
),
SingleChildScrollView(
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(
left: 10.0,
right: 10.0,
top: 10.0,
bottom: 5.0,
),
child: TVShowDetailsOverviewBox(
overview: tvShowDetails.overview,
),
),
generateLists(context),
Padding(
padding: const EdgeInsets.only(
left: 10.0,
right: 10.0,
top: 5.0,
bottom: 5.0,
),
child: TVShowDetailsSettingsBox(
downloadLink: tvShowDetails.download,
localPath: tvShowDetails.localPath,
resolution: tvShowDetails.resolution,
cliffhanger: tvShowDetails.cliffhanger,
settingsChanged: settingsChanged,
),
),
Padding(
padding: const EdgeInsets.only(
left: 10.0,
right: 10.0,
top: 5.0,
bottom: 5.0,
),
child: TVShowDetailsSeasons(
seasonStatus: tvShowDetails.seasonStatus,
stateChanged: stateChanged,
),
),
],
),
),
]);
} else {
return const Center(
child: CircularProgressIndicator(
strokeWidth: 2,
value: 0.8,
),
);
}
}),
);
}
}