add a video page and disply tiles correctly
This commit is contained in:
parent
baed9c23d2
commit
d7184f09aa
@ -10,7 +10,6 @@ class API {
|
||||
String apinode, String action, Object payload) async {
|
||||
final Completer<String> cmpl = Completer();
|
||||
final t = await Token.getInstance().getToken();
|
||||
Log.d(t);
|
||||
if (t != null) {
|
||||
final resp = await http.post(
|
||||
Uri.parse(t.domain + '/api/$apinode/$action'),
|
||||
|
@ -31,8 +31,11 @@ class Token {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
final token = await _storage.read(key: 'jwt');
|
||||
final domain = await _storage.read(key: 'domain');
|
||||
|
||||
// check if value is defined in phone store
|
||||
if (token != null && domain != null) {
|
||||
_tokenval = token;
|
||||
_domain = domain;
|
||||
completer.complete(TokenT(token, domain));
|
||||
} else {
|
||||
Log.d("no token defined");
|
||||
|
@ -60,8 +60,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: const BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage('assets/images/login.png'), fit: BoxFit.cover),
|
||||
image: DecorationImage(image: AssetImage('assets/images/login.png'), fit: BoxFit.cover),
|
||||
),
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
@ -76,8 +75,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
),
|
||||
SingleChildScrollView(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(
|
||||
top: MediaQuery.of(context).size.height * 0.5),
|
||||
padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@ -88,6 +86,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
TextField(
|
||||
controller: _domainTextController,
|
||||
style: const TextStyle(color: Colors.black),
|
||||
autofocus: true,
|
||||
decoration: InputDecoration(
|
||||
fillColor: Colors.grey.shade100,
|
||||
filled: true,
|
||||
@ -103,6 +102,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
controller: _passwordTextController,
|
||||
style: const TextStyle(),
|
||||
obscureText: true,
|
||||
autofocus: true,
|
||||
decoration: InputDecoration(
|
||||
fillColor: Colors.grey.shade100,
|
||||
filled: true,
|
||||
@ -119,8 +119,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
children: [
|
||||
const Text(
|
||||
'Sign in',
|
||||
style: TextStyle(
|
||||
fontSize: 27, fontWeight: FontWeight.w700),
|
||||
style: TextStyle(fontSize: 27, fontWeight: FontWeight.w700),
|
||||
),
|
||||
CircleAvatar(
|
||||
radius: 30,
|
||||
@ -128,10 +127,9 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
child: IconButton(
|
||||
color: Colors.white,
|
||||
onPressed: () {
|
||||
final pwd =
|
||||
_passwordTextController.value.text;
|
||||
final domain =
|
||||
_domainTextController.value.text;
|
||||
Log.d("clickkked");
|
||||
final pwd = _passwordTextController.value.text;
|
||||
final domain = _domainTextController.value.text;
|
||||
login(pwd, domain).then((value) {
|
||||
if (value != "") {
|
||||
setState(() {
|
||||
|
@ -1,11 +1,36 @@
|
||||
import "package:dart_vlc/dart_vlc.dart";
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:openmediacentermobile/app.dart';
|
||||
|
||||
import 'log/log.dart';
|
||||
import 'login/logincontext.dart';
|
||||
import 'platform.dart';
|
||||
|
||||
// main app entry point
|
||||
void main() {
|
||||
void main() async {
|
||||
Log.i("App init!");
|
||||
runApp(const LoginContainer(child: App()));
|
||||
if (isDesktop()) {
|
||||
DartVLC.initialize();
|
||||
} else {
|
||||
await loadDeviceInfo();
|
||||
}
|
||||
|
||||
// RawKeyboard.instance.addListener((event) {
|
||||
// if (LogicalKeyboardKey.arrowLeft == event.logicalKey) {
|
||||
// FocusManager.instance.primaryFocus?.focusInDirection(TraversalDirection.left);
|
||||
// } else if (LogicalKeyboardKey.arrowRight == event.logicalKey) {
|
||||
// FocusManager.instance.primaryFocus?.focusInDirection(TraversalDirection.right);
|
||||
// } else if (LogicalKeyboardKey.arrowDown == event.logicalKey) {
|
||||
// FocusManager.instance.primaryFocus?.focusInDirection(TraversalDirection.down);
|
||||
// } else if (LogicalKeyboardKey.arrowUp == event.logicalKey) {
|
||||
// FocusManager.instance.primaryFocus?.focusInDirection(TraversalDirection.up);
|
||||
// }
|
||||
// });
|
||||
|
||||
runApp(Shortcuts(shortcuts: <LogicalKeySet, Intent>{
|
||||
LogicalKeySet(LogicalKeyboardKey.select): ActivateIntent(),
|
||||
}, child: const LoginContainer(child: App())));
|
||||
|
||||
// runApp(const LoginContainer(child: App()));
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:openmediacentermobile/videoscreen.dart';
|
||||
|
||||
import 'api/api.dart';
|
||||
import 'platform.dart';
|
||||
|
||||
class VideoT {
|
||||
int id;
|
||||
@ -12,8 +14,7 @@ class VideoT {
|
||||
VideoT(this.title, this.id, this.Ratio);
|
||||
|
||||
factory VideoT.fromJson(dynamic json) {
|
||||
return VideoT(json['MovieName'] as String, json['MovieId'] as int,
|
||||
(json['Ratio'] as num).toDouble());
|
||||
return VideoT(json['MovieName'] as String, json['MovieId'] as int, (json['Ratio'] as num).toDouble());
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,31 +27,82 @@ class PreviewTile extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _PreviewTileState extends State<PreviewTile> {
|
||||
String prev = "";
|
||||
late Future<Image> _preview;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
API.query("video", "readThumbnail", {'Movieid': widget.dta.id}).then(
|
||||
(value) {
|
||||
setState(() {
|
||||
prev = value.substring(23);
|
||||
});
|
||||
});
|
||||
_preview = loadData();
|
||||
}
|
||||
|
||||
Future<Image> loadData() async {
|
||||
final data = await API.query("video", "readThumbnail", {'Movieid': widget.dta.id});
|
||||
|
||||
final img = Image.memory(
|
||||
base64Decode(data.substring(23)),
|
||||
width: double.infinity,
|
||||
fit: BoxFit.fitWidth,
|
||||
);
|
||||
|
||||
// precache image to avoid loading time to render image
|
||||
await precacheImage(img.image, context);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
child: Column(
|
||||
return FutureBuilder<Image>(
|
||||
future: _preview, // a previously-obtained Future<String> or null
|
||||
builder: (BuildContext context, AsyncSnapshot<Image> snapshot) {
|
||||
if (snapshot.hasError) {
|
||||
return Text("Error");
|
||||
} else if (snapshot.hasData) {
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(20.0),
|
||||
child: Stack(
|
||||
children: [
|
||||
Text(widget.dta.title),
|
||||
prev != ""
|
||||
? Image.memory(base64Decode(prev))
|
||||
: const CircularProgressIndicator()
|
||||
Container(
|
||||
child: Column(
|
||||
children: [Text(widget.dta.title, style: TextStyle(fontSize: isTV() ? 8 : 12)), snapshot.data!],
|
||||
),
|
||||
color: Colors.green,
|
||||
),
|
||||
Positioned.fill(
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => VideoScreen(videoID: widget.dta.id),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Column(children: const <Widget>[
|
||||
SizedBox(height: 100),
|
||||
SizedBox(
|
||||
width: 60,
|
||||
height: 60,
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 16),
|
||||
child: Text('Awaiting result...'),
|
||||
),
|
||||
SizedBox(height: 100),
|
||||
]);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,9 @@ import 'package:flutter/material.dart';
|
||||
import 'package:openmediacentermobile/api/api.dart';
|
||||
|
||||
import 'log/log.dart';
|
||||
import 'platform.dart';
|
||||
import 'preview_tile.dart';
|
||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||
|
||||
class VideoFeed extends StatefulWidget {
|
||||
const VideoFeed({Key? key}) : super(key: key);
|
||||
@ -16,36 +18,59 @@ class VideoFeed extends StatefulWidget {
|
||||
}
|
||||
|
||||
class VideoFeedState extends State<VideoFeed> {
|
||||
List<VideoT> _vids = [];
|
||||
late Future<List<VideoT>> _data;
|
||||
|
||||
Future<List<VideoT>> loadData() async {
|
||||
final data = await API.query("video", "getMovies", {'Tag': 1, 'Sort': 0});
|
||||
|
||||
final d = jsonDecode(data);
|
||||
|
||||
List<VideoT> dta = (d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList();
|
||||
|
||||
return dta;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
API.query("video", "getMovies", {'Tag': 1, 'Sort': 0}).then((value) {
|
||||
final d = jsonDecode(value);
|
||||
|
||||
List<VideoT> dta =
|
||||
(d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList();
|
||||
|
||||
setState(() {
|
||||
_vids = dta;
|
||||
});
|
||||
});
|
||||
_data = loadData();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GridView.builder(
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
childAspectRatio: MediaQuery.of(context).size.width /
|
||||
MediaQuery.of(context).size.height,
|
||||
crossAxisSpacing: 10),
|
||||
itemCount: _vids.length,
|
||||
double width = MediaQuery.of(context).size.width;
|
||||
Log.d(width);
|
||||
|
||||
return FutureBuilder<List<VideoT>>(
|
||||
future: _data, // a previously-obtained Future<String> or null
|
||||
builder: (BuildContext context, AsyncSnapshot<List<VideoT>> snapshot) {
|
||||
if (snapshot.hasError) {
|
||||
return Text("Error");
|
||||
} else if (snapshot.hasData) {
|
||||
return MasonryGridView.count(
|
||||
// every tile should be at max 330 pixels long...
|
||||
crossAxisCount: isTV() ? width ~/ 200 : width ~/ 330,
|
||||
mainAxisSpacing: 4,
|
||||
crossAxisSpacing: 4,
|
||||
itemBuilder: (context, index) {
|
||||
Log.d("item $index built!");
|
||||
return PreviewTile(dta: _vids[index]);
|
||||
});
|
||||
return PreviewTile(dta: snapshot.data![index]);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return Column(children: const <Widget>[
|
||||
SizedBox(
|
||||
width: 60,
|
||||
height: 60,
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 16),
|
||||
child: Text('Awaiting result...'),
|
||||
)
|
||||
]);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
177
pubspec.lock
177
pubspec.lock
@ -8,6 +8,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.8.2"
|
||||
audio_video_progress_bar:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: audio_video_progress_bar
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.10.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -50,6 +57,62 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
dart_vlc:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: dart_vlc
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.9"
|
||||
dart_vlc_ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_vlc_ffi
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.5+1"
|
||||
device_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: device_info_plus
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.2.3"
|
||||
device_info_plus_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info_plus_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
device_info_plus_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info_plus_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.3"
|
||||
device_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info_plus_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.3.0+1"
|
||||
device_info_plus_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info_plus_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
device_info_plus_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info_plus_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -57,6 +120,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.1.2"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -111,6 +188,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
flutter_staggered_grid_view:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_staggered_grid_view
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
@ -141,7 +225,7 @@ packages:
|
||||
name: js
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.3"
|
||||
version: "0.6.4"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -169,7 +253,7 @@ packages:
|
||||
name: material_color_utilities
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.2"
|
||||
version: "0.1.4"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -183,7 +267,63 @@ packages:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
version: "1.8.1"
|
||||
path_provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.9"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.12"
|
||||
path_provider_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_ios
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.8"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
path_provider_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -191,6 +331,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.2.4"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@ -202,7 +349,7 @@ packages:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.1"
|
||||
version: "1.8.2"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -237,7 +384,7 @@ packages:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.8"
|
||||
version: "0.4.9"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -251,7 +398,21 @@ packages:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.5.1"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.0+1"
|
||||
sdks:
|
||||
dart: ">=2.15.0 <3.0.0"
|
||||
flutter: ">=2.0.0"
|
||||
dart: ">=2.16.0-100.0.dev <3.0.0"
|
||||
flutter: ">=2.8.0"
|
||||
|
@ -37,6 +37,9 @@ dependencies:
|
||||
flutter_secure_storage: ^5.0.2
|
||||
logger: ^1.1.0
|
||||
http: ^0.13.4
|
||||
flutter_staggered_grid_view: ^0.6.1
|
||||
dart_vlc: ^0.1.9
|
||||
device_info_plus: ^3.2.3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
Reference in New Issue
Block a user