diff --git a/lib/api/actor_api.dart b/lib/api/actor_api.dart index 659918b..4fcdf59 100644 --- a/lib/api/actor_api.dart +++ b/lib/api/actor_api.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import '../log/log.dart'; import '../types/actor.dart'; import 'api.dart'; @@ -10,3 +11,26 @@ Future> loadAllActors() async { final actors = d.map((e) => Actor.fromJson(e)).toList(growable: false); return actors; } + +Future> loadActorsOfVideo(int movieId) async { + final data = + await API.query("actor", "getActorsOfVideo", {'MovieId': movieId}); + if (data == 'null') { + return []; + } + final d = jsonDecode(data); + + List dta = (d as List).map((e) => Actor.fromJson(e)).toList(); + + return dta; +} + +Future addActorToVideo(int actorId, int movieId) async { + final data = await API.query( + "actor", "addActorToVideo", {'ActorId': actorId, 'MovieId': movieId}); + + final d = jsonDecode(data); + if (d["result"] != "success") { + Log.w("couldn't add actor to video"); + } +} diff --git a/lib/api/tag_api.dart b/lib/api/tag_api.dart new file mode 100644 index 0000000..2ec06e7 --- /dev/null +++ b/lib/api/tag_api.dart @@ -0,0 +1,23 @@ +import 'dart:convert'; + +import '../log/log.dart'; +import '../types/tag.dart'; +import 'api.dart'; + +Future> loadAllTags() async { + final data = await API.query("tags", "getAllTags", {}); + + final d = (jsonDecode(data) ?? []) as List; + final tags = d.map((e) => Tag.fromJson(e)).toList(growable: false); + return tags; +} + +Future addTagToVideo(int tagId, int movieId) async { + final data = + await API.query("tags", "addTag", {'TagId': tagId, 'MovieId': movieId}); + + final d = jsonDecode(data); + if (d["result"] != "success") { + Log.w("couldn't add actor to video"); + } +} diff --git a/lib/api/video_api.dart b/lib/api/video_api.dart index 6197061..b19c517 100644 --- a/lib/api/video_api.dart +++ b/lib/api/video_api.dart @@ -1,5 +1,11 @@ import 'dart:convert'; +import 'dart:math'; +import 'dart:typed_data'; +import '../log/log.dart'; +import '../types/actor.dart'; +import '../types/tag.dart'; +import '../types/video.dart'; import '../types/video_data.dart'; import 'api.dart'; @@ -10,3 +16,55 @@ Future loadVideoData(int videoId) async { final video = VideoData.fromJson(d); return video; } + +Future> loadVideo(Tag? tag, int filterIdx) async { + final data = await API + .query("video", "getMovies", {'Tag': tag?.tagId ?? 1, 'Sort': filterIdx}); + + final d = jsonDecode(data); + + List dta = + (d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList(); + + return dta; +} + +Future> loadShuffledVideos(int nr) async { + final data = await API.query("video", "getRandomMovies", + {'Number': nr, 'Seed': Random().nextInt(0x7fffffff)}); + + final d = jsonDecode(data); + + List dta = + (d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList(); + + return dta; +} + +Future> loadVideoByActor(Actor actor) async { + final data = + await API.query("actor", "getActorInfo", {'ActorId': actor.actorId}); + + final d = jsonDecode(data); + + List dta = + (d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList(); + + return dta; +} + +Future addLike(int movieId) async { + final data = await API.query("video", "addLike", {'MovieId': movieId}); + final d = jsonDecode(data); + if (d["result"] != 'success') { + Log.w(d); + } + + return d["result"] == 'success'; +} + +Future fetchThumbnail(int movieId) async { + final base64str = + await API.query("video", "readThumbnail", {'Movieid': movieId}); + return base64Decode(base64str.substring(23)); +} diff --git a/lib/app.dart b/lib/app.dart index b82e6b8..c60e890 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -12,6 +12,7 @@ class AppScrollBehavior extends MaterialScrollBehavior { Set get dragDevices => { PointerDeviceKind.touch, PointerDeviceKind.mouse, + PointerDeviceKind.trackpad }; } diff --git a/lib/db/database.dart b/lib/db/database.dart index b3af8bf..e3f9d58 100644 --- a/lib/db/database.dart +++ b/lib/db/database.dart @@ -25,12 +25,8 @@ class Db { } _db = await openDatabase( - // Set the path to the database. Note: Using the `join` function from the - // `path` package is best practice to ensure the path is correctly - // constructed for each platform. dbpath, onCreate: (db, version) { - // Run the CREATE TABLE statement on the database. return db.execute( 'CREATE TABLE previews(id INTEGER PRIMARY KEY, thumbnail BLOB)', ); diff --git a/lib/dialog/add_actor_dialog.dart b/lib/dialog/add_actor_dialog.dart index 2df3907..ee1df58 100644 --- a/lib/dialog/add_actor_dialog.dart +++ b/lib/dialog/add_actor_dialog.dart @@ -1,10 +1,6 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; import '../api/actor_api.dart'; -import '../api/api.dart'; -import '../log/log.dart'; import '../screen_loading.dart'; import '../types/actor.dart'; @@ -19,16 +15,6 @@ class AddActorDialog extends StatefulWidget { class _AddActorDialogState extends State { late Future> actors = loadAllActors(); - Future addActorToVideo(int actorId) async { - final data = await API.query("actor", "addActorToVideo", - {'ActorId': actorId, 'MovieId': widget.movieId}); - - final d = jsonDecode(data); - if (d["result"] != "success") { - Log.w("couldn't add actor to video"); - } - } - @override void initState() { super.initState(); @@ -52,7 +38,7 @@ class _AddActorDialogState extends State { .map((e) => ListTile( title: Text(e.name), onTap: () async { - await addActorToVideo(e.actorId); + await addActorToVideo(e.actorId, widget.movieId); Navigator.pop(context, e); }, )) diff --git a/lib/dialog/add_tag_dialog.dart b/lib/dialog/add_tag_dialog.dart index 754268a..8cd4f6b 100644 --- a/lib/dialog/add_tag_dialog.dart +++ b/lib/dialog/add_tag_dialog.dart @@ -1,9 +1,6 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; -import '../api/api.dart'; -import '../log/log.dart'; +import '../api/tag_api.dart'; import '../screen_loading.dart'; import '../types/tag.dart'; @@ -18,24 +15,6 @@ class AddTagDialog extends StatefulWidget { class _AddTagDialogState extends State { late Future> tags = loadAllTags(); - Future> loadAllTags() async { - final data = await API.query("tags", "getAllTags", {}); - - final d = (jsonDecode(data) ?? []) as List; - final tags = d.map((e) => Tag.fromJson(e)).toList(growable: false); - return tags; - } - - Future addTagToVideo(int tagId) async { - final data = await API - .query("tags", "addTag", {'TagId': tagId, 'MovieId': widget.movieId}); - - final d = jsonDecode(data); - if (d["result"] != "success") { - Log.w("couldn't add actor to video"); - } - } - @override void initState() { super.initState(); @@ -60,7 +39,7 @@ class _AddTagDialogState extends State { (e) => ListTile( title: Text(e.tagName), onTap: () async { - await addTagToVideo(e.tagId); + await addTagToVideo(e.tagId, widget.movieId); Navigator.pop(context, e); }, ), diff --git a/lib/navigation/categorie_screen.dart b/lib/navigation/categorie_screen.dart index 603e519..c399408 100644 --- a/lib/navigation/categorie_screen.dart +++ b/lib/navigation/categorie_screen.dart @@ -1,11 +1,9 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; -import 'package:openmediacentermobile/preview/tag_tile.dart'; +import '../api/tag_api.dart'; +import '../preview/tag_tile.dart'; import '../drawer/my_drawer.dart'; import '../screen_loading.dart'; -import '../api/api.dart'; import '../types/tag.dart'; class CategorieScreen extends StatefulWidget { @@ -18,18 +16,10 @@ class CategorieScreen extends StatefulWidget { class _CategorieScreenState extends State { late Future> _categories; - Future> loadVideoData() async { - final data = await API.query("tags", "getAllTags", {}); - - final d = (jsonDecode(data) ?? []) as List; - final tags = d.map((e) => Tag.fromJson(e)).toList(growable: false); - return tags; - } - @override void initState() { super.initState(); - _categories = loadVideoData(); + _categories = loadAllTags(); } @override diff --git a/lib/navigation/settings_screen.dart b/lib/navigation/settings_screen.dart index d0779de..cc65f5e 100644 --- a/lib/navigation/settings_screen.dart +++ b/lib/navigation/settings_screen.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:openmediacentermobile/utils/file_formatter.dart'; +import '../utils/file_formatter.dart'; import '../api/token.dart'; import '../db/database.dart'; @@ -15,6 +15,7 @@ class SettingsScreen extends StatefulWidget { class _SettingsScreenState extends State { int dbsize = 0; + String serverUrl = ""; @override void initState() { @@ -22,6 +23,10 @@ class _SettingsScreenState extends State { Db().getDbSize().then((v) => setState(() { dbsize = v; })); + + Token.getInstance().getToken().then((value) => setState(() { + serverUrl = value?.domain ?? "unknown"; + })); } @override @@ -34,6 +39,7 @@ class _SettingsScreenState extends State { ), body: Column( children: [ + Text("Current server: $serverUrl"), ElevatedButton( onPressed: () async { await Db().clear(); diff --git a/lib/navigation/shuffle_screen.dart b/lib/navigation/shuffle_screen.dart index 45b9df2..8256013 100644 --- a/lib/navigation/shuffle_screen.dart +++ b/lib/navigation/shuffle_screen.dart @@ -1,12 +1,9 @@ -import 'dart:convert'; -import 'dart:math'; import 'package:flutter/material.dart'; +import '../api/video_api.dart'; import '../drawer/my_drawer.dart'; import '../preview/preview_grid.dart'; -import '../api/api.dart'; import '../utils/platform.dart'; -import '../types/video.dart'; class ShuffleScreen extends StatefulWidget { const ShuffleScreen({Key? key}) : super(key: key); @@ -16,18 +13,6 @@ class ShuffleScreen extends StatefulWidget { } class _ShuffleScreenState extends State { - Future> loadData(int nr) async { - final data = await API.query("video", "getRandomMovies", - {'Number': nr, 'Seed': Random().nextInt(0x7fffffff)}); - - final d = jsonDecode(data); - - List dta = - (d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList(); - - return dta; - } - @override Widget build(BuildContext context) { double width = MediaQuery.of(context).size.width; @@ -38,7 +23,8 @@ class _ShuffleScreenState extends State { ), body: PreviewGrid( videoLoader: () { - return loadData((isTV() ? width ~/ 200 : width ~/ 275) * 2); + return loadShuffledVideos( + (isTV() ? width ~/ 200 : width ~/ 275) * 2); }, footerBuilder: (state) => Column( children: [ diff --git a/lib/navigation/video_feed.dart b/lib/navigation/video_feed.dart index 8e3266d..39f1de4 100644 --- a/lib/navigation/video_feed.dart +++ b/lib/navigation/video_feed.dart @@ -1,12 +1,9 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; +import '../api/video_api.dart'; -import '../api/api.dart'; import '../drawer/my_drawer.dart'; import '../preview/preview_grid.dart'; import '../types/tag.dart'; -import '../types/video.dart'; enum FilterTypes { DATE, LIKES, RANDOM, NAMES, LENGTH } @@ -24,18 +21,6 @@ class VideoFeedState extends State { FilterTypes filterSelection = FilterTypes.DATE; Key _refreshKey = UniqueKey(); - Future> loadData() async { - final data = await API.query("video", "getMovies", - {'Tag': widget.tag?.tagId ?? 1, 'Sort': filterSelection.index}); - - final d = jsonDecode(data); - - List dta = - (d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList(); - - return dta; - } - @override Widget build(BuildContext context) { return Scaffold( @@ -80,7 +65,7 @@ class VideoFeedState extends State { ), body: PreviewGrid( key: _refreshKey, - videoLoader: () => loadData(), + videoLoader: () => loadVideo(widget.tag, filterSelection.index), ), drawer: widget.tag == null ? MyDrawer() : null); } diff --git a/lib/preview/actor_feed.dart b/lib/preview/actor_feed.dart index 8614394..5d792ea 100644 --- a/lib/preview/actor_feed.dart +++ b/lib/preview/actor_feed.dart @@ -1,11 +1,8 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; -import '../api/api.dart'; +import '../api/video_api.dart'; import 'preview_grid.dart'; import '../types/actor.dart'; -import '../types/video.dart'; class ActorFeed extends StatefulWidget { const ActorFeed({Key? key, required this.actor}) : super(key: key); @@ -16,22 +13,10 @@ class ActorFeed extends StatefulWidget { } class _ActorFeedState extends State { - Future> loadData() async { - final data = await API - .query("actor", "getActorInfo", {'ActorId': widget.actor.actorId}); - - final d = jsonDecode(data); - - List dta = - (d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList(); - - return dta; - } - @override Widget build(BuildContext context) { return PreviewGrid( - videoLoader: () => loadData(), + videoLoader: () => loadVideoByActor(widget.actor), ); } } diff --git a/lib/preview/actor_tile.dart b/lib/preview/actor_tile.dart index 4f3b06e..8a0543c 100644 --- a/lib/preview/actor_tile.dart +++ b/lib/preview/actor_tile.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:openmediacentermobile/preview/actor_feed.dart'; +import '../preview/actor_feed.dart'; import '../utils/platform.dart'; import '../types/actor.dart'; diff --git a/lib/preview/preview_grid.dart b/lib/preview/preview_grid.dart index a87a310..214fa7b 100644 --- a/lib/preview/preview_grid.dart +++ b/lib/preview/preview_grid.dart @@ -56,15 +56,15 @@ class _PreviewGridState extends State { builder: (BuildContext context, AsyncSnapshot> snapshot) { if (snapshot.hasError) { - return Column( - children: [ - Text("Error"), - TextButton( - onPressed: () { - loadData(); - }, - child: Text("Reload page")) - ], + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Error"), + TextButton( + onPressed: () => loadData(), child: Text("Reload page")) + ], + ), ); } else if (snapshot.hasData) { return _mainGrid(snapshot.data!, width); diff --git a/lib/preview/preview_tile.dart b/lib/preview/preview_tile.dart index b6a91eb..6ee192a 100644 --- a/lib/preview/preview_tile.dart +++ b/lib/preview/preview_tile.dart @@ -1,9 +1,8 @@ -import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; -import '../api/api.dart'; +import '../api/video_api.dart'; import '../db/database.dart'; import '../log/log.dart'; import '../utils/platform.dart'; @@ -51,23 +50,17 @@ class _PreviewTileState extends State { ); } - Future _fetchThumbnail(int id) async { - final base64str = - await API.query("video", "readThumbnail", {'Movieid': id}); - return base64Decode(base64str.substring(23)); - } - Future loadData() async { Uint8List data; final id = widget.dta.id; if (kIsWeb) { - data = await _fetchThumbnail(id); + data = await fetchThumbnail(id); } else { final List> prev = await Db().db().query('previews', where: "id=$id"); if (prev.isEmpty) { - data = await _fetchThumbnail(id); + data = await fetchThumbnail(id); insert(id, data); Log.d("Adding $id to db"); } else { diff --git a/lib/video_screen/info_view.dart b/lib/video_screen/info_view.dart index 20c8333..cb2ac29 100644 --- a/lib/video_screen/info_view.dart +++ b/lib/video_screen/info_view.dart @@ -1,6 +1,5 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; +import '../api/actor_api.dart'; import '../api/video_api.dart'; import '../dialog/add_actor_dialog.dart'; import '../dialog/add_tag_dialog.dart'; @@ -8,9 +7,6 @@ import '../navigation/video_feed.dart'; import '../screen_loading.dart'; import '../types/video_data.dart'; import '../preview/actor_tile.dart'; - -import '../api/api.dart'; -import '../log/log.dart'; import '../types/actor.dart'; class InfoView extends StatefulWidget { @@ -29,7 +25,7 @@ class _InfoViewState extends State { void initState() { super.initState(); setState(() { - _data = loadData(); + _data = loadActorsOfVideo(widget.videoId); vdata = loadVideoData(widget.videoId); }); } @@ -39,19 +35,6 @@ class _InfoViewState extends State { super.didUpdateWidget(oldWidget); } - Future> loadData() async { - final data = await API - .query("actor", "getActorsOfVideo", {'MovieId': widget.videoId}); - if (data == 'null') { - return []; - } - final d = jsonDecode(data); - - List dta = (d as List).map((e) => Actor.fromJson(e)).toList(); - - return dta; - } - @override Widget build(BuildContext context) { return FutureBuilder( @@ -71,15 +54,10 @@ class _InfoViewState extends State { children: [ IconButton( onPressed: () async { - final data = await API.query("video", "addLike", - {'MovieId': videoData.movieId}); - final d = jsonDecode(data); - if (d["result"] != 'success') { - Log.w(d); - } - setState(() { - vdata = loadVideoData(widget.videoId); - }); + if (await addLike(videoData.movieId)) + setState(() { + vdata = loadVideoData(widget.videoId); + }); }, icon: Icon(Icons.thumb_up)), TextButton( @@ -90,9 +68,8 @@ class _InfoViewState extends State { movieId: videoData.movieId, ), ); - Log.d("finished dialog"); setState(() { - _data = loadData(); + _data = loadActorsOfVideo(widget.videoId); }); }, child: Text("Add Actor"), @@ -105,7 +82,6 @@ class _InfoViewState extends State { movieId: videoData.movieId, ), ); - Log.d("finished dialog"); setState(() { vdata = loadVideoData(widget.videoId); }); diff --git a/lib/video_screen/videoscreen.dart b/lib/video_screen/videoscreen.dart index f5d1c08..0dd4832 100644 --- a/lib/video_screen/videoscreen.dart +++ b/lib/video_screen/videoscreen.dart @@ -92,7 +92,7 @@ class _VideoScreenState extends State { child: GestureDetector( onPanDown: (details) async { if (_appBarVisible) { - await Future.delayed(Duration(milliseconds: 100)); + await Future.delayed(Duration(milliseconds: 300)); setState(() { _appBarVisible = false; });