474 lines
14 KiB
Dart
474 lines
14 KiB
Dart
import 'dart:convert';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:multimedia/widgets/movies/add/add_screen.dart';
|
|
import 'package:multimedia/widgets/movies/details/details_screen.dart';
|
|
import 'package:multimedia/widgets/movies/filter_box.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
import 'package:http/http.dart' as http;
|
|
|
|
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
|
|
import 'package:syncfusion_flutter_core/theme.dart';
|
|
|
|
import 'package:multimedia/data/movies.dart';
|
|
|
|
import 'package:multimedia/constants.dart';
|
|
|
|
import 'package:logger/logger.dart';
|
|
import 'package:multimedia/log_printer.dart';
|
|
|
|
class MoviesScreen extends StatefulWidget {
|
|
const MoviesScreen({
|
|
super.key,
|
|
});
|
|
|
|
@override
|
|
State<StatefulWidget> createState() => _MoviesScreenState();
|
|
}
|
|
|
|
class _MoviesScreenState extends State<MoviesScreen> {
|
|
final DataGridController _dataGridController = DataGridController();
|
|
late MovieDataSource movieDataSource;
|
|
List<GridColumn> _columns = [];
|
|
late List<Movie> _moviesList;
|
|
|
|
String searchText = '';
|
|
bool showInit = false;
|
|
bool showProg = false;
|
|
bool showDone = false;
|
|
|
|
Logger logger = getLogger();
|
|
|
|
Future<List<Movie>> generateMovieList() 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': 'movie',
|
|
'function': 'getList',
|
|
},
|
|
);
|
|
|
|
try {
|
|
final response = await http.get(url);
|
|
//LATER bool? error;
|
|
//LATER String? errorMessage;
|
|
|
|
Map<String, dynamic> movies = json.decode(response.body);
|
|
//LATER error = movies['error'];
|
|
//LATER errorMessage = movies['errmsg'];
|
|
var list = movies['data'];
|
|
|
|
List<Movie> moviesTmp =
|
|
await list.map<Movie>((json) => Movie.fromJson(json)).toList();
|
|
movieDataSource = MovieDataSource(moviesTmp);
|
|
|
|
_moviesList = moviesTmp;
|
|
|
|
return moviesTmp;
|
|
} catch (e) {
|
|
print(e.toString());
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
List<GridColumn> getColumns() {
|
|
return <GridColumn>[
|
|
GridColumn(
|
|
columnName: 'movieID',
|
|
visible: false,
|
|
width: 70,
|
|
label: Container(
|
|
padding: const EdgeInsets.all(16.0),
|
|
alignment: Alignment.centerLeft,
|
|
child: const Text('movieID'))),
|
|
GridColumn(
|
|
columnName: 'state',
|
|
visible: false,
|
|
width: 70,
|
|
label: Container(
|
|
padding: const EdgeInsets.all(16.0),
|
|
alignment: Alignment.centerLeft,
|
|
child: const Text('state'))),
|
|
GridColumn(
|
|
columnName: 'backdropPath',
|
|
visible: false,
|
|
width: 70,
|
|
label: Container(
|
|
padding: const EdgeInsets.all(16.0),
|
|
alignment: Alignment.centerLeft,
|
|
child: const Text('backdropPath'))),
|
|
GridColumn(
|
|
columnName: 'movieTitle',
|
|
columnWidthMode: ColumnWidthMode.auto,
|
|
label: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
alignment: Alignment.centerLeft,
|
|
child: const Text('Title'))),
|
|
GridColumn(
|
|
columnName: 'releaseDate',
|
|
columnWidthMode: ColumnWidthMode.auto,
|
|
label: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
alignment: Alignment.centerLeft,
|
|
child: const Text('First Aired'))),
|
|
GridColumn(
|
|
columnName: 'resolution',
|
|
columnWidthMode: ColumnWidthMode.auto,
|
|
label: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
alignment: Alignment.centerLeft,
|
|
child: const Text('Resolution'))),
|
|
GridColumn(
|
|
columnName: 'overview',
|
|
columnWidthMode: ColumnWidthMode.auto,
|
|
label: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
alignment: Alignment.centerLeft,
|
|
child: const Text('Overview'))),
|
|
];
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_columns = getColumns();
|
|
}
|
|
|
|
Future<void> showMovieDetails(int index) async {
|
|
DataGridRow row = movieDataSource.effectiveRows.elementAt(index);
|
|
List<DataGridCell<dynamic>> cells = row.getCells();
|
|
|
|
String movieID = cells[MovieColumn.movieID].value.toString();
|
|
bool found = false;
|
|
int movieIndex;
|
|
int realIndex;
|
|
|
|
movieDataSource.clearFilters();
|
|
|
|
realIndex = movieDataSource.rows.indexOf(row);
|
|
|
|
for (movieIndex = 0; movieIndex < _moviesList.length; movieIndex++) {
|
|
if (_moviesList[movieIndex].movieID == int.parse(movieID)) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found) {
|
|
final m = await Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (ctx) =>
|
|
MovieDetailsScreen(movie: _moviesList[movieIndex])));
|
|
|
|
if (m != null) {
|
|
_moviesList[movieIndex].movieTitle = m.movieTitle;
|
|
_moviesList[movieIndex].localPath = m.localPath;
|
|
_moviesList[movieIndex].resolution = m.resolution;
|
|
_moviesList[movieIndex].state = m.state;
|
|
Movie e = _moviesList[movieIndex];
|
|
|
|
movieDataSource._movieDataGridRows[realIndex] = DataGridRow(cells: [
|
|
DataGridCell<int>(columnName: 'movieID', value: e.movieID),
|
|
DataGridCell<int>(columnName: 'state', value: e.state),
|
|
DataGridCell<String>(
|
|
columnName: 'backdropPath', value: e.backdropPath),
|
|
DataGridCell<String>(columnName: 'movieTitle', value: e.movieTitle),
|
|
DataGridCell<String>(
|
|
columnName: 'releaseDate',
|
|
value: DateFormat('yyyy-MM-dd').format(e.releaseDate)),
|
|
DataGridCell<String>(columnName: 'resolution', value: e.resolution),
|
|
DataGridCell<String>(columnName: 'overview', value: e.overview),
|
|
]);
|
|
|
|
for (int i = 0; i < _columns.length; i++) {
|
|
movieDataSource.updateDataGridSource(
|
|
rowColumnIndex: RowColumnIndex(realIndex, i));
|
|
}
|
|
} else {}
|
|
filter();
|
|
}
|
|
}
|
|
|
|
void setFilter(String text, bool sInit, bool sProg, bool sDone) {
|
|
searchText = text;
|
|
showInit = sInit;
|
|
showProg = sProg;
|
|
showDone = sDone;
|
|
filter();
|
|
}
|
|
|
|
void filter() {
|
|
movieDataSource.clearFilters();
|
|
|
|
if (showInit)
|
|
movieDataSource.addFilter(
|
|
'state',
|
|
FilterCondition(
|
|
type: FilterType.equals,
|
|
value: 1,
|
|
filterOperator: FilterOperator.or),
|
|
);
|
|
|
|
if (showProg)
|
|
movieDataSource.addFilter(
|
|
'state',
|
|
FilterCondition(
|
|
type: FilterType.equals,
|
|
value: 2,
|
|
filterOperator: FilterOperator.or,
|
|
));
|
|
|
|
if (showDone)
|
|
movieDataSource.addFilter(
|
|
'state',
|
|
FilterCondition(
|
|
type: FilterType.equals,
|
|
value: 3,
|
|
filterOperator: FilterOperator.or,
|
|
));
|
|
|
|
movieDataSource.addFilter(
|
|
'movieTitle',
|
|
FilterCondition(
|
|
type: FilterType.beginsWith,
|
|
value: searchText,
|
|
filterOperator: FilterOperator.and,
|
|
filterBehavior: FilterBehavior.stringDataType,
|
|
));
|
|
}
|
|
|
|
late SfDataGrid dataGrid;
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text('Movies'),
|
|
actions: [
|
|
const VerticalDivider(
|
|
width: 10,
|
|
thickness: 3,
|
|
indent: 0,
|
|
endIndent: 0,
|
|
color: Colors.grey,
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.add_circle_outline),
|
|
tooltip: 'Add Movie',
|
|
onPressed: () {
|
|
addMovie();
|
|
},
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.update_outlined),
|
|
tooltip: 'Update movie',
|
|
onPressed: () {
|
|
updateMovies();
|
|
//todo
|
|
},
|
|
),
|
|
],
|
|
),
|
|
body: Column(children: [
|
|
MovieFilterBox(setFilter: setFilter),
|
|
Expanded(
|
|
child: FutureBuilder<Object>(
|
|
future: generateMovieList(),
|
|
builder: (context, data) {
|
|
if (data.hasData) {
|
|
dataGrid = 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);
|
|
},
|
|
);
|
|
|
|
return SfDataGridTheme(
|
|
data: const SfDataGridThemeData(
|
|
headerColor: Color(0xff009889),
|
|
),
|
|
child: dataGrid,
|
|
);
|
|
} else {
|
|
return const Center(
|
|
child: CircularProgressIndicator(
|
|
strokeWidth: 2,
|
|
value: 0.8,
|
|
),
|
|
);
|
|
}
|
|
},
|
|
),
|
|
),
|
|
]),
|
|
);
|
|
}
|
|
|
|
void addMovieToList(Movie movie) {
|
|
String movieTitle = movie.movieTitle.toUpperCase().replaceAll('Ä', 'a').replaceAll('Ö', 'ö').replaceAll('Ü', 'ü').replaceAll('ß', 'ss');
|
|
_moviesList.add(movie);
|
|
|
|
DataGridRow newRow = DataGridRow(cells: [
|
|
DataGridCell<int>(columnName: 'movieID', value: movie.movieID),
|
|
DataGridCell<int>(columnName: 'state', value: movie.state),
|
|
DataGridCell<String>(
|
|
columnName: 'backdropPath', value: movie.backdropPath),
|
|
DataGridCell<String>(columnName: 'movieTitle', value: movie.movieTitle),
|
|
DataGridCell<String>(
|
|
columnName: 'releaseDate',
|
|
value: DateFormat('yyyy-MM-dd').format(movie.releaseDate)),
|
|
DataGridCell<String>(columnName: 'resolution', value: movie.resolution),
|
|
DataGridCell<String>(columnName: 'overview', value: movie.overview),
|
|
]);
|
|
|
|
int rowNum = -1;
|
|
for (int i = 0; i < movieDataSource._movieDataGridRows.length; i++) {
|
|
DataGridRow tmpRow = movieDataSource._movieDataGridRows[i];
|
|
List<DataGridCell> tmpCells = tmpRow.getCells();
|
|
String tmpTitle = tmpCells[3].value.toString().toUpperCase().replaceAll('Ä', 'a').replaceAll('Ö', 'ö').replaceAll('Ü', 'ü').replaceAll('ß', 'ss');
|
|
|
|
if (tmpTitle.toUpperCase().compareTo(movieTitle) >= 0) {
|
|
rowNum = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (rowNum == -1) {
|
|
rowNum = movieDataSource._movieDataGridRows.length;
|
|
}
|
|
|
|
movieDataSource.rows.insert(rowNum, newRow);
|
|
movieDataSource.notifyListeners();
|
|
}
|
|
|
|
void addMovieFinished() {}
|
|
|
|
void addMovie() {
|
|
/*final m =*/ Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (ctx) =>
|
|
AddMovieScreen(addMovieToList, addMovieFinished)));
|
|
}
|
|
|
|
void searchMovie() {
|
|
logger.i('search movie');
|
|
}
|
|
|
|
void updateMovies() {
|
|
logger.i('update movies');
|
|
}
|
|
}
|
|
|
|
class MovieDataSource extends DataGridSource {
|
|
/// Creates the employee data source class with required details.
|
|
MovieDataSource(this.movies) {
|
|
buildDataGridRow();
|
|
}
|
|
|
|
void addDataGridRow(DataGridRow newRow) {
|
|
rows.add(newRow);
|
|
|
|
// To refresh the DataGrid based on CRUD operation.
|
|
notifyListeners();
|
|
}
|
|
|
|
Logger logger = getLogger();
|
|
|
|
void buildDataGridRow() {
|
|
_movieDataGridRows = movies
|
|
.map<DataGridRow>((e) => DataGridRow(cells: [
|
|
DataGridCell<int>(columnName: 'movieID', value: e.movieID),
|
|
DataGridCell<int>(columnName: 'state', value: e.state),
|
|
DataGridCell<String>(
|
|
columnName: 'backdropPath', value: e.backdropPath),
|
|
DataGridCell<String>(
|
|
columnName: 'movieTitle', value: e.movieTitle),
|
|
DataGridCell<String>(
|
|
columnName: 'releaseDate',
|
|
value: DateFormat('yyyy-MM-dd').format(e.releaseDate)),
|
|
DataGridCell<String>(
|
|
columnName: 'resolution', value: e.resolution),
|
|
DataGridCell<String>(columnName: 'overview', value: e.overview),
|
|
]))
|
|
.toList();
|
|
}
|
|
|
|
List<Movie> movies = [];
|
|
|
|
List<DataGridRow> _movieDataGridRows = [];
|
|
|
|
@override
|
|
List<DataGridRow> get rows => _movieDataGridRows;
|
|
|
|
@override
|
|
DataGridRowAdapter buildRow(DataGridRow row) {
|
|
return DataGridRowAdapter(
|
|
cells: row.getCells().map<Widget>((e) {
|
|
Color colorBG = Colors.white;
|
|
Color colorFG = Colors.black;
|
|
|
|
if (e.columnName == 'movieTitle') {
|
|
int state = row.getCells().toList()[MovieColumn.movieState].value;
|
|
|
|
if (state == 1) {
|
|
colorBG = StateColor.init;
|
|
} else if (state == 2) {
|
|
colorBG = StateColor.prog;
|
|
colorFG = Colors.white;
|
|
} else {
|
|
colorBG = StateColor.done;
|
|
}
|
|
}
|
|
|
|
return Container(
|
|
alignment: Alignment.centerLeft,
|
|
padding: const EdgeInsets.all(8.0),
|
|
color: colorBG,
|
|
child: Text(
|
|
e.value.toString(),
|
|
style: TextStyle(color: colorFG),
|
|
),
|
|
);
|
|
}).toList());
|
|
}
|
|
|
|
void updateDataGrid() {
|
|
notifyListeners();
|
|
}
|
|
|
|
void updateDataGridSource({required RowColumnIndex rowColumnIndex}) {
|
|
notifyDataSourceListeners(rowColumnIndex: rowColumnIndex);
|
|
}
|
|
}
|