addactor, addtag dialogs

This commit is contained in:
lukas-heiligenbrunner 2022-08-30 23:25:21 +02:00
parent b0f913f8d1
commit 405d7e420e
10 changed files with 302 additions and 64 deletions

12
lib/api/actor_api.dart Normal file
View File

@ -0,0 +1,12 @@
import 'dart:convert';
import '../types/actor.dart';
import 'api.dart';
Future<List<Actor>> loadAllActors() async {
final data = await API.query("actor", "getAllActors", {});
final d = (jsonDecode(data) ?? []) as List<dynamic>;
final actors = d.map((e) => Actor.fromJson(e)).toList(growable: false);
return actors;
}

12
lib/api/video_api.dart Normal file
View File

@ -0,0 +1,12 @@
import 'dart:convert';
import '../types/video_data.dart';
import 'api.dart';
Future<VideoData> loadVideoData(int videoId) async {
final data = await API.query("video", "loadVideo", {'MovieId': videoId});
final d = jsonDecode(data);
final video = VideoData.fromJson(d);
return video;
}

View File

@ -0,0 +1,67 @@
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';
class AddActorDialog extends StatefulWidget {
const AddActorDialog({Key? key, required this.movieId}) : super(key: key);
final int movieId;
@override
State<AddActorDialog> createState() => _AddActorDialogState();
}
class _AddActorDialogState extends State<AddActorDialog> {
late Future<List<Actor>> actors = loadAllActors();
Future<void> 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();
}
@override
Widget build(BuildContext context) {
return AlertDialog(
scrollable: true,
title: Text("Add Actor"),
content: FutureBuilder(
future: actors,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text("Error");
} else if (snapshot.hasData) {
final data = snapshot.data! as List<Actor>;
return Column(
mainAxisSize: MainAxisSize.min,
children: data
.map((e) => ListTile(
title: Text(e.name),
onTap: () async {
await addActorToVideo(e.actorId);
Navigator.pop(context, e);
},
))
.toList(),
);
} else {
return ScreenLoading();
}
},
));
}
}

View File

@ -0,0 +1,76 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import '../api/api.dart';
import '../log/log.dart';
import '../screen_loading.dart';
import '../types/tag.dart';
class AddTagDialog extends StatefulWidget {
const AddTagDialog({Key? key, required this.movieId}) : super(key: key);
final int movieId;
@override
State<AddTagDialog> createState() => _AddTagDialogState();
}
class _AddTagDialogState extends State<AddTagDialog> {
late Future<List<Tag>> tags = loadAllTags();
Future<List<Tag>> loadAllTags() async {
final data = await API.query("tags", "getAllTags", {});
final d = (jsonDecode(data) ?? []) as List<dynamic>;
final tags = d.map((e) => Tag.fromJson(e)).toList(growable: false);
return tags;
}
Future<void> 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();
}
@override
Widget build(BuildContext context) {
return AlertDialog(
scrollable: true,
title: Text("Add Tag"),
content: FutureBuilder(
future: tags,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text("Error");
} else if (snapshot.hasData) {
final data = snapshot.data! as List<Tag>;
return Column(
mainAxisSize: MainAxisSize.min,
children: data
.map(
(e) => ListTile(
title: Text(e.tagName),
onTap: () async {
await addTagToVideo(e.tagId);
Navigator.pop(context, e);
},
),
)
.toList(),
);
} else {
return ScreenLoading();
}
},
));
}
}

View File

@ -1,11 +1,9 @@
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:openmediacentermobile/types/actor.dart'; import 'package:openmediacentermobile/types/actor.dart';
import 'package:openmediacentermobile/preview/actor_tile.dart'; import 'package:openmediacentermobile/preview/actor_tile.dart';
import '../DrawerPage.dart'; import '../DrawerPage.dart';
import '../api/api.dart'; import '../api/actor_api.dart';
import '../screen_loading.dart'; import '../screen_loading.dart';
class ActorScreen extends StatefulWidget { class ActorScreen extends StatefulWidget {
@ -18,18 +16,10 @@ class ActorScreen extends StatefulWidget {
class _ActorScreenState extends State<ActorScreen> { class _ActorScreenState extends State<ActorScreen> {
late Future<List<Actor>> _categories; late Future<List<Actor>> _categories;
Future<List<Actor>> loadVideoData() async {
final data = await API.query("actor", "getAllActors", {});
final d = (jsonDecode(data) ?? []) as List<dynamic>;
final actors = d.map((e) => Actor.fromJson(e)).toList(growable: false);
return actors;
}
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_categories = loadVideoData(); _categories = loadAllActors();
} }
@override @override

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:openmediacentermobile/utils/FileFormatter.dart';
import '../DrawerPage.dart'; import '../DrawerPage.dart';
import '../api/token.dart'; import '../api/token.dart';
@ -41,7 +42,8 @@ class _SettingsScreenState extends State<SettingsScreen> {
})); }));
}, },
child: const Text("Delete cache!")), child: const Text("Delete cache!")),
Text("db size: ${dbsize / 1024} kb"), Text(
"DB size: ${dbsize.readableFileSize()} / ${dbsize.readableFileSize(base1024: false)}"),
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {
loginCtx.onLoggin(false); loginCtx.onLoggin(false);

View File

@ -32,7 +32,6 @@ class _PreviewTileState extends State<PreviewTile> {
super.initState(); super.initState();
_preview = loadData(); _preview = loadData();
Log.d("initial load of tile");
} }
@override @override
@ -43,7 +42,6 @@ class _PreviewTileState extends State<PreviewTile> {
setState(() { setState(() {
_preview = loadData(); _preview = loadData();
}); });
Log.i("load of tile due to change");
} }
} }

View File

@ -0,0 +1,17 @@
import 'dart:math';
double _log10(num x) => log(x) / ln10;
extension FileFormatter on num {
String readableFileSize({bool base1024 = true}) {
if (this <= 0) return "0";
final base = base1024 ? 1024 : 1000;
final units = base1024
? ["Bi", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"]
: ["B", "KB", "MB", "GB", "TB", "PB", "EB"];
final digitGroups = (_log10(this) / _log10(base)).floor();
return (this / pow(base, digitGroups)).toStringAsFixed(2) +
" " +
units[digitGroups];
}
}

View File

@ -1,18 +1,21 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:openmediacentermobile/screen_loading.dart'; import '../api/video_api.dart';
import 'package:openmediacentermobile/preview/tag_tile.dart'; import '../dialog/add_actor_dialog.dart';
import 'package:openmediacentermobile/types/video_data.dart'; import '../dialog/add_tag_dialog.dart';
import 'package:openmediacentermobile/preview/actor_tile.dart'; import '../navigation/video_feed.dart';
import '../screen_loading.dart';
import '../types/video_data.dart';
import '../preview/actor_tile.dart';
import '../api/api.dart'; import '../api/api.dart';
import '../log/log.dart'; import '../log/log.dart';
import '../types/actor.dart'; import '../types/actor.dart';
class InfoView extends StatefulWidget { class InfoView extends StatefulWidget {
const InfoView({Key? key, required this.vdata}) : super(key: key); const InfoView({Key? key, required this.videoId}) : super(key: key);
final VideoData vdata; final int videoId;
@override @override
State<InfoView> createState() => _InfoViewState(); State<InfoView> createState() => _InfoViewState();
@ -20,18 +23,25 @@ class InfoView extends StatefulWidget {
class _InfoViewState extends State<InfoView> { class _InfoViewState extends State<InfoView> {
late Future<List<Actor>> _data; late Future<List<Actor>> _data;
late Future<VideoData> vdata;
@override @override
void initState() { void initState() {
super.initState();
setState(() { setState(() {
_data = loadData(); _data = loadData();
vdata = loadVideoData(widget.videoId);
}); });
super.initState(); }
@override
void didUpdateWidget(InfoView oldWidget) {
super.didUpdateWidget(oldWidget);
} }
Future<List<Actor>> loadData() async { Future<List<Actor>> loadData() async {
final data = await API final data = await API
.query("actor", "getActorsOfVideo", {'MovieId': widget.vdata.movieId}); .query("actor", "getActorsOfVideo", {'MovieId': widget.videoId});
if (data == 'null') { if (data == 'null') {
return []; return [];
} }
@ -45,42 +55,106 @@ class _InfoViewState extends State<InfoView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FutureBuilder( return FutureBuilder(
future: _data, future: Future.wait([_data, vdata]),
builder: (context, AsyncSnapshot<List<Actor>> snapshot) { builder: (context, AsyncSnapshot<List<dynamic>> snapshot) {
if (snapshot.hasError) { if (snapshot.hasError) {
return Text("Error"); return Text("Error");
} else if (snapshot.hasData) { } else if (snapshot.hasData) {
final actors = snapshot.data; final actors = snapshot.data![0] as List<Actor>;
final videoData = snapshot.data![1] as VideoData;
return Padding( return Padding(
padding: EdgeInsets.only(left: 10, right: 10, top: 60), padding: EdgeInsets.only(left: 10, right: 10, top: 60),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text("Likes: ${widget.vdata.likes}"), Row(
children: [
IconButton( IconButton(
onPressed: () async { onPressed: () async {
final data = await API.query("video", "addLike", final data = await API.query("video", "addLike",
{'MovieId': widget.vdata.movieId}); {'MovieId': videoData.movieId});
final d = jsonDecode(data); final d = jsonDecode(data);
if (d["result"] != 'success') { if (d["result"] != 'success') {
Log.w(d); Log.w(d);
} }
// bit hacky but it works setState(() {
widget.vdata.likes += 1; vdata = loadVideoData(widget.videoId);
});
}, },
icon: Icon(Icons.thumb_up)), icon: Icon(Icons.thumb_up)),
Text("Quality: ${widget.vdata.quality}"), TextButton(
Text("Length: ${widget.vdata.length}sec"), onPressed: () async {
Text("Actors:"), await showDialog(
actors?.isEmpty ?? true context: context,
? Text("no actors available") builder: (context) => AddActorDialog(
: Row( movieId: videoData.movieId,
children: _renderActors(snapshot.data!),
), ),
Text("Tags:"), );
Row( Log.d("finished dialog");
children: widget.vdata.tags setState(() {
.map((e) => TagTile(tag: e)) _data = loadData();
});
},
child: Text("Add Actor"),
),
TextButton(
onPressed: () async {
await showDialog(
context: context,
builder: (context) => AddTagDialog(
movieId: videoData.movieId,
),
);
Log.d("finished dialog");
setState(() {
vdata = loadVideoData(widget.videoId);
});
},
child: Text("Add Tag"),
)
],
),
Text(
"General info:",
style: TextStyle(fontWeight: FontWeight.bold),
),
Text("Likes: ${videoData.likes}"),
Text("Quality: ${videoData.quality}"),
Text("Length: ${videoData.length}sec"),
Text("Actors:",
style: TextStyle(fontWeight: FontWeight.bold)),
actors.isEmpty
? Text("no actors available")
: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: _renderActors(actors),
),
),
Text("Tags:",
style: TextStyle(fontWeight: FontWeight.bold)),
SizedBox(
height: 5,
),
Wrap(
spacing: 4,
runSpacing: 4,
children: videoData.tags
.map(
(e) => ActionChip(
backgroundColor:
Theme.of(context).secondaryHeaderColor,
label: Text(e.tagName),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => VideoFeed(tag: e),
),
);
},
),
)
.toList(growable: false), .toList(growable: false),
) )
])); ]));

View File

@ -1,9 +1,8 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../api/api.dart';
import '../api/token.dart'; import '../api/token.dart';
import '../api/video_api.dart';
import '../platform.dart'; import '../platform.dart';
import '../screen_loading.dart'; import '../screen_loading.dart';
import '../types/video.dart'; import '../types/video.dart';
@ -32,15 +31,6 @@ class _VideoScreenState extends State<VideoScreen> {
String url = ""; String url = "";
Future<VideoData> loadVideoData() async {
final data =
await API.query("video", "loadVideo", {'MovieId': widget.metaData.id});
final d = jsonDecode(data);
final video = VideoData.fromJson(d);
return video;
}
void initPlayer() async { void initPlayer() async {
final videodata = await _videoData; final videodata = await _videoData;
@ -57,7 +47,7 @@ class _VideoScreenState extends State<VideoScreen> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_videoData = loadVideoData(); _videoData = loadVideoData(widget.metaData.id);
initPlayer(); initPlayer();
_setAppBarTimer(); _setAppBarTimer();
} }
@ -117,7 +107,7 @@ class _VideoScreenState extends State<VideoScreen> {
} }
} }
}, },
behavior: HitTestBehavior.opaque, // behavior: HitTestBehavior.opaque,
child: Stack(children: [ child: Stack(children: [
PageView( PageView(
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
@ -132,7 +122,7 @@ class _VideoScreenState extends State<VideoScreen> {
url: url, url: url,
)), )),
InfoView( InfoView(
vdata: snapshot.data!, videoId: widget.metaData.id,
) )
]), ]),
if (_appBarVisible) if (_appBarVisible)