481 lines
14 KiB
Dart
481 lines
14 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:accordion/accordion.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:intl/intl.dart';
|
|
|
|
import 'package:logger/logger.dart';
|
|
import 'package:multimedia/data/movies.dart';
|
|
import 'package:multimedia/log_printer.dart';
|
|
import 'package:multimedia/widgets/checkbox_with_label.dart';
|
|
import 'package:multimedia/widgets/movies/add/movie_search_list.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import 'package:tmdb_api/tmdb_api.dart' as TMDB;
|
|
|
|
// ignore: must_be_immutable
|
|
class AddMovieScreen extends StatefulWidget {
|
|
final Function(Movie) addMovieToList;
|
|
final Function() addMovieFinished;
|
|
|
|
AddMovieScreen(
|
|
this.addMovieToList,
|
|
this.addMovieFinished, {
|
|
super.key,
|
|
});
|
|
|
|
@override
|
|
State<AddMovieScreen> createState() => _AddMovieScreenState();
|
|
}
|
|
|
|
class _AddMovieScreenState extends State<AddMovieScreen> {
|
|
Logger logger = getLogger();
|
|
|
|
String movieTitleSearch = '';
|
|
String yearSearch = '';
|
|
bool includeAdult = false;
|
|
bool searchGerman = true;
|
|
bool searchEnglish = false;
|
|
List<Movie> movieList = [];
|
|
|
|
late MovieSearchList movieSearchList;
|
|
late Function(Movie) addMovieToList;
|
|
late Function() addMovieFinished;
|
|
|
|
static const headerStyle = TextStyle(
|
|
color: Color(0xffffffff), fontSize: 18, fontWeight: FontWeight.bold);
|
|
bool advancedOptionsOpen = false;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
addMovieToList = widget.addMovieToList;
|
|
addMovieFinished = widget.addMovieFinished;
|
|
movieSearchList = MovieSearchList(movieList: movieList);
|
|
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text('Search Movie'),
|
|
actions: [
|
|
const VerticalDivider(
|
|
width: 10,
|
|
thickness: 3,
|
|
indent: 0,
|
|
endIndent: 0,
|
|
color: Colors.grey,
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.check_circle_outline),
|
|
tooltip: 'Add Movie(s)',
|
|
onPressed: () {
|
|
if (addMovies()) {
|
|
Navigator.pop(context, true);
|
|
}
|
|
},
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.highlight_off),
|
|
tooltip: 'Cancel Add',
|
|
onPressed: () {
|
|
Navigator.pop(context, null);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
body: Column(
|
|
children: [
|
|
Row(
|
|
children: [
|
|
SizedBox(
|
|
width: 20,
|
|
),
|
|
SizedBox(
|
|
width: 250,
|
|
child: TextField(
|
|
style: TextStyle(color: Colors.white),
|
|
decoration: InputDecoration(
|
|
labelText: 'Movie Title',
|
|
),
|
|
onChanged: (text) {
|
|
movieTitleSearch = text;
|
|
},
|
|
),
|
|
),
|
|
const SizedBox(
|
|
width: 10,
|
|
),
|
|
SizedBox(
|
|
width: 50,
|
|
child: TextField(
|
|
style: TextStyle(color: Colors.white),
|
|
decoration: InputDecoration(
|
|
labelText: 'Year',
|
|
),
|
|
onChanged: (text) {
|
|
yearSearch = text;
|
|
},
|
|
),
|
|
),
|
|
const SizedBox(
|
|
width: 10,
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
startSearch();
|
|
},
|
|
child: const Text('Search'),
|
|
),
|
|
],
|
|
),
|
|
Accordion(
|
|
headerBorderColor: Colors.blueGrey,
|
|
headerBorderColorOpened: Colors.transparent,
|
|
// headerBorderWidth: 1,
|
|
headerBackgroundColorOpened: Colors.grey,
|
|
contentBackgroundColor: Colors.black87,
|
|
contentBorderColor: Colors.grey,
|
|
contentBorderWidth: 3,
|
|
contentHorizontalPadding: 20,
|
|
scaleWhenAnimating: true,
|
|
openAndCloseAnimation: true,
|
|
headerPadding:
|
|
const EdgeInsets.symmetric(vertical: 7, horizontal: 15),
|
|
children: [
|
|
AccordionSection(
|
|
isOpen: advancedOptionsOpen,
|
|
contentVerticalPadding: 20,
|
|
leftIcon: const Icon(Icons.settings, color: Colors.white),
|
|
header: const Text('Advanced Options', style: headerStyle),
|
|
content: advancedOptions(),
|
|
onOpenSection: () {
|
|
advancedOptionsOpen = true;
|
|
},
|
|
onCloseSection: () {
|
|
advancedOptionsOpen = false;
|
|
},
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(
|
|
height: 10,
|
|
),
|
|
const Divider(
|
|
height: 5,
|
|
thickness: 3,
|
|
),
|
|
Expanded(
|
|
child: MovieSearchList(
|
|
movieList: movieList,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
void includeAdultCallback(bool state) {
|
|
includeAdult = state;
|
|
}
|
|
|
|
void searchGermanCallback(bool state) {
|
|
searchGerman = state;
|
|
}
|
|
|
|
void searchEnglishCallback(bool state) {
|
|
searchEnglish = state;
|
|
}
|
|
|
|
Widget advancedOptions() {
|
|
return Row(
|
|
children: [
|
|
CheckboxWithLabel(
|
|
label: 'Include Adult',
|
|
callback: includeAdultCallback,
|
|
state: includeAdult,
|
|
),
|
|
CheckboxWithLabel(
|
|
label: 'German',
|
|
callback: searchGermanCallback,
|
|
state: searchGerman,
|
|
),
|
|
CheckboxWithLabel(
|
|
label: 'English',
|
|
callback: searchEnglishCallback,
|
|
state: searchEnglish,
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
String parseString(dynamic data, String field) {
|
|
if (data[field].toString() == Null) {
|
|
return '';
|
|
}
|
|
|
|
return data[field].toString();
|
|
}
|
|
|
|
DateTime parseDate(dynamic data, String field) {
|
|
if (data[field].toString() == Null) {
|
|
return DateTime(1900, 1, 1);
|
|
}
|
|
|
|
if (data[field].toString().length < 1) {
|
|
return DateTime(1900, 1, 1);
|
|
}
|
|
|
|
return DateTime.parse(data[field].toString());
|
|
}
|
|
|
|
double parseDouble(dynamic data, String field) {
|
|
if (data[field] == Null) {
|
|
return 0.0;
|
|
}
|
|
return data[field];
|
|
}
|
|
|
|
int parseInt(dynamic data, String field) {
|
|
if (data[field] == Null) {
|
|
return 0;
|
|
}
|
|
|
|
return data[field];
|
|
}
|
|
|
|
bool parseBool(dynamic data, String field) {
|
|
if (data[field] == Null) {
|
|
return false;
|
|
}
|
|
|
|
return data[field];
|
|
}
|
|
|
|
Future<void> startSearch() async {
|
|
if (movieTitleSearch.isEmpty) {
|
|
return;
|
|
}
|
|
|
|
int year = int.tryParse(yearSearch) ?? 0;
|
|
|
|
final tmdb = TMDB.TMDB(TMDB.ApiKeys(
|
|
'a33271b9e54cdcb9a80680eaf5522f1b', 'apiReadAccessTokenv4'));
|
|
|
|
final response = await tmdb.v3.search.queryMovies(
|
|
movieTitleSearch,
|
|
year: year,
|
|
includeAdult: includeAdult,
|
|
language: searchGerman == true ? 'de' : 'en',
|
|
);
|
|
List<dynamic> movies = response['results'];
|
|
|
|
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': 'movie',
|
|
'function': 'getIDs',
|
|
},
|
|
);
|
|
|
|
List<int> movieIDsTmp = [];
|
|
|
|
try {
|
|
final response = await http.get(url);
|
|
//LATER bool? error;
|
|
//LATER String? errorMessage;
|
|
|
|
Map<String, dynamic> movieIDs = json.decode(response.body);
|
|
//LATER error = movies['error'];
|
|
//LATER errorMessage = movies['errmsg'];
|
|
var list = movieIDs['data'];
|
|
|
|
for (int i = 0; i < list.length; i++) {
|
|
var entry = list[i];
|
|
movieIDsTmp.add(int.tryParse(entry['movieID'].toString()) ?? 0);
|
|
}
|
|
} catch (e) {
|
|
print(e.toString());
|
|
}
|
|
|
|
setState(
|
|
() {
|
|
movieList.clear();
|
|
|
|
for (int i = 0; i < movies.length; i++) {
|
|
dynamic movie = movies[i];
|
|
|
|
int movieID = parseInt(movie, 'id');
|
|
String movieTitle = parseString(movie, 'title');
|
|
String originalTitle = parseString(movie, 'original_title');
|
|
String overview = parseString(movie, 'overview');
|
|
DateTime releaseDate = parseDate(movie, 'release_date');
|
|
String backdropPath = parseString(movie, 'backdrop_path');
|
|
String posterPath = parseString(movie, 'poster_path');
|
|
String languages = ''; //MISSING
|
|
String productionCountries = ''; //MISSING
|
|
String productionCompanies = ''; //MISSING
|
|
double voteAverage = parseDouble(movie, 'vote_average');
|
|
int voteCount = parseInt(movie, 'vote_count');
|
|
String cast = ''; //MISSING
|
|
String crew = ''; //MISSING
|
|
String genre = ''; //DIFFERENT;
|
|
String localPath = '';
|
|
String imdbID = ''; //MISSING
|
|
String originalLanguage = parseString(movie, 'original_language');
|
|
double popularity = parseDouble(movie, 'popularity');
|
|
bool adult = parseBool(movie, 'adult');
|
|
String belongsToCollection = ''; //MISSING
|
|
double budget = 0; //MISSING
|
|
String homepage = ''; //MISSING
|
|
double revenue = 0; //MISSING
|
|
int runtime = 0; //MISSING
|
|
String tagline = ''; //MISSING
|
|
|
|
if (!movieIDsTmp.contains(movieID)) {
|
|
movieList.add(Movie(
|
|
movieID: movieID,
|
|
movieTitle: movieTitle,
|
|
originalTitle: originalTitle,
|
|
overview: overview,
|
|
releaseDate: releaseDate,
|
|
state: 0,
|
|
resolution: '',
|
|
backdropPath: backdropPath,
|
|
posterPath: posterPath,
|
|
languages: languages,
|
|
productionCountries: productionCountries,
|
|
productionCompanies: productionCompanies,
|
|
voteAverage: voteAverage,
|
|
voteCount: voteCount,
|
|
cast: cast,
|
|
crew: crew,
|
|
genre: genre,
|
|
localPath: localPath,
|
|
imdbID: imdbID,
|
|
originalLanguage: originalLanguage,
|
|
popularity: popularity,
|
|
adult: adult,
|
|
belongsToCollection: belongsToCollection,
|
|
budget: budget,
|
|
homepage: homepage,
|
|
revenue: revenue,
|
|
runtime: runtime,
|
|
tagline: tagline,
|
|
));
|
|
}
|
|
}
|
|
},
|
|
);
|
|
}
|
|
|
|
bool addMovies() {
|
|
bool somethingFound = false;
|
|
|
|
logger.i('addMovies');
|
|
|
|
for (int i = 0; i < movieList.length; i++) {
|
|
Movie movie = movieList[i];
|
|
if (movie.state == 1) {
|
|
somethingFound = true;
|
|
addMovie(movieList[i].movieID);
|
|
addMovieToList(movie);
|
|
}
|
|
}
|
|
addMovieFinished();
|
|
|
|
return somethingFound;
|
|
}
|
|
|
|
Future<bool> addMovie(int movieID) async {
|
|
String lang = 'de';
|
|
|
|
if (!searchGerman || searchEnglish) {
|
|
lang = 'en';
|
|
}
|
|
|
|
final tmdb = TMDB.TMDB(TMDB.ApiKeys(
|
|
'a33271b9e54cdcb9a80680eaf5522f1b', 'apiReadAccessTokenv4'));
|
|
|
|
final Map response = await tmdb.v3.movies.getDetails(
|
|
movieID,
|
|
language: lang,
|
|
appendToResponse: 'credits,external_ids',
|
|
);
|
|
|
|
Movie movie = Movie.fromJsonDynamic(response);
|
|
writeToDB(movie);
|
|
|
|
return true;
|
|
}
|
|
|
|
Future<bool> writeToDB(Movie movie) 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,
|
|
);
|
|
|
|
try {
|
|
/*final r = */await http.post(
|
|
url,
|
|
headers: <String, String>{
|
|
'Content-Type': 'application/json; charset=UTF-8',
|
|
},
|
|
body: jsonEncode(
|
|
<String, String>{
|
|
'module': 'movie',
|
|
'function': 'add',
|
|
'movieID': movie.movieID.toString(),
|
|
'movieTitle': movie.movieTitle,
|
|
'originalTitle': movie.originalTitle,
|
|
'overview': movie.overview,
|
|
'releaseDate': DateFormat('yyyy-MM-dd').format(movie.releaseDate),
|
|
'resolution': movie.resolution,
|
|
'state': movie.state.toString(),
|
|
'backdropPath': movie.backdropPath,
|
|
'languages': movie.languages,
|
|
'productionCountries': movie.productionCountries,
|
|
'productionCompanies': movie.productionCompanies,
|
|
'voteAverage': movie.voteAverage.toString(),
|
|
'voteCount': movie.voteCount.toString(),
|
|
'cast': movie.cast,
|
|
'crew': movie.crew,
|
|
'genre': movie.genre,
|
|
'localPath': movie.localPath,
|
|
'posterPath': movie.posterPath,
|
|
'imdbid': movie.imdbID,
|
|
'originalLanguage': movie.originalLanguage,
|
|
'popularity': movie.popularity.toString(),
|
|
'adult': movie.adult.toString(),
|
|
'belongsToCollection': movie.belongsToCollection,
|
|
'budget': movie.budget.toString(),
|
|
'homepage': movie.homepage,
|
|
'revenue': movie.revenue.toString(),
|
|
'runtime': movie.runtime.toString(),
|
|
'status': '',
|
|
'tagline': movie.tagline,
|
|
'video': ''
|
|
},
|
|
),
|
|
);
|
|
} catch (e) {
|
|
logger.e(e.toString());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|