1 Commits

Author SHA1 Message Date
dc87a4369e use betterplayer instead of chewie 2022-08-31 16:30:34 +02:00
38 changed files with 363 additions and 573 deletions

View File

@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android { android {
compileSdkVersion 33 compileSdkVersion flutter.compileSdkVersion
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8

View File

@ -1,12 +1,12 @@
buildscript { buildscript {
ext.kotlin_version = '1.6.10' ext.kotlin_version = '1.4.32'
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.1.2' classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
} }
} }

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip

View File

@ -1,6 +1,5 @@
import 'dart:convert'; import 'dart:convert';
import '../log/log.dart';
import '../types/actor.dart'; import '../types/actor.dart';
import 'api.dart'; import 'api.dart';
@ -11,26 +10,3 @@ Future<List<Actor>> loadAllActors() async {
final actors = d.map((e) => Actor.fromJson(e)).toList(growable: false); final actors = d.map((e) => Actor.fromJson(e)).toList(growable: false);
return actors; return actors;
} }
Future<List<Actor>> loadActorsOfVideo(int movieId) async {
final data =
await API.query("actor", "getActorsOfVideo", {'MovieId': movieId});
if (data == 'null') {
return [];
}
final d = jsonDecode(data);
List<Actor> dta = (d as List).map((e) => Actor.fromJson(e)).toList();
return dta;
}
Future<void> 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");
}
}

View File

@ -1,42 +0,0 @@
import 'dart:convert';
import 'api.dart';
class InitialData {
bool darkMode;
bool password;
String mediacenterName;
String videoPath;
String tvShowPath;
bool tvShowEnabled;
bool fullDeleteEnabled;
InitialData(
this.darkMode,
this.password,
this.mediacenterName,
this.videoPath,
this.tvShowPath,
this.tvShowEnabled,
this.fullDeleteEnabled);
factory InitialData.fromJson(dynamic json) {
return InitialData(
json['DarkMode'] as bool,
json['Pasword'] as bool,
json['MediacenterName'] as String,
json['VideoPath'] as String,
json['TVShowPath'] as String,
json['TVShowEnabled'] as bool,
json['FullDeleteEnabled'] as bool,
);
}
}
Future<InitialData> loadInitialData() async {
final data = await API.query("settings", "loadInitialData", {});
final d = jsonDecode(data);
final video = InitialData.fromJson(d);
return video;
}

View File

@ -1,23 +0,0 @@
import 'dart:convert';
import '../log/log.dart';
import '../types/tag.dart';
import 'api.dart';
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, 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");
}
}

View File

@ -8,10 +8,8 @@ import '../log/log.dart';
class TokenT { class TokenT {
String token; String token;
String domain; String domain;
String videoPath;
String tvPath;
TokenT(this.token, this.domain, this.videoPath, this.tvPath); TokenT(this.token, this.domain);
} }
class Token { class Token {
@ -20,46 +18,40 @@ class Token {
String _tokenval = ""; String _tokenval = "";
String _domain = ""; String _domain = "";
String _vPath = "";
String _tvPath = "";
static Token getInstance() { static Token getInstance() {
return _token; return _token;
} }
Future<TokenT?> getToken() async { Future<TokenT?> getToken() async {
if (_tokenval == "" || _domain == "" || _vPath == "") { var completer = Completer<TokenT?>();
if (_tokenval == "" || _domain == "") {
Log.d("reading token store"); Log.d("reading token store");
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
final token = await _storage.read(key: 'jwt'); final token = await _storage.read(key: 'jwt');
final domain = await _storage.read(key: 'domain'); final domain = await _storage.read(key: 'domain');
// todo paths should be loaded on each app start
final vPath = await _storage.read(key: 'videoPath');
final tvPath = await _storage.read(key: 'tvPath');
// check if value is defined in phone store // check if value is defined in phone store
if (token != null && domain != null && vPath != null) { if (token != null && domain != null) {
_tokenval = token; _tokenval = token;
_domain = domain; _domain = domain;
return TokenT(token, domain, vPath, tvPath ?? ""); completer.complete(TokenT(token, domain));
} else { } else {
Log.d("no token defined"); Log.d("no token defined");
return null; completer.complete(null);
} }
} else { } else {
return TokenT(_tokenval, _domain, _vPath, _tvPath); completer.complete(TokenT(_tokenval, _domain));
} }
return completer.future;
} }
void setToken(String token, String domain, String videoPath, String tvPath) { void setToken(String token, String domain) {
_tokenval = token; _tokenval = token;
_domain = domain; _domain = domain;
_vPath = videoPath;
_tvPath = tvPath;
_storage.write(key: 'jwt', value: token); _storage.write(key: 'jwt', value: token);
_storage.write(key: 'domain', value: domain); _storage.write(key: 'domain', value: domain);
_storage.write(key: 'videoPath', value: videoPath);
_storage.write(key: 'tvPath', value: tvPath);
} }
Token._(); Token._();

View File

@ -1,11 +1,5 @@
import 'dart:convert'; 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 '../types/video_data.dart';
import 'api.dart'; import 'api.dart';
@ -16,55 +10,3 @@ Future<VideoData> loadVideoData(int videoId) async {
final video = VideoData.fromJson(d); final video = VideoData.fromJson(d);
return video; return video;
} }
Future<List<VideoT>> loadVideo(Tag? tag, int filterIdx) async {
final data = await API
.query("video", "getMovies", {'Tag': tag?.tagId ?? 1, 'Sort': filterIdx});
final d = jsonDecode(data);
List<VideoT> dta =
(d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList();
return dta;
}
Future<List<VideoT>> loadShuffledVideos(int nr) async {
final data = await API.query("video", "getRandomMovies",
{'Number': nr, 'Seed': Random().nextInt(0x7fffffff)});
final d = jsonDecode(data);
List<VideoT> dta =
(d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList();
return dta;
}
Future<List<VideoT>> loadVideoByActor(Actor actor) async {
final data =
await API.query("actor", "getActorInfo", {'ActorId': actor.actorId});
final d = jsonDecode(data);
List<VideoT> dta =
(d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList();
return dta;
}
Future<bool> 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<Uint8List> fetchThumbnail(int movieId) async {
final base64str =
await API.query("video", "readThumbnail", {'Movieid': movieId});
return base64Decode(base64str.substring(23));
}

View File

@ -3,17 +3,15 @@ import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:openmediacentermobile/log/log.dart'; import 'package:openmediacentermobile/log/log.dart';
import 'package:openmediacentermobile/login/login_screen.dart'; import 'package:openmediacentermobile/login/login_screen.dart';
import 'package:openmediacentermobile/utils/feature_context.dart';
import 'drawer/drawer_page.dart'; import 'drawer/drawer_page.dart';
import 'login/login_context.dart'; import 'login/logincontext.dart';
class AppScrollBehavior extends MaterialScrollBehavior { class AppScrollBehavior extends MaterialScrollBehavior {
@override @override
Set<PointerDeviceKind> get dragDevices => { Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch, PointerDeviceKind.touch,
PointerDeviceKind.mouse, PointerDeviceKind.mouse,
PointerDeviceKind.trackpad
}; };
} }
@ -22,21 +20,18 @@ class App extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final loginCtx = LoginContext.of(context); var loginCtx = LoginContext.of(context);
Log.d("We are logged in: ${loginCtx.loggedIn}"); Log.d("We are logged in: ${loginCtx.loggedIn}");
if (!loginCtx.loggedIn) { if (!loginCtx.loggedIn) {
return const MaterialApp(home: LoginScreen()); return const MaterialApp(home: LoginScreen());
} else { } else {
return FeatureContainer( return MaterialApp(
child: MaterialApp(
scrollBehavior: AppScrollBehavior(), scrollBehavior: AppScrollBehavior(),
home: DrawerPage( home: DrawerPage(
title: 'OpenMediaCenter', title: 'OpenMediaCenter',
), ));
),
);
} }
} }
} }

View File

@ -25,8 +25,12 @@ class Db {
} }
_db = await openDatabase( _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, dbpath,
onCreate: (db, version) { onCreate: (db, version) {
// Run the CREATE TABLE statement on the database.
return db.execute( return db.execute(
'CREATE TABLE previews(id INTEGER PRIMARY KEY, thumbnail BLOB)', 'CREATE TABLE previews(id INTEGER PRIMARY KEY, thumbnail BLOB)',
); );

View File

@ -1,6 +1,10 @@
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../api/actor_api.dart'; import '../api/actor_api.dart';
import '../api/api.dart';
import '../log/log.dart';
import '../screen_loading.dart'; import '../screen_loading.dart';
import '../types/actor.dart'; import '../types/actor.dart';
@ -15,6 +19,16 @@ class AddActorDialog extends StatefulWidget {
class _AddActorDialogState extends State<AddActorDialog> { class _AddActorDialogState extends State<AddActorDialog> {
late Future<List<Actor>> actors = loadAllActors(); 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 @override
void initState() { void initState() {
super.initState(); super.initState();
@ -38,7 +52,7 @@ class _AddActorDialogState extends State<AddActorDialog> {
.map((e) => ListTile( .map((e) => ListTile(
title: Text(e.name), title: Text(e.name),
onTap: () async { onTap: () async {
await addActorToVideo(e.actorId, widget.movieId); await addActorToVideo(e.actorId);
Navigator.pop(context, e); Navigator.pop(context, e);
}, },
)) ))

View File

@ -1,6 +1,9 @@
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../api/tag_api.dart'; import '../api/api.dart';
import '../log/log.dart';
import '../screen_loading.dart'; import '../screen_loading.dart';
import '../types/tag.dart'; import '../types/tag.dart';
@ -15,6 +18,24 @@ class AddTagDialog extends StatefulWidget {
class _AddTagDialogState extends State<AddTagDialog> { class _AddTagDialogState extends State<AddTagDialog> {
late Future<List<Tag>> tags = loadAllTags(); 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 @override
void initState() { void initState() {
super.initState(); super.initState();
@ -39,7 +60,7 @@ class _AddTagDialogState extends State<AddTagDialog> {
(e) => ListTile( (e) => ListTile(
title: Text(e.tagName), title: Text(e.tagName),
onTap: () async { onTap: () async {
await addTagToVideo(e.tagId, widget.movieId); await addTagToVideo(e.tagId);
Navigator.pop(context, e); Navigator.pop(context, e);
}, },
), ),

View File

@ -2,8 +2,7 @@ import 'package:flutter/material.dart';
import 'package:openmediacentermobile/navigation/settings_screen.dart'; import 'package:openmediacentermobile/navigation/settings_screen.dart';
import '../navigation/actor_screen.dart'; import '../navigation/actor_screen.dart';
import '../navigation/categorie_screen.dart'; import '../navigation/categorie_screen.dart';
import '../navigation/shuffle_screen.dart'; import '../navigation/shufflescreen.dart';
import '../navigation/tv_show_screen.dart';
import '../navigation/video_feed.dart'; import '../navigation/video_feed.dart';
import 'drawer_context.dart'; import 'drawer_context.dart';
@ -16,7 +15,7 @@ class DrawerPage extends StatefulWidget {
_DrawerPageState createState() => _DrawerPageState(); _DrawerPageState createState() => _DrawerPageState();
} }
enum Section { HOME, SHUFFLE, SETTING, CATEGORIE, ACTOR, TVSHOW } enum Section { HOME, SHUFFLE, SETTING, CATEGORIE, ACTOR }
class _DrawerPageState extends State<DrawerPage> { class _DrawerPageState extends State<DrawerPage> {
Section _sec = Section.HOME; Section _sec = Section.HOME;
@ -51,11 +50,6 @@ class _DrawerPageState extends State<DrawerPage> {
body = ActorScreen(); body = ActorScreen();
title = "Actors"; title = "Actors";
break; break;
case Section.TVSHOW:
body = TVShowScreen();
title = "TV Shows";
break;
} }
return DrawerContext( return DrawerContext(

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:openmediacentermobile/utils/feature_context.dart';
import 'drawer_context.dart'; import 'drawer_context.dart';
import 'drawer_page.dart'; import 'drawer_page.dart';
@ -10,7 +9,6 @@ class MyDrawer extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ctx = DrawerContext.of(context); final ctx = DrawerContext.of(context);
final featureCtx = FeatureContext.of(context);
return Drawer( return Drawer(
child: ListView(children: [ child: ListView(children: [
@ -46,15 +44,6 @@ class MyDrawer extends StatelessWidget {
Navigator.pop(context); Navigator.pop(context);
}, },
), ),
if (featureCtx.tvShowEnabled)
ListTile(
title: const Text('TV Shows'),
leading: const Icon(Icons.tv),
onTap: () {
ctx.onChangePage(Section.TVSHOW);
Navigator.pop(context);
},
),
ListTile( ListTile(
title: const Text('Settings'), title: const Text('Settings'),
leading: const Icon(Icons.settings), leading: const Icon(Icons.settings),

View File

@ -1,25 +0,0 @@
import 'package:flutter/material.dart';
class LoginContext extends InheritedWidget {
const LoginContext(
{Key? key,
required Widget child,
required this.loggedIn,
required this.onLoggin})
: super(key: key, child: child);
final bool loggedIn;
final void Function(bool) onLoggin;
static LoginContext of(BuildContext context) {
final LoginContext? result =
context.dependOnInheritedWidgetOfExactType<LoginContext>();
assert(result != null, 'No LoginContext found in context');
return result!;
}
@override
bool updateShouldNotify(LoginContext old) {
return loggedIn != old.loggedIn;
}
}

View File

@ -3,10 +3,9 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import '../api/settings_api.dart'; import 'package:openmediacentermobile/api/token.dart';
import '../api/token.dart'; import 'package:openmediacentermobile/log/log.dart';
import '../log/log.dart'; import 'package:openmediacentermobile/login/logincontext.dart';
import 'login_context.dart';
class LoginScreen extends StatefulWidget { class LoginScreen extends StatefulWidget {
const LoginScreen({Key? key}) : super(key: key); const LoginScreen({Key? key}) : super(key: key);
@ -40,45 +39,19 @@ class _LoginScreenState extends State<LoginScreen> {
if (resp.statusCode != 200) { if (resp.statusCode != 200) {
return "error" + resp.body; return "error" + resp.body;
// compl.complete(resp.body);
} else { } else {
final json = jsonDecode(resp.body); final json = jsonDecode(resp.body);
final token = json["Token"]; final token = json["Token"];
// todo bit hacky Token.getInstance().setToken(token, domain);
Token.getInstance().setToken(token, domain, "temp", "temp");
// we need to call this twice because we need for the loadInitialData an api token
final initalData = await loadInitialData();
Token.getInstance()
.setToken(token, domain, initalData.videoPath, initalData.tvShowPath);
LoginContext.of(context).onLoggin(true); LoginContext.of(context).onLoggin(true);
return ""; return "";
} }
} }
Future<void> onLoginClick() async {
Log.d("logging in");
final pwd = _passwordTextController.value.text;
final domain = _domainTextController.value.text;
var err = "";
if (domain.startsWith("https://") || domain.startsWith("http://")) {
err = await login(pwd, domain);
if (err.isEmpty) return;
} else {
// try to auto infering domain prefix
err = await login(pwd, "https://" + domain);
if (err.isEmpty) return;
err = await login(pwd, "http://" + domain);
if (err.isEmpty) return;
}
Log.i(err);
setState(() {
error = err;
});
}
@override @override
void dispose() { void dispose() {
_domainTextController.dispose(); _domainTextController.dispose();
@ -159,7 +132,33 @@ class _LoginScreenState extends State<LoginScreen> {
backgroundColor: const Color(0xff4c505b), backgroundColor: const Color(0xff4c505b),
child: IconButton( child: IconButton(
color: Colors.white, color: Colors.white,
onPressed: () async => await onLoginClick(), onPressed: () async {
Log.d("clickkked");
final pwd =
_passwordTextController.value.text;
final domain =
_domainTextController.value.text;
var err = "";
if (domain.startsWith("https://") ||
domain.startsWith("http://")) {
err = await login(pwd, domain);
if (err.isEmpty) return;
} else {
// try to auto infering domain prefix
err = await login(
pwd, "https://" + domain);
if (err.isEmpty) return;
err = await login(
pwd, "http://" + domain);
if (err.isEmpty) return;
}
Log.i(err);
setState(() {
error = err;
});
},
icon: const Icon( icon: const Icon(
Icons.arrow_forward, Icons.arrow_forward,
)), )),

View File

@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import '../api/token.dart'; import '../api/token.dart';
import '../log/log.dart'; import '../log/log.dart';
import 'login_context.dart';
class LoginContainer extends StatefulWidget { class LoginContainer extends StatefulWidget {
const LoginContainer({Key? key, required this.child}) : super(key: key); const LoginContainer({Key? key, required this.child}) : super(key: key);
@ -19,23 +18,22 @@ class _LoginContainerState extends State<LoginContainer> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_init();
}
void _init() async { final token = Token.getInstance();
final token = await Token.getInstance().getToken(); token.getToken().then((value) {
Log.i("The token value is $token"); Log.i("The token value is $value");
if (token != null) { if (value != null) {
setState(() { setState(() {
_loggedIn = true; _loggedIn = true;
_loading = false; _loading = false;
}); });
} else { } else {
setState(() { setState(() {
_loggedIn = false; _loggedIn = false;
_loading = false; _loading = false;
}); });
} }
});
} }
@override @override
@ -60,3 +58,27 @@ class _LoginContainerState extends State<LoginContainer> {
); );
} }
} }
class LoginContext extends InheritedWidget {
const LoginContext(
{Key? key,
required Widget child,
required this.loggedIn,
required this.onLoggin})
: super(key: key, child: child);
final bool loggedIn;
final void Function(bool) onLoggin;
static LoginContext of(BuildContext context) {
final LoginContext? result =
context.dependOnInheritedWidgetOfExactType<LoginContext>();
assert(result != null, 'No LoginContext found in context');
return result!;
}
@override
bool updateShouldNotify(LoginContext old) {
return loggedIn != old.loggedIn;
}
}

View File

@ -5,7 +5,7 @@ import 'package:flutter/services.dart';
import 'app.dart'; import 'app.dart';
import 'db/database.dart'; import 'db/database.dart';
import 'log/log.dart'; import 'log/log.dart';
import 'login/login_container.dart'; import 'login/logincontext.dart';
import 'utils/platform.dart'; import 'utils/platform.dart';
void main() async { void main() async {

View File

@ -1,9 +1,11 @@
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../api/tag_api.dart'; import 'package:openmediacentermobile/preview/tag_tile.dart';
import '../preview/tag_tile.dart';
import '../drawer/my_drawer.dart'; import '../drawer/my_drawer.dart';
import '../screen_loading.dart'; import '../screen_loading.dart';
import '../api/api.dart';
import '../types/tag.dart'; import '../types/tag.dart';
class CategorieScreen extends StatefulWidget { class CategorieScreen extends StatefulWidget {
@ -16,10 +18,18 @@ class CategorieScreen extends StatefulWidget {
class _CategorieScreenState extends State<CategorieScreen> { class _CategorieScreenState extends State<CategorieScreen> {
late Future<List<Tag>> _categories; late Future<List<Tag>> _categories;
Future<List<Tag>> loadVideoData() 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;
}
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_categories = loadAllTags(); _categories = loadVideoData();
} }
@override @override

View File

@ -1,10 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../utils/file_formatter.dart'; import 'package:openmediacentermobile/utils/FileFormatter.dart';
import '../api/token.dart'; import '../api/token.dart';
import '../db/database.dart'; import '../db/database.dart';
import '../drawer/my_drawer.dart'; import '../drawer/my_drawer.dart';
import '../login/login_context.dart'; import '../login/logincontext.dart';
class SettingsScreen extends StatefulWidget { class SettingsScreen extends StatefulWidget {
const SettingsScreen({Key? key}) : super(key: key); const SettingsScreen({Key? key}) : super(key: key);
@ -15,7 +15,6 @@ class SettingsScreen extends StatefulWidget {
class _SettingsScreenState extends State<SettingsScreen> { class _SettingsScreenState extends State<SettingsScreen> {
int dbsize = 0; int dbsize = 0;
String serverUrl = "";
@override @override
void initState() { void initState() {
@ -23,10 +22,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
Db().getDbSize().then((v) => setState(() { Db().getDbSize().then((v) => setState(() {
dbsize = v; dbsize = v;
})); }));
Token.getInstance().getToken().then((value) => setState(() {
serverUrl = value?.domain ?? "unknown";
}));
} }
@override @override
@ -39,7 +34,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
), ),
body: Column( body: Column(
children: [ children: [
Text("Current server: $serverUrl"),
ElevatedButton( ElevatedButton(
onPressed: () async { onPressed: () async {
await Db().clear(); await Db().clear();
@ -53,7 +47,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {
loginCtx.onLoggin(false); loginCtx.onLoggin(false);
Token.getInstance().setToken("", "", "", ""); Token.getInstance().setToken("", "");
Db().clear(); Db().clear();
}, },
child: Text("Logout")) child: Text("Logout"))

View File

@ -1,9 +1,12 @@
import 'dart:convert';
import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../api/video_api.dart';
import '../drawer/my_drawer.dart'; import '../drawer/my_drawer.dart';
import '../preview/preview_grid.dart'; import '../preview/preview_grid.dart';
import '../api/api.dart';
import '../utils/platform.dart'; import '../utils/platform.dart';
import '../types/video.dart';
class ShuffleScreen extends StatefulWidget { class ShuffleScreen extends StatefulWidget {
const ShuffleScreen({Key? key}) : super(key: key); const ShuffleScreen({Key? key}) : super(key: key);
@ -13,6 +16,18 @@ class ShuffleScreen extends StatefulWidget {
} }
class _ShuffleScreenState extends State<ShuffleScreen> { class _ShuffleScreenState extends State<ShuffleScreen> {
Future<List<VideoT>> loadData(int nr) async {
final data = await API.query("video", "getRandomMovies",
{'Number': nr, 'Seed': Random().nextInt(0x7fffffff)});
final d = jsonDecode(data);
List<VideoT> dta =
(d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList();
return dta;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width; double width = MediaQuery.of(context).size.width;
@ -23,8 +38,7 @@ class _ShuffleScreenState extends State<ShuffleScreen> {
), ),
body: PreviewGrid( body: PreviewGrid(
videoLoader: () { videoLoader: () {
return loadShuffledVideos( return loadData((isTV() ? width ~/ 200 : width ~/ 275) * 2);
(isTV() ? width ~/ 200 : width ~/ 275) * 2);
}, },
footerBuilder: (state) => Column( footerBuilder: (state) => Column(
children: [ children: [

View File

@ -1,15 +0,0 @@
import 'package:flutter/material.dart';
class TVShowScreen extends StatefulWidget {
const TVShowScreen({Key? key}) : super(key: key);
@override
State<TVShowScreen> createState() => _TVShowScreenState();
}
class _TVShowScreenState extends State<TVShowScreen> {
@override
Widget build(BuildContext context) {
return Container();
}
}

View File

@ -1,9 +1,12 @@
import 'package:flutter/material.dart'; import 'dart:convert';
import '../api/video_api.dart';
import 'package:flutter/material.dart';
import '../api/api.dart';
import '../drawer/my_drawer.dart'; import '../drawer/my_drawer.dart';
import '../preview/preview_grid.dart'; import '../preview/preview_grid.dart';
import '../types/tag.dart'; import '../types/tag.dart';
import '../types/video.dart';
enum FilterTypes { DATE, LIKES, RANDOM, NAMES, LENGTH } enum FilterTypes { DATE, LIKES, RANDOM, NAMES, LENGTH }
@ -21,6 +24,18 @@ class VideoFeedState extends State<VideoFeed> {
FilterTypes filterSelection = FilterTypes.DATE; FilterTypes filterSelection = FilterTypes.DATE;
Key _refreshKey = UniqueKey(); Key _refreshKey = UniqueKey();
Future<List<VideoT>> loadData() async {
final data = await API.query("video", "getMovies",
{'Tag': widget.tag?.tagId ?? 1, 'Sort': filterSelection.index});
final d = jsonDecode(data);
List<VideoT> dta =
(d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList();
return dta;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -65,7 +80,7 @@ class VideoFeedState extends State<VideoFeed> {
), ),
body: PreviewGrid( body: PreviewGrid(
key: _refreshKey, key: _refreshKey,
videoLoader: () => loadVideo(widget.tag, filterSelection.index), videoLoader: () => loadData(),
), ),
drawer: widget.tag == null ? MyDrawer() : null); drawer: widget.tag == null ? MyDrawer() : null);
} }

View File

@ -1,8 +1,11 @@
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../api/video_api.dart'; import '../api/api.dart';
import 'preview_grid.dart'; import 'preview_grid.dart';
import '../types/actor.dart'; import '../types/actor.dart';
import '../types/video.dart';
class ActorFeed extends StatefulWidget { class ActorFeed extends StatefulWidget {
const ActorFeed({Key? key, required this.actor}) : super(key: key); const ActorFeed({Key? key, required this.actor}) : super(key: key);
@ -13,10 +16,22 @@ class ActorFeed extends StatefulWidget {
} }
class _ActorFeedState extends State<ActorFeed> { class _ActorFeedState extends State<ActorFeed> {
Future<List<VideoT>> loadData() async {
final data = await API
.query("actor", "getActorInfo", {'ActorId': widget.actor.actorId});
final d = jsonDecode(data);
List<VideoT> dta =
(d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList();
return dta;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return PreviewGrid( return PreviewGrid(
videoLoader: () => loadVideoByActor(widget.actor), videoLoader: () => loadData(),
); );
} }
} }

View File

@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../preview/actor_feed.dart'; import 'package:openmediacentermobile/preview/actor_feed.dart';
import '../utils/platform.dart'; import '../utils/platform.dart';
import '../types/actor.dart'; import '../types/actor.dart';

View File

@ -56,15 +56,15 @@ class _PreviewGridState extends State<PreviewGrid> {
builder: builder:
(BuildContext context, AsyncSnapshot<List<VideoT>> snapshot) { (BuildContext context, AsyncSnapshot<List<VideoT>> snapshot) {
if (snapshot.hasError) { if (snapshot.hasError) {
return Center( return Column(
child: Column( children: [
mainAxisAlignment: MainAxisAlignment.center, Text("Error"),
children: [ TextButton(
Text("Error"), onPressed: () {
TextButton( loadData();
onPressed: () => loadData(), child: Text("Reload page")) },
], child: Text("Reload page"))
), ],
); );
} else if (snapshot.hasData) { } else if (snapshot.hasData) {
return _mainGrid(snapshot.data!, width); return _mainGrid(snapshot.data!, width);

View File

@ -1,8 +1,11 @@
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart'; import 'package:sqflite/sqflite.dart';
import '../api/video_api.dart'; import '../api/api.dart';
import '../db/database.dart'; import '../db/database.dart';
import '../log/log.dart'; import '../log/log.dart';
import '../utils/platform.dart'; import '../utils/platform.dart';
@ -50,17 +53,23 @@ class _PreviewTileState extends State<PreviewTile> {
); );
} }
Future<Uint8List> _fetchThumbnail(int id) async {
final base64str =
await API.query("video", "readThumbnail", {'Movieid': id});
return base64Decode(base64str.substring(23));
}
Future<Image> loadData() async { Future<Image> loadData() async {
Uint8List data; Uint8List data;
final id = widget.dta.id; final id = widget.dta.id;
if (kIsWeb) { if (kIsWeb) {
data = await fetchThumbnail(id); data = await _fetchThumbnail(id);
} else { } else {
final List<Map<String, dynamic>> prev = final List<Map<String, dynamic>> prev =
await Db().db().query('previews', where: "id=$id"); await Db().db().query('previews', where: "id=$id");
if (prev.isEmpty) { if (prev.isEmpty) {
data = await fetchThumbnail(id); data = await _fetchThumbnail(id);
insert(id, data); insert(id, data);
Log.d("Adding $id to db"); Log.d("Adding $id to db");
} else { } else {

View File

@ -18,7 +18,7 @@ class TagTile extends StatelessWidget {
), ),
); );
}, },
style: ElevatedButton.styleFrom(backgroundColor: Color(0x6a94a6ff)), style: ElevatedButton.styleFrom(primary: Color(0x6a94a6ff)),
child: SizedBox( child: SizedBox(
child: Center(child: Text(tag.tagName)), child: Center(child: Text(tag.tagName)),
height: 100, height: 100,

View File

@ -1,92 +0,0 @@
import 'package:flutter/material.dart';
import 'package:openmediacentermobile/login/login_context.dart';
import '../api/settings_api.dart';
// todo maybe instead of feature context a context for all settings?
class FeatureContext extends InheritedWidget {
const FeatureContext(this.tvShowEnabled, this.fullDeleteEnabled,
{Key? key, required Widget child})
: super(key: key, child: child);
final bool tvShowEnabled;
final bool fullDeleteEnabled;
static FeatureContext of(BuildContext context) {
final FeatureContext? result =
context.dependOnInheritedWidgetOfExactType<FeatureContext>();
assert(result != null, 'No LoginContext found in context');
return result!;
}
@override
bool updateShouldNotify(FeatureContext old) {
return tvShowEnabled != old.tvShowEnabled ||
fullDeleteEnabled != old.fullDeleteEnabled;
}
}
class FeatureContainer extends StatefulWidget {
const FeatureContainer({Key? key, required this.child}) : super(key: key);
final Widget child;
@override
State<FeatureContainer> createState() => _FeatureContainerState();
}
class _FeatureContainerState extends State<FeatureContainer> {
bool? tvShowEnabled;
bool? fullDeleteEnabled;
bool fetcherror = false;
@override
void initState() {
loadInitialData()
.then((value) => setState(
() {
fullDeleteEnabled = value.fullDeleteEnabled;
tvShowEnabled = value.tvShowEnabled;
},
))
.catchError((err) => setState(() => fetcherror = true));
super.initState();
}
@override
Widget build(BuildContext context) {
if (fetcherror) {
final loginctx = LoginContext.of(context);
return MaterialApp(
home: Scaffold(
body: Center(
child:
Column(mainAxisAlignment: MainAxisAlignment.center, children: [
Text("Fetch error"),
MaterialButton(
onPressed: () => loginctx.onLoggin(false),
child: Text("Logout"),
)
]),
),
),
);
} else if (tvShowEnabled == null || fullDeleteEnabled == null) {
return MaterialApp(
home: Scaffold(
body: Container(
color: Colors.white,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [CircularProgressIndicator(), Text("loading features")],
)),
),
),
);
} else {
return FeatureContext(tvShowEnabled!, fullDeleteEnabled!,
child: widget.child);
}
}
}

View File

@ -1,5 +1,6 @@
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../api/actor_api.dart';
import '../api/video_api.dart'; import '../api/video_api.dart';
import '../dialog/add_actor_dialog.dart'; import '../dialog/add_actor_dialog.dart';
import '../dialog/add_tag_dialog.dart'; import '../dialog/add_tag_dialog.dart';
@ -7,6 +8,9 @@ import '../navigation/video_feed.dart';
import '../screen_loading.dart'; import '../screen_loading.dart';
import '../types/video_data.dart'; import '../types/video_data.dart';
import '../preview/actor_tile.dart'; import '../preview/actor_tile.dart';
import '../api/api.dart';
import '../log/log.dart';
import '../types/actor.dart'; import '../types/actor.dart';
class InfoView extends StatefulWidget { class InfoView extends StatefulWidget {
@ -25,7 +29,7 @@ class _InfoViewState extends State<InfoView> {
void initState() { void initState() {
super.initState(); super.initState();
setState(() { setState(() {
_data = loadActorsOfVideo(widget.videoId); _data = loadData();
vdata = loadVideoData(widget.videoId); vdata = loadVideoData(widget.videoId);
}); });
} }
@ -35,6 +39,19 @@ class _InfoViewState extends State<InfoView> {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
} }
Future<List<Actor>> loadData() async {
final data = await API
.query("actor", "getActorsOfVideo", {'MovieId': widget.videoId});
if (data == 'null') {
return [];
}
final d = jsonDecode(data);
List<Actor> dta = (d as List).map((e) => Actor.fromJson(e)).toList();
return dta;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FutureBuilder( return FutureBuilder(
@ -54,10 +71,15 @@ class _InfoViewState extends State<InfoView> {
children: [ children: [
IconButton( IconButton(
onPressed: () async { onPressed: () async {
if (await addLike(videoData.movieId)) final data = await API.query("video", "addLike",
setState(() { {'MovieId': videoData.movieId});
vdata = loadVideoData(widget.videoId); final d = jsonDecode(data);
}); if (d["result"] != 'success') {
Log.w(d);
}
setState(() {
vdata = loadVideoData(widget.videoId);
});
}, },
icon: Icon(Icons.thumb_up)), icon: Icon(Icons.thumb_up)),
TextButton( TextButton(
@ -68,8 +90,9 @@ class _InfoViewState extends State<InfoView> {
movieId: videoData.movieId, movieId: videoData.movieId,
), ),
); );
Log.d("finished dialog");
setState(() { setState(() {
_data = loadActorsOfVideo(widget.videoId); _data = loadData();
}); });
}, },
child: Text("Add Actor"), child: Text("Add Actor"),
@ -82,6 +105,7 @@ class _InfoViewState extends State<InfoView> {
movieId: videoData.movieId, movieId: videoData.movieId,
), ),
); );
Log.d("finished dialog");
setState(() { setState(() {
vdata = loadVideoData(widget.videoId); vdata = loadVideoData(widget.videoId);
}); });

View File

@ -37,7 +37,9 @@ class _VideoScreenState extends State<VideoScreen> {
final token = await Token.getInstance().getToken(); final token = await Token.getInstance().getToken();
if (token == null) return; if (token == null) return;
final path = token.domain + token.videoPath + videodata.movieUrl; final baseurl = token.domain;
// todo not static middle path
final path = baseurl + "/videos/vids/" + videodata.movieUrl;
url = path; url = path;
} }
@ -92,7 +94,7 @@ class _VideoScreenState extends State<VideoScreen> {
child: GestureDetector( child: GestureDetector(
onPanDown: (details) async { onPanDown: (details) async {
if (_appBarVisible) { if (_appBarVisible) {
await Future.delayed(Duration(milliseconds: 300)); await Future.delayed(Duration(milliseconds: 100));
setState(() { setState(() {
_appBarVisible = false; _appBarVisible = false;
}); });

View File

@ -18,10 +18,11 @@ class _VideoScreenDesktopState extends State<VideoScreenDesktop> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Video( return Video(
player: _player, player: _player,
showFullscreenButton: true, scale: 1.0, // default
scale: 1.0, // default showControls: true,
showControls: true); playlistLength: 1,
);
} }
@override @override

View File

@ -1,6 +1,5 @@
import 'package:chewie/chewie.dart'; import 'package:better_player/better_player.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
class VideoScreenMobile extends StatefulWidget { class VideoScreenMobile extends StatefulWidget {
const VideoScreenMobile({Key? key, required this.url}) : super(key: key); const VideoScreenMobile({Key? key, required this.url}) : super(key: key);
@ -11,27 +10,28 @@ class VideoScreenMobile extends StatefulWidget {
} }
class _VideoScreenMobileState extends State<VideoScreenMobile> { class _VideoScreenMobileState extends State<VideoScreenMobile> {
ChewieController? _chewieController; BetterPlayerController? _betterPlayerController;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (_chewieController == null) { if (_betterPlayerController == null) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: const [CircularProgressIndicator(), Text("loading...")], children: const [CircularProgressIndicator(), Text("loading...")],
); );
} else {
return BetterPlayer(
controller: _betterPlayerController!,
);
} }
return Chewie(
controller: _chewieController!,
);
} }
@override @override
void dispose() { void dispose() {
super.dispose(); super.dispose();
_chewieController?.videoPlayerController.dispose(); _betterPlayerController?.videoPlayerController?.dispose();
_chewieController?.dispose(); _betterPlayerController?.dispose();
} }
@override @override
@ -41,18 +41,12 @@ class _VideoScreenMobileState extends State<VideoScreenMobile> {
} }
void _init() async { void _init() async {
final VideoPlayerController _controller = BetterPlayerDataSource betterPlayerDataSource =
VideoPlayerController.network(widget.url); BetterPlayerDataSource(BetterPlayerDataSourceType.network, widget.url);
await _controller.initialize(); _betterPlayerController = BetterPlayerController(
BetterPlayerConfiguration(
_chewieController = ChewieController( autoPlay: true, looping: true, allowedScreenSleep: false),
videoPlayerController: _controller, betterPlayerDataSource: betterPlayerDataSource);
autoPlay: true,
looping: true,
allowFullScreen: true,
allowMuting: true,
allowPlaybackSpeedChanging: true,
zoomAndPan: true);
setState(() {}); setState(() {});
} }

View File

@ -8,8 +8,6 @@
#include <dart_vlc/dart_vlc_plugin.h> #include <dart_vlc/dart_vlc_plugin.h>
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h> #include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
#include <screen_retriever/screen_retriever_plugin.h>
#include <window_manager/window_manager_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) dart_vlc_registrar = g_autoptr(FlPluginRegistrar) dart_vlc_registrar =
@ -18,10 +16,4 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
g_autoptr(FlPluginRegistrar) screen_retriever_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin");
screen_retriever_plugin_register_with_registrar(screen_retriever_registrar);
g_autoptr(FlPluginRegistrar) window_manager_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin");
window_manager_plugin_register_with_registrar(window_manager_registrar);
} }

View File

@ -5,8 +5,6 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
dart_vlc dart_vlc
flutter_secure_storage_linux flutter_secure_storage_linux
screen_retriever
window_manager
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST

View File

@ -7,7 +7,7 @@ packages:
name: async name: async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.9.0" version: "2.8.2"
audio_video_progress_bar: audio_video_progress_bar:
dependency: transitive dependency: transitive
description: description:
@ -15,6 +15,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.10.0" version: "0.10.0"
better_player:
dependency: "direct main"
description:
name: better_player
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.83"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
@ -28,21 +35,21 @@ packages:
name: characters name: characters
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.1" version: "1.2.0"
chewie: charcode:
dependency: "direct main" dependency: transitive
description: description:
name: chewie name: charcode
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.4" version: "1.3.1"
clock: clock:
dependency: transitive dependency: transitive
description: description:
name: clock name: clock
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.1" version: "1.1.0"
collection: collection:
dependency: transitive dependency: transitive
description: description:
@ -56,7 +63,7 @@ packages:
name: csslib name: csslib
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.17.2" version: "0.17.1"
cupertino_icons: cupertino_icons:
dependency: "direct main" dependency: "direct main"
description: description:
@ -70,21 +77,21 @@ packages:
name: dart_vlc name: dart_vlc
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.3.0" version: "0.1.9"
dart_vlc_ffi: dart_vlc_ffi:
dependency: transitive dependency: transitive
description: description:
name: dart_vlc_ffi name: dart_vlc_ffi
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.8" version: "0.1.5+1"
device_info_plus: device_info_plus:
dependency: "direct main" dependency: "direct main"
description: description:
name: device_info_plus name: device_info_plus
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.0" version: "3.2.3"
device_info_plus_linux: device_info_plus_linux:
dependency: transitive dependency: transitive
description: description:
@ -105,7 +112,7 @@ packages:
name: device_info_plus_platform_interface name: device_info_plus_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.6.1" version: "2.3.0+1"
device_info_plus_web: device_info_plus_web:
dependency: transitive dependency: transitive
description: description:
@ -126,21 +133,21 @@ packages:
name: fake_async name: fake_async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.1" version: "1.3.0"
ffi: ffi:
dependency: transitive dependency: transitive
description: description:
name: ffi name: ffi
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.1" version: "1.1.2"
file: file:
dependency: transitive dependency: transitive
description: description:
name: file name: file
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.1.4" version: "6.1.2"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -153,34 +160,27 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.1" version: "2.0.1"
flutter_native_view:
dependency: transitive
description:
name: flutter_native_view
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.2"
flutter_secure_storage: flutter_secure_storage:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_secure_storage name: flutter_secure_storage
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.0.0" version: "5.0.2"
flutter_secure_storage_linux: flutter_secure_storage_linux:
dependency: transitive dependency: transitive
description: description:
name: flutter_secure_storage_linux name: flutter_secure_storage_linux
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.1" version: "1.1.0"
flutter_secure_storage_macos: flutter_secure_storage_macos:
dependency: transitive dependency: transitive
description: description:
name: flutter_secure_storage_macos name: flutter_secure_storage_macos
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.1" version: "1.1.0"
flutter_secure_storage_platform_interface: flutter_secure_storage_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -208,7 +208,7 @@ packages:
name: flutter_staggered_grid_view name: flutter_staggered_grid_view
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.6.2" version: "0.6.1"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -219,6 +219,20 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_widget_from_html_core:
dependency: transitive
description:
name: flutter_widget_from_html_core
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.5+3"
fwfh_text_style:
dependency: transitive
description:
name: fwfh_text_style
url: "https://pub.dartlang.org"
source: hosted
version: "2.22.08"
html: html:
dependency: transitive dependency: transitive
description: description:
@ -232,14 +246,14 @@ packages:
name: http name: http
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.13.5" version: "0.13.4"
http_parser: http_parser:
dependency: transitive dependency: transitive
description: description:
name: http_parser name: http_parser
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.1" version: "4.0.0"
js: js:
dependency: transitive dependency: transitive
description: description:
@ -267,35 +281,28 @@ packages:
name: matcher name: matcher
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.12.12" version: "0.12.11"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.5" version: "0.1.4"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.0" version: "1.7.0"
nested:
dependency: transitive
description:
name: nested
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
path: path:
dependency: "direct main" dependency: "direct main"
description: description:
name: path name: path
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.2" version: "1.8.1"
path_provider: path_provider:
dependency: transitive dependency: transitive
description: description:
@ -309,42 +316,49 @@ packages:
name: path_provider_android name: path_provider_android
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.20" version: "2.0.12"
path_provider_ios: path_provider_ios:
dependency: transitive dependency: transitive
description: description:
name: path_provider_ios name: path_provider_ios
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.11" version: "2.0.8"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
name: path_provider_linux name: path_provider_linux
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.7" version: "2.1.5"
path_provider_macos: path_provider_macos:
dependency: transitive dependency: transitive
description: description:
name: path_provider_macos name: path_provider_macos
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.6" version: "2.0.5"
path_provider_platform_interface: path_provider_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: path_provider_platform_interface name: path_provider_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.4" version: "2.0.1"
path_provider_windows: path_provider_windows:
dependency: transitive dependency: transitive
description: description:
name: path_provider_windows name: path_provider_windows
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.7" version: "2.0.5"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
version: "5.0.0"
platform: platform:
dependency: transitive dependency: transitive
description: description:
@ -366,20 +380,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.2.4" version: "4.2.4"
provider:
dependency: transitive
description:
name: provider
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.3"
screen_retriever:
dependency: transitive
description:
name: screen_retriever
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.2"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -391,7 +391,7 @@ packages:
name: source_span name: source_span
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.9.0" version: "1.8.2"
sqflite: sqflite:
dependency: "direct main" dependency: "direct main"
description: description:
@ -419,7 +419,7 @@ packages:
name: sqlite3 name: sqlite3
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.0" version: "1.7.0"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
@ -440,7 +440,7 @@ packages:
name: string_scanner name: string_scanner
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.1" version: "1.1.0"
synchronized: synchronized:
dependency: transitive dependency: transitive
description: description:
@ -454,21 +454,21 @@ packages:
name: term_glyph name: term_glyph
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.1" version: "1.2.0"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.12" version: "0.4.9"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
name: typed_data name: typed_data
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.1" version: "1.3.0"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
@ -476,48 +476,20 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.2" version: "2.1.2"
video_player: visibility_detector:
dependency: "direct main"
description:
name: video_player
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.7"
video_player_android:
dependency: transitive dependency: transitive
description: description:
name: video_player_android name: visibility_detector
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.3.9" version: "0.3.3"
video_player_avfoundation:
dependency: transitive
description:
name: video_player_avfoundation
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.5"
video_player_platform_interface:
dependency: transitive
description:
name: video_player_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "5.1.4"
video_player_web:
dependency: transitive
description:
name: video_player_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.12"
wakelock: wakelock:
dependency: transitive dependency: transitive
description: description:
name: wakelock name: wakelock
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.6.2" version: "0.6.1+2"
wakelock_macos: wakelock_macos:
dependency: transitive dependency: transitive
description: description:
@ -552,21 +524,21 @@ packages:
name: win32 name: win32
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.6.1" version: "2.5.1"
window_manager:
dependency: transitive
description:
name: window_manager
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.7"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
name: xdg_directories name: xdg_directories
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.0+2" version: "0.2.0+1"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.0"
sdks: sdks:
dart: ">=2.17.0 <3.0.0" dart: ">=2.17.0 <3.0.0"
flutter: ">=3.0.0" flutter: ">=3.0.0"

View File

@ -34,17 +34,16 @@ dependencies:
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2 cupertino_icons: ^1.0.2
flutter_secure_storage: ^6.0.0 flutter_secure_storage: ^5.0.2
logger: ^1.1.0 logger: ^1.1.0
http: ^0.13.4 http: ^0.13.4
flutter_staggered_grid_view: ^0.6.1 flutter_staggered_grid_view: ^0.6.1
dart_vlc: ^0.3.0 dart_vlc: ^0.1.9
device_info_plus: ^4.0.0 device_info_plus: ^3.2.3
video_player: ^2.3.0
chewie: ^1.3.2
sqflite: ^2.0.3+1 sqflite: ^2.0.3+1
path: ^1.8.1 path: ^1.8.1
sqflite_common_ffi: ^2.1.1+1 sqflite_common_ffi: ^2.1.1+1
better_player: ^0.0.83
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: