addactor, addtag dialogs
This commit is contained in:
parent
b0f913f8d1
commit
405d7e420e
12
lib/api/actor_api.dart
Normal file
12
lib/api/actor_api.dart
Normal 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
12
lib/api/video_api.dart
Normal 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;
|
||||||
|
}
|
67
lib/dialog/add_actor_dialog.dart
Normal file
67
lib/dialog/add_actor_dialog.dart
Normal 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();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
76
lib/dialog/add_tag_dialog.dart
Normal file
76
lib/dialog/add_tag_dialog.dart
Normal 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();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
lib/utils/FileFormatter.dart
Normal file
17
lib/utils/FileFormatter.dart
Normal 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];
|
||||||
|
}
|
||||||
|
}
|
@ -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}"),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () async {
|
|
||||||
final data = await API.query("video", "addLike",
|
|
||||||
{'MovieId': widget.vdata.movieId});
|
|
||||||
final d = jsonDecode(data);
|
|
||||||
if (d["result"] != 'success') {
|
|
||||||
Log.w(d);
|
|
||||||
}
|
|
||||||
// bit hacky but it works
|
|
||||||
widget.vdata.likes += 1;
|
|
||||||
},
|
|
||||||
icon: Icon(Icons.thumb_up)),
|
|
||||||
Text("Quality: ${widget.vdata.quality}"),
|
|
||||||
Text("Length: ${widget.vdata.length}sec"),
|
|
||||||
Text("Actors:"),
|
|
||||||
actors?.isEmpty ?? true
|
|
||||||
? Text("no actors available")
|
|
||||||
: Row(
|
|
||||||
children: _renderActors(snapshot.data!),
|
|
||||||
),
|
|
||||||
Text("Tags:"),
|
|
||||||
Row(
|
Row(
|
||||||
children: widget.vdata.tags
|
children: [
|
||||||
.map((e) => TagTile(tag: e))
|
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);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.thumb_up)),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AddActorDialog(
|
||||||
|
movieId: videoData.movieId,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Log.d("finished dialog");
|
||||||
|
setState(() {
|
||||||
|
_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),
|
||||||
)
|
)
|
||||||
]));
|
]));
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user