Compare commits
6 Commits
better_pla
...
tv_shows
Author | SHA1 | Date | |
---|---|---|---|
eff1ea0812 | |||
6f6fbb3897 | |||
9ef317f0ba | |||
cb42db80af | |||
7ff0d387b5 | |||
d96bc57c09 |
@ -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 flutter.compileSdkVersion
|
compileSdkVersion 33
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.4.32'
|
ext.kotlin_version = '1.6.10'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
classpath 'com.android.tools.build:gradle:7.1.2'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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-6.7-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import '../log/log.dart';
|
||||||
import '../types/actor.dart';
|
import '../types/actor.dart';
|
||||||
import 'api.dart';
|
import 'api.dart';
|
||||||
|
|
||||||
@ -10,3 +11,26 @@ 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
42
lib/api/settings_api.dart
Normal file
42
lib/api/settings_api.dart
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
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;
|
||||||
|
}
|
23
lib/api/tag_api.dart
Normal file
23
lib/api/tag_api.dart
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
@ -8,8 +8,10 @@ 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);
|
TokenT(this.token, this.domain, this.videoPath, this.tvPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Token {
|
class Token {
|
||||||
@ -18,40 +20,46 @@ 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 {
|
||||||
var completer = Completer<TokenT?>();
|
if (_tokenval == "" || _domain == "" || _vPath == "") {
|
||||||
|
|
||||||
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) {
|
if (token != null && domain != null && vPath != null) {
|
||||||
_tokenval = token;
|
_tokenval = token;
|
||||||
_domain = domain;
|
_domain = domain;
|
||||||
completer.complete(TokenT(token, domain));
|
return TokenT(token, domain, vPath, tvPath ?? "");
|
||||||
} else {
|
} else {
|
||||||
Log.d("no token defined");
|
Log.d("no token defined");
|
||||||
completer.complete(null);
|
return null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
completer.complete(TokenT(_tokenval, _domain));
|
return TokenT(_tokenval, _domain, _vPath, _tvPath);
|
||||||
}
|
}
|
||||||
return completer.future;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setToken(String token, String domain) {
|
void setToken(String token, String domain, String videoPath, String tvPath) {
|
||||||
_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._();
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
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';
|
||||||
|
|
||||||
@ -10,3 +16,55 @@ 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));
|
||||||
|
}
|
||||||
|
13
lib/app.dart
13
lib/app.dart
@ -3,15 +3,17 @@ 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/logincontext.dart';
|
import 'login/login_context.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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,18 +22,21 @@ class App extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var loginCtx = LoginContext.of(context);
|
final 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 MaterialApp(
|
return FeatureContainer(
|
||||||
|
child: MaterialApp(
|
||||||
scrollBehavior: AppScrollBehavior(),
|
scrollBehavior: AppScrollBehavior(),
|
||||||
home: DrawerPage(
|
home: DrawerPage(
|
||||||
title: 'OpenMediaCenter',
|
title: 'OpenMediaCenter',
|
||||||
));
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,8 @@ 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)',
|
||||||
);
|
);
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
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';
|
||||||
|
|
||||||
@ -19,16 +15,6 @@ 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();
|
||||||
@ -52,7 +38,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);
|
await addActorToVideo(e.actorId, widget.movieId);
|
||||||
Navigator.pop(context, e);
|
Navigator.pop(context, e);
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../api/api.dart';
|
import '../api/tag_api.dart';
|
||||||
import '../log/log.dart';
|
|
||||||
import '../screen_loading.dart';
|
import '../screen_loading.dart';
|
||||||
import '../types/tag.dart';
|
import '../types/tag.dart';
|
||||||
|
|
||||||
@ -18,24 +15,6 @@ 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();
|
||||||
@ -60,7 +39,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);
|
await addTagToVideo(e.tagId, widget.movieId);
|
||||||
Navigator.pop(context, e);
|
Navigator.pop(context, e);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -2,7 +2,8 @@ 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/shufflescreen.dart';
|
import '../navigation/shuffle_screen.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';
|
||||||
|
|
||||||
@ -15,7 +16,7 @@ class DrawerPage extends StatefulWidget {
|
|||||||
_DrawerPageState createState() => _DrawerPageState();
|
_DrawerPageState createState() => _DrawerPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Section { HOME, SHUFFLE, SETTING, CATEGORIE, ACTOR }
|
enum Section { HOME, SHUFFLE, SETTING, CATEGORIE, ACTOR, TVSHOW }
|
||||||
|
|
||||||
class _DrawerPageState extends State<DrawerPage> {
|
class _DrawerPageState extends State<DrawerPage> {
|
||||||
Section _sec = Section.HOME;
|
Section _sec = Section.HOME;
|
||||||
@ -50,6 +51,11 @@ 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(
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
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';
|
||||||
@ -9,6 +10,7 @@ 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: [
|
||||||
@ -44,6 +46,15 @@ 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),
|
||||||
|
@ -2,6 +2,7 @@ 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);
|
||||||
@ -18,22 +19,23 @@ class _LoginContainerState extends State<LoginContainer> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_init();
|
||||||
|
}
|
||||||
|
|
||||||
final token = Token.getInstance();
|
void _init() async {
|
||||||
token.getToken().then((value) {
|
final token = await Token.getInstance().getToken();
|
||||||
Log.i("The token value is $value");
|
Log.i("The token value is $token");
|
||||||
if (value != null) {
|
if (token != 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
|
||||||
@ -58,27 +60,3 @@ 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;
|
|
||||||
}
|
|
||||||
}
|
|
25
lib/login/login_context.dart
Normal file
25
lib/login/login_context.dart
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -3,9 +3,10 @@ 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 'package:openmediacentermobile/api/token.dart';
|
import '../api/settings_api.dart';
|
||||||
import 'package:openmediacentermobile/log/log.dart';
|
import '../api/token.dart';
|
||||||
import 'package:openmediacentermobile/login/logincontext.dart';
|
import '../log/log.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);
|
||||||
@ -39,19 +40,45 @@ 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"];
|
||||||
|
|
||||||
Token.getInstance().setToken(token, domain);
|
// todo bit hacky
|
||||||
|
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();
|
||||||
@ -132,33 +159,7 @@ 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 {
|
onPressed: () async => await onLoginClick(),
|
||||||
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,
|
||||||
)),
|
)),
|
||||||
|
@ -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/logincontext.dart';
|
import 'login/login_container.dart';
|
||||||
import 'utils/platform.dart';
|
import 'utils/platform.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
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 '../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 {
|
||||||
@ -18,18 +16,10 @@ 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 = loadVideoData();
|
_categories = loadAllTags();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:openmediacentermobile/utils/FileFormatter.dart';
|
import '../utils/file_formatter.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/logincontext.dart';
|
import '../login/login_context.dart';
|
||||||
|
|
||||||
class SettingsScreen extends StatefulWidget {
|
class SettingsScreen extends StatefulWidget {
|
||||||
const SettingsScreen({Key? key}) : super(key: key);
|
const SettingsScreen({Key? key}) : super(key: key);
|
||||||
@ -15,6 +15,7 @@ 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() {
|
||||||
@ -22,6 +23,10 @@ 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
|
||||||
@ -34,6 +39,7 @@ 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();
|
||||||
@ -47,7 +53,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"))
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
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);
|
||||||
@ -16,18 +13,6 @@ 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;
|
||||||
@ -38,7 +23,8 @@ class _ShuffleScreenState extends State<ShuffleScreen> {
|
|||||||
),
|
),
|
||||||
body: PreviewGrid(
|
body: PreviewGrid(
|
||||||
videoLoader: () {
|
videoLoader: () {
|
||||||
return loadData((isTV() ? width ~/ 200 : width ~/ 275) * 2);
|
return loadShuffledVideos(
|
||||||
|
(isTV() ? width ~/ 200 : width ~/ 275) * 2);
|
||||||
},
|
},
|
||||||
footerBuilder: (state) => Column(
|
footerBuilder: (state) => Column(
|
||||||
children: [
|
children: [
|
15
lib/navigation/tv_show_screen.dart
Normal file
15
lib/navigation/tv_show_screen.dart
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,9 @@
|
|||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import '../api/video_api.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 }
|
||||||
|
|
||||||
@ -24,18 +21,6 @@ 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(
|
||||||
@ -80,7 +65,7 @@ class VideoFeedState extends State<VideoFeed> {
|
|||||||
),
|
),
|
||||||
body: PreviewGrid(
|
body: PreviewGrid(
|
||||||
key: _refreshKey,
|
key: _refreshKey,
|
||||||
videoLoader: () => loadData(),
|
videoLoader: () => loadVideo(widget.tag, filterSelection.index),
|
||||||
),
|
),
|
||||||
drawer: widget.tag == null ? MyDrawer() : null);
|
drawer: widget.tag == null ? MyDrawer() : null);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../api/api.dart';
|
import '../api/video_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);
|
||||||
@ -16,22 +13,10 @@ 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: () => loadData(),
|
videoLoader: () => loadVideoByActor(widget.actor),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:openmediacentermobile/preview/actor_feed.dart';
|
import '../preview/actor_feed.dart';
|
||||||
|
|
||||||
import '../utils/platform.dart';
|
import '../utils/platform.dart';
|
||||||
import '../types/actor.dart';
|
import '../types/actor.dart';
|
||||||
|
@ -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 Column(
|
return Center(
|
||||||
children: [
|
child: Column(
|
||||||
Text("Error"),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
TextButton(
|
children: [
|
||||||
onPressed: () {
|
Text("Error"),
|
||||||
loadData();
|
TextButton(
|
||||||
},
|
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);
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
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/api.dart';
|
import '../api/video_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';
|
||||||
@ -53,23 +50,17 @@ 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 {
|
||||||
|
@ -18,7 +18,7 @@ class TagTile extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(primary: Color(0x6a94a6ff)),
|
style: ElevatedButton.styleFrom(backgroundColor: Color(0x6a94a6ff)),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
child: Center(child: Text(tag.tagName)),
|
child: Center(child: Text(tag.tagName)),
|
||||||
height: 100,
|
height: 100,
|
||||||
|
92
lib/utils/feature_context.dart
Normal file
92
lib/utils/feature_context.dart
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
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';
|
||||||
@ -8,9 +7,6 @@ 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 {
|
||||||
@ -29,7 +25,7 @@ class _InfoViewState extends State<InfoView> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
setState(() {
|
setState(() {
|
||||||
_data = loadData();
|
_data = loadActorsOfVideo(widget.videoId);
|
||||||
vdata = loadVideoData(widget.videoId);
|
vdata = loadVideoData(widget.videoId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -39,19 +35,6 @@ 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(
|
||||||
@ -71,15 +54,10 @@ class _InfoViewState extends State<InfoView> {
|
|||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final data = await API.query("video", "addLike",
|
if (await addLike(videoData.movieId))
|
||||||
{'MovieId': videoData.movieId});
|
setState(() {
|
||||||
final d = jsonDecode(data);
|
vdata = loadVideoData(widget.videoId);
|
||||||
if (d["result"] != 'success') {
|
});
|
||||||
Log.w(d);
|
|
||||||
}
|
|
||||||
setState(() {
|
|
||||||
vdata = loadVideoData(widget.videoId);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
icon: Icon(Icons.thumb_up)),
|
icon: Icon(Icons.thumb_up)),
|
||||||
TextButton(
|
TextButton(
|
||||||
@ -90,9 +68,8 @@ class _InfoViewState extends State<InfoView> {
|
|||||||
movieId: videoData.movieId,
|
movieId: videoData.movieId,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
Log.d("finished dialog");
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_data = loadData();
|
_data = loadActorsOfVideo(widget.videoId);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Text("Add Actor"),
|
child: Text("Add Actor"),
|
||||||
@ -105,7 +82,6 @@ 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);
|
||||||
});
|
});
|
||||||
|
@ -37,9 +37,7 @@ 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 baseurl = token.domain;
|
final path = token.domain + token.videoPath + videodata.movieUrl;
|
||||||
// todo not static middle path
|
|
||||||
final path = baseurl + "/videos/vids/" + videodata.movieUrl;
|
|
||||||
|
|
||||||
url = path;
|
url = path;
|
||||||
}
|
}
|
||||||
@ -94,7 +92,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: 100));
|
await Future.delayed(Duration(milliseconds: 300));
|
||||||
setState(() {
|
setState(() {
|
||||||
_appBarVisible = false;
|
_appBarVisible = false;
|
||||||
});
|
});
|
||||||
|
@ -18,11 +18,10 @@ class _VideoScreenDesktopState extends State<VideoScreenDesktop> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Video(
|
return Video(
|
||||||
player: _player,
|
player: _player,
|
||||||
scale: 1.0, // default
|
showFullscreenButton: true,
|
||||||
showControls: true,
|
scale: 1.0, // default
|
||||||
playlistLength: 1,
|
showControls: true);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#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 =
|
||||||
@ -16,4 +18,10 @@ 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);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
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
|
||||||
|
127
pubspec.lock
127
pubspec.lock
@ -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.8.2"
|
version: "2.9.0"
|
||||||
audio_video_progress_bar:
|
audio_video_progress_bar:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -28,28 +28,21 @@ packages:
|
|||||||
name: characters
|
name: characters
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.1"
|
||||||
charcode:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: charcode
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.1"
|
|
||||||
chewie:
|
chewie:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: chewie
|
name: chewie
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.2"
|
version: "1.3.4"
|
||||||
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.0"
|
version: "1.1.1"
|
||||||
collection:
|
collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -63,35 +56,35 @@ packages:
|
|||||||
name: csslib
|
name: csslib
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.17.1"
|
version: "0.17.2"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: cupertino_icons
|
name: cupertino_icons
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.5"
|
||||||
dart_vlc:
|
dart_vlc:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: dart_vlc
|
name: dart_vlc
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.9"
|
version: "0.3.0"
|
||||||
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.5+1"
|
version: "0.1.8"
|
||||||
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: "3.2.3"
|
version: "4.0.0"
|
||||||
device_info_plus_linux:
|
device_info_plus_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -112,7 +105,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.3.0+1"
|
version: "2.6.1"
|
||||||
device_info_plus_web:
|
device_info_plus_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -133,21 +126,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.0"
|
version: "1.3.1"
|
||||||
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.1.2"
|
version: "1.2.1"
|
||||||
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.2"
|
version: "6.1.4"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -160,27 +153,34 @@ 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: "5.0.2"
|
version: "6.0.0"
|
||||||
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.0"
|
version: "1.1.1"
|
||||||
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.0"
|
version: "1.1.1"
|
||||||
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.1"
|
version: "0.6.2"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -232,14 +232,14 @@ packages:
|
|||||||
name: http
|
name: http
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.13.4"
|
version: "0.13.5"
|
||||||
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.0"
|
version: "4.0.1"
|
||||||
js:
|
js:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -267,21 +267,21 @@ packages:
|
|||||||
name: matcher
|
name: matcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.11"
|
version: "0.12.12"
|
||||||
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.4"
|
version: "0.1.5"
|
||||||
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.7.0"
|
version: "1.8.0"
|
||||||
nested:
|
nested:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -295,56 +295,56 @@ packages:
|
|||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.1"
|
version: "1.8.2"
|
||||||
path_provider:
|
path_provider:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider
|
name: path_provider
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.9"
|
version: "2.0.11"
|
||||||
path_provider_android:
|
path_provider_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
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.12"
|
version: "2.0.20"
|
||||||
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.8"
|
version: "2.0.11"
|
||||||
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.5"
|
version: "2.1.7"
|
||||||
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.5"
|
version: "2.0.6"
|
||||||
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.1"
|
version: "2.0.4"
|
||||||
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.5"
|
version: "2.0.7"
|
||||||
platform:
|
platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -372,7 +372,14 @@ packages:
|
|||||||
name: provider
|
name: provider
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.2"
|
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
|
||||||
@ -384,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.8.2"
|
version: "1.9.0"
|
||||||
sqflite:
|
sqflite:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -412,7 +419,7 @@ packages:
|
|||||||
name: sqlite3
|
name: sqlite3
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.7.0"
|
version: "1.8.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -433,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.0"
|
version: "1.1.1"
|
||||||
synchronized:
|
synchronized:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -447,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.0"
|
version: "1.2.1"
|
||||||
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.9"
|
version: "0.4.12"
|
||||||
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.0"
|
version: "1.3.1"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -469,55 +476,48 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.2"
|
||||||
very_good_analysis:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: very_good_analysis
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.4.0"
|
|
||||||
video_player:
|
video_player:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: video_player
|
name: video_player
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0"
|
version: "2.4.7"
|
||||||
video_player_android:
|
video_player_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: video_player_android
|
name: video_player_android
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.2"
|
version: "2.3.9"
|
||||||
video_player_avfoundation:
|
video_player_avfoundation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: video_player_avfoundation
|
name: video_player_avfoundation
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.1"
|
version: "2.3.5"
|
||||||
video_player_platform_interface:
|
video_player_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: video_player_platform_interface
|
name: video_player_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.1.1"
|
version: "5.1.4"
|
||||||
video_player_web:
|
video_player_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: video_player_web
|
name: video_player_web
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.7"
|
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.1+2"
|
version: "0.6.2"
|
||||||
wakelock_macos:
|
wakelock_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -552,14 +552,21 @@ packages:
|
|||||||
name: win32
|
name: win32
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.5.1"
|
version: "2.6.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+1"
|
version: "0.2.0+2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.17.0-206.0.dev <3.0.0"
|
dart: ">=2.17.0 <3.0.0"
|
||||||
flutter: ">=3.0.0"
|
flutter: ">=3.0.0"
|
||||||
|
@ -34,12 +34,12 @@ 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: ^5.0.2
|
flutter_secure_storage: ^6.0.0
|
||||||
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.1.9
|
dart_vlc: ^0.3.0
|
||||||
device_info_plus: ^3.2.3
|
device_info_plus: ^4.0.0
|
||||||
video_player: ^2.3.0
|
video_player: ^2.3.0
|
||||||
chewie: ^1.3.2
|
chewie: ^1.3.2
|
||||||
sqflite: ^2.0.3+1
|
sqflite: ^2.0.3+1
|
||||||
|
Reference in New Issue
Block a user