565 lines
16 KiB
Dart
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,
|
|
),
|
|
);
|
|
}
|
|
}),
|
|
);
|
|
}
|
|
}
|