Movie Search

This commit is contained in:
2024-11-20 23:21:32 +01:00
parent 1483ec80f2
commit 68efd08a8a
8 changed files with 393 additions and 183 deletions
+9
View File
@@ -5,10 +5,12 @@ class CheckboxWithLabel extends StatefulWidget {
super.key,
required String this.label,
required this.callback,
this.state = false,
});
final String label;
final Function(bool state) callback;
final bool state;
@override
State<CheckboxWithLabel> createState() => _CheckboxWithLabelState();
@@ -17,6 +19,13 @@ class CheckboxWithLabel extends StatefulWidget {
class _CheckboxWithLabelState extends State<CheckboxWithLabel> {
bool isChecked = false;
@override
void initState() {
// TODO: implement initState
super.initState();
isChecked = widget.state;
}
@override
Widget build(BuildContext context) {
Color getColor(Set<WidgetState> states) {
+87 -26
View File
@@ -1,9 +1,10 @@
import 'package:accordion/accordion.dart';
import 'package:flutter/material.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:tmdb_api/tmdb_api.dart' as TMDB;
@@ -22,13 +23,17 @@ class _AddMovieScreenState extends State<AddMovieScreen> {
Logger logger = getLogger();
String movieTitleSearch = '';
String yearSearch = '';
bool includeAdult = false;
List<Movie> movieList = [];
late MovieSearchList movieSearchList;
static const headerStyle = TextStyle(
color: Color(0xffffffff), fontSize: 18, fontWeight: FontWeight.bold);
bool advancedOptionsOpen = false;
@override
Widget build(BuildContext context) {
movieSearchList = MovieSearchList(movieList: movieList);
@@ -37,8 +42,38 @@ class _AddMovieScreenState extends State<AddMovieScreen> {
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: 'Save changes',
onPressed: () {
// if (save()) {
// Navigator.pop(context, movieDetails);
// }
},
),
IconButton(
icon: const Icon(Icons.highlight_off),
tooltip: 'Revert changes',
onPressed: () {
// Navigator.pop(context, null);
},
),
],
),
body: Column(
children: [
Row(
children: [
SizedBox(
width: 20,
),
SizedBox(
width: 250,
child: TextField(
@@ -77,34 +112,58 @@ class _AddMovieScreenState extends State<AddMovieScreen> {
),
],
),
const VerticalDivider(
width: 10,
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,
indent: 0,
endIndent: 0,
color: Colors.grey,
),
IconButton(
icon: const Icon(Icons.check_circle_outline),
tooltip: 'Save changes',
onPressed: () {
// if (save()) {
// Navigator.pop(context, movieDetails);
// }
},
),
IconButton(
icon: const Icon(Icons.highlight_off),
tooltip: 'Revert changes',
onPressed: () {
// Navigator.pop(context, null);
},
Expanded(
child: MovieSearchList(
movieList: movieList,
),
),
],
),
body: MovieSearchList(
movieList: movieList,
),
);
}
void includeAdultCallback(bool state) {
includeAdult = state;
logger.i('Include Adult: ${includeAdult}');
}
Widget advancedOptions() {
return CheckboxWithLabel(
label: 'Include Adult',
callback: includeAdultCallback,
state: includeAdult,
);
}
@@ -148,15 +207,17 @@ class _AddMovieScreenState extends State<AddMovieScreen> {
return;
}
int year = int.tryParse(yearSearch) ?? 0;
logger.i('Wir suchen ...');
final tmdb = TMDB.TMDB(TMDB.ApiKeys(
'a33271b9e54cdcb9a80680eaf5522f1b', 'apiReadAccessTokenv4'));
logger.i('IncludeAdult: ${includeAdult}');
final response = await tmdb.v3.search.queryMovies(
movieTitleSearch,
year: year,
includeAdult: includeAdult,
language: 'de',
);
List<dynamic> movies = response['results'];
+85 -34
View File
@@ -45,42 +45,93 @@ class MovieFilterBox extends StatelessWidget {
callSetFilter();
}
Widget buildScreen(BuildContext context) {
double width = MediaQuery.sizeOf(context).width;
if (width < 500.0) {
return Column(
children: [
Row(
children: [
const SizedBox(
width: 20,
),
SizedBox(
width: 250,
child: TextField(
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: 'Movie Title',
),
onChanged: (text) {
textCallback(text);
},
),
),
],
),
Row(
children: [
const SizedBox(
width: 20,
),
CheckboxWithLabel(
label: 'Init',
callback: initCallback,
),
CheckboxWithLabel(
label: 'Progress',
callback: progCallback,
),
CheckboxWithLabel(
label: 'Done',
callback: doneCallback,
),
],
),
],
);
} else {
return Row(
children: [
const SizedBox(
width: 20,
),
SizedBox(
width: 250,
child: TextField(
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: 'Movie Title',
),
onChanged: (text) {
textCallback(text);
},
),
),
const SizedBox(
width: 20,
),
CheckboxWithLabel(
label: 'Init',
callback: initCallback,
),
CheckboxWithLabel(
label: 'Progress',
callback: progCallback,
),
CheckboxWithLabel(
label: 'Done',
callback: doneCallback,
),
],
);
}
}
@override
Widget build(BuildContext context) {
return Row(
children: [
const SizedBox(
width: 20,
),
SizedBox(
width: 250,
child: TextField(
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: 'Movie Title',
),
onChanged: (text) {
textCallback(text);
},
),
),
const SizedBox(
width: 20,
),
CheckboxWithLabel(
label: 'Init',
callback: initCallback,
),
CheckboxWithLabel(
label: 'Progress',
callback: progCallback,
),
CheckboxWithLabel(
label: 'Done',
callback: doneCallback,
),
],
);
return buildScreen(context);
}
void callSetFilter() {
+51 -46
View File
@@ -267,7 +267,6 @@ class _MoviesScreenState extends State<MoviesScreen> {
appBar: AppBar(
title: Text('Movies'),
actions: [
MovieFilterBox(setFilter: setFilter),
const VerticalDivider(
width: 10,
thickness: 3,
@@ -295,57 +294,63 @@ class _MoviesScreenState extends State<MoviesScreen> {
),
],
),
body: FutureBuilder<Object>(
future: generateMovieList(),
builder: (context, data) {
return data.hasData
? SfDataGridTheme(
data: const SfDataGridThemeData(
headerColor: Color(0xff009889),
),
child: SfDataGrid(
source: movieDataSource,
selectionMode: SelectionMode.single,
navigationMode: GridNavigationMode.row,
columns: _columns,
controller: _dataGridController,
columnWidthMode: ColumnWidthMode.auto,
columnWidthCalculationRange:
ColumnWidthCalculationRange.allRows,
onCellTap: (DataGridCellTapDetails details) {
int index = details.rowColumnIndex.rowIndex - 1;
if (index < 0) {
return;
}
showMovieDetails(index);
},
onCellDoubleTap: (DataGridCellDoubleTapDetails details) {
print(details.rowColumnIndex);
},
onCellLongPress: (DataGridCellLongPressDetails details) {
print(details.rowColumnIndex);
},
onCellSecondaryTap: (DataGridCellTapDetails details) {
print(details.rowColumnIndex);
},
),
)
: const Center(
child: CircularProgressIndicator(
strokeWidth: 2,
value: 0.8,
),
);
},
),
body: Column(children: [
MovieFilterBox(setFilter: setFilter),
Expanded(
child: FutureBuilder<Object>(
future: generateMovieList(),
builder: (context, data) {
return data.hasData
? SfDataGridTheme(
data: const SfDataGridThemeData(
headerColor: Color(0xff009889),
),
child: SfDataGrid(
source: movieDataSource,
selectionMode: SelectionMode.single,
navigationMode: GridNavigationMode.row,
columns: _columns,
controller: _dataGridController,
columnWidthMode: ColumnWidthMode.auto,
columnWidthCalculationRange:
ColumnWidthCalculationRange.allRows,
onCellTap: (DataGridCellTapDetails details) {
int index = details.rowColumnIndex.rowIndex - 1;
if (index < 0) {
return;
}
showMovieDetails(index);
},
onCellDoubleTap:
(DataGridCellDoubleTapDetails details) {
print(details.rowColumnIndex);
},
onCellLongPress:
(DataGridCellLongPressDetails details) {
print(details.rowColumnIndex);
},
onCellSecondaryTap: (DataGridCellTapDetails details) {
print(details.rowColumnIndex);
},
),
)
: const Center(
child: CircularProgressIndicator(
strokeWidth: 2,
value: 0.8,
),
);
},
),
),
]),
);
}
void addMovie() {
final m = Navigator.push(
context, MaterialPageRoute(builder: (ctx) => AddMovieScreen()));
}
}
void searchMovie() {
logger.i('search movie');
+85 -34
View File
@@ -45,42 +45,93 @@ class TVShowFilterBox extends StatelessWidget {
callSetFilter();
}
Widget buildScreen(BuildContext context) {
double width = MediaQuery.sizeOf(context).width;
if (width < 500.0) {
return Column(
children: [
Row(
children: [
const SizedBox(
width: 20,
),
SizedBox(
width: 250,
child: TextField(
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: 'TVShow Title',
),
onChanged: (text) {
textCallback(text);
},
),
),
],
),
Row(
children: [
const SizedBox(
width: 20,
),
CheckboxWithLabel(
label: 'Init',
callback: initCallback,
),
CheckboxWithLabel(
label: 'Progress',
callback: progCallback,
),
CheckboxWithLabel(
label: 'Done',
callback: doneCallback,
),
],
),
],
);
} else {
return Row(
children: [
const SizedBox(
width: 20,
),
SizedBox(
width: 250,
child: TextField(
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: 'TVShow Title',
),
onChanged: (text) {
textCallback(text);
},
),
),
const SizedBox(
width: 20,
),
CheckboxWithLabel(
label: 'Init',
callback: initCallback,
),
CheckboxWithLabel(
label: 'Progress',
callback: progCallback,
),
CheckboxWithLabel(
label: 'Done',
callback: doneCallback,
),
],
);
}
}
@override
Widget build(BuildContext context) {
return Row(
children: [
const SizedBox(
width: 20,
),
SizedBox(
width: 250,
child: TextField(
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: 'TVShow Title',
),
onChanged: (text) {
textCallback(text);
},
),
),
const SizedBox(
width: 20,
),
CheckboxWithLabel(
label: 'Init',
callback: initCallback,
),
CheckboxWithLabel(
label: 'Progress',
callback: progCallback,
),
CheckboxWithLabel(
label: 'Done',
callback: doneCallback,
),
],
);
return buildScreen(context);
}
void callSetFilter() {
+51 -43
View File
@@ -363,7 +363,6 @@ class _TVShowsScreenState extends State<TVShowsScreen> {
appBar: AppBar(
title: Text('TV Shows'),
actions: [
TVShowFilterBox(setFilter: setFilter),
const VerticalDivider(
width: 10,
thickness: 3,
@@ -399,48 +398,57 @@ class _TVShowsScreenState extends State<TVShowsScreen> {
),
],
),
body: FutureBuilder<Object>(
future: generateTVShowList(),
builder: (context, data) {
return data.hasData
? SfDataGridTheme(
data: const SfDataGridThemeData(
headerColor: Color(0xff009889),
),
child: SfDataGrid(
source: tvshowDataSource,
selectionMode: SelectionMode.single,
navigationMode: GridNavigationMode.row,
columns: _columns,
controller: _dataGridController,
columnWidthMode: ColumnWidthMode.auto,
columnWidthCalculationRange:
ColumnWidthCalculationRange.allRows,
onCellTap: (DataGridCellTapDetails details) {
int index = details.rowColumnIndex.rowIndex - 1;
if (index < 0) {
return;
}
showTVShowDetails(index);
},
onCellDoubleTap: (DataGridCellDoubleTapDetails details) {
print(details.rowColumnIndex);
},
onCellLongPress: (DataGridCellLongPressDetails details) {
print(details.rowColumnIndex);
},
onCellSecondaryTap: (DataGridCellTapDetails details) {
print(details.rowColumnIndex);
},
),
)
: const Center(
child: CircularProgressIndicator(
strokeWidth: 2,
value: 0.8,
),
);
},
body: Column(
children: [
TVShowFilterBox(setFilter: setFilter),
Expanded(
child: FutureBuilder<Object>(
future: generateTVShowList(),
builder: (context, data) {
return data.hasData
? SfDataGridTheme(
data: const SfDataGridThemeData(
headerColor: Color(0xff009889),
),
child: SfDataGrid(
source: tvshowDataSource,
selectionMode: SelectionMode.single,
navigationMode: GridNavigationMode.row,
columns: _columns,
controller: _dataGridController,
columnWidthMode: ColumnWidthMode.auto,
columnWidthCalculationRange:
ColumnWidthCalculationRange.allRows,
onCellTap: (DataGridCellTapDetails details) {
int index = details.rowColumnIndex.rowIndex - 1;
if (index < 0) {
return;
}
showTVShowDetails(index);
},
onCellDoubleTap:
(DataGridCellDoubleTapDetails details) {
print(details.rowColumnIndex);
},
onCellLongPress:
(DataGridCellLongPressDetails details) {
print(details.rowColumnIndex);
},
onCellSecondaryTap: (DataGridCellTapDetails details) {
print(details.rowColumnIndex);
},
),
)
: const Center(
child: CircularProgressIndicator(
strokeWidth: 2,
value: 0.8,
),
);
},
),
),
],
),
);
}
+24
View File
@@ -1,6 +1,14 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
accordion:
dependency: "direct main"
description:
name: accordion
sha256: "0eca3d1c619c6df63d6e384010fd2ef1164e7385d7102f88a6b56f658f160cd0"
url: "https://pub.dev"
source: hosted
version: "2.6.0"
async:
dependency: transitive
description:
@@ -128,6 +136,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
get:
dependency: transitive
description:
name: get
sha256: e4e7335ede17452b391ed3b2ede016545706c01a02292a6c97619705e7d2a85e
url: "https://pub.dev"
source: hosted
version: "4.6.6"
google_fonts:
dependency: "direct main"
description:
@@ -296,6 +312,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.8"
scroll_to_index:
dependency: transitive
description:
name: scroll_to_index
sha256: b707546e7500d9f070d63e5acf74fd437ec7eeeb68d3412ef7b0afada0b4f176
url: "https://pub.dev"
source: hosted
version: "3.0.1"
shared_preferences:
dependency: "direct main"
description:
+1
View File
@@ -44,6 +44,7 @@ dependencies:
transparent_image: ^2.0.1
logger: ^2.4.0
tmdb_api: ^2.2.0
accordion: ^2.6.0
dev_dependencies: