format, lint

outsource preview table in several function
revert android compile version
This commit is contained in:
lukas-heiligenbrunner 2022-08-25 22:48:44 +02:00
parent 404d1d7cf7
commit a7757b14dd
17 changed files with 184 additions and 134 deletions

View File

@ -13,3 +13,13 @@ flutter_build_android: #Job name
artifacts: artifacts:
paths: paths:
- build/app/outputs/apk/release/app-release.apk - build/app/outputs/apk/release/app-release.apk
flutter_lint:
stage: build
script:
- flutter format . --output none --set-exit-if-changed
flutter_analyze:
stage: build
script:
- flutter analyze ./lib

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
@ -45,7 +45,7 @@ android {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "eu.heili.openmediacentermobile" applicationId "eu.heili.openmediacentermobile"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 30 targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
} }

View File

@ -1,5 +1,5 @@
buildscript { buildscript {
ext.kotlin_version = '1.6.0' ext.kotlin_version = '1.4.32'
repositories { repositories {
google() google()
mavenCentral() mavenCentral()

View File

@ -44,14 +44,17 @@ class _DrawerPageState extends State<DrawerPage> {
final loginCtx = LoginContext.of(context); final loginCtx = LoginContext.of(context);
return Scaffold( return Scaffold(
appBar: AppBar(title: Text(title), actions: [ appBar: AppBar(
title: Text(title),
actions: [
IconButton( IconButton(
onPressed: () { onPressed: () {
loginCtx.onLoggin(false); loginCtx.onLoggin(false);
Token.getInstance().setToken("", ""); Token.getInstance().setToken("", "");
}, },
icon: const Icon(Icons.logout)) icon: const Icon(Icons.logout))
],), ],
),
body: body, body: body,
drawer: Drawer( drawer: Drawer(
child: ListView(children: [ child: ListView(children: [

View File

@ -18,7 +18,6 @@ class _LoginScreenState extends State<LoginScreen> {
final TextEditingController _domainTextController = TextEditingController(); final TextEditingController _domainTextController = TextEditingController();
final TextEditingController _passwordTextController = TextEditingController(); final TextEditingController _passwordTextController = TextEditingController();
String error = ""; String error = "";
bool _loginActive = false;
Future<String> login(String password, String domain) async { Future<String> login(String password, String domain) async {
Log.i("logging in..."); Log.i("logging in...");
@ -64,7 +63,8 @@ class _LoginScreenState extends State<LoginScreen> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
decoration: const BoxDecoration( 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( child: Scaffold(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
@ -79,7 +79,8 @@ class _LoginScreenState extends State<LoginScreen> {
), ),
SingleChildScrollView( SingleChildScrollView(
child: Container( 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( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -123,7 +124,8 @@ class _LoginScreenState extends State<LoginScreen> {
children: [ children: [
const Text( const Text(
'Sign in', 'Sign in',
style: TextStyle(fontSize: 27, fontWeight: FontWeight.w700), style: TextStyle(
fontSize: 27, fontWeight: FontWeight.w700),
), ),
CircleAvatar( CircleAvatar(
radius: 30, radius: 30,
@ -132,18 +134,23 @@ class _LoginScreenState extends State<LoginScreen> {
color: Colors.white, color: Colors.white,
onPressed: () async { onPressed: () async {
Log.d("clickkked"); Log.d("clickkked");
final pwd = _passwordTextController.value.text; final pwd =
final domain = _domainTextController.value.text; _passwordTextController.value.text;
final domain =
_domainTextController.value.text;
var err = ""; var err = "";
if (domain.startsWith("https://") || domain.startsWith("http://")) { if (domain.startsWith("https://") ||
domain.startsWith("http://")) {
err = await login(pwd, domain); err = await login(pwd, domain);
if (err.isEmpty) return; if (err.isEmpty) return;
} else { } else {
// try to auto infering domain prefix // try to auto infering domain prefix
err = await login(pwd, "https://" + domain); err = await login(
pwd, "https://" + domain);
if (err.isEmpty) return; if (err.isEmpty) return;
err = await login(pwd, "http://" + domain); err = await login(
pwd, "http://" + domain);
if (err.isEmpty) return; if (err.isEmpty) return;
} }

View File

@ -11,7 +11,6 @@ void main() async {
Log.i("App init!"); Log.i("App init!");
DartVLC.initialize(); DartVLC.initialize();
if (isDesktop()) { if (isDesktop()) {
} else { } else {
await loadDeviceInfo(); await loadDeviceInfo();
} }

View File

@ -7,7 +7,8 @@ import 'package:flutter/foundation.dart';
bool _isTV = false; bool _isTV = false;
bool isDesktop() { bool isDesktop() {
return (Platform.isLinux || Platform.isWindows || Platform.isMacOS) && !kIsWeb; return (Platform.isLinux || Platform.isWindows || Platform.isMacOS) &&
!kIsWeb;
} }
Future<void> loadDeviceInfo() async { Future<void> loadDeviceInfo() async {

View File

@ -6,7 +6,12 @@ import 'package:openmediacentermobile/platform.dart';
import 'package:openmediacentermobile/preview_tile.dart'; import 'package:openmediacentermobile/preview_tile.dart';
class PreviewGrid extends StatefulWidget { class PreviewGrid extends StatefulWidget {
const PreviewGrid({Key? key, required this.videoLoader, this.headerBuilder, this.footerBuilder}) : super(key: key); const PreviewGrid(
{Key? key,
required this.videoLoader,
this.headerBuilder,
this.footerBuilder})
: super(key: key);
final Future<List<VideoT>> Function() videoLoader; final Future<List<VideoT>> Function() videoLoader;
final Widget Function(_PreviewGridState state)? footerBuilder; final Widget Function(_PreviewGridState state)? footerBuilder;
@ -37,11 +42,34 @@ class _PreviewGridState extends State<PreviewGrid> {
final double width = MediaQuery.of(context).size.width; final double width = MediaQuery.of(context).size.width;
return FutureBuilder<List<VideoT>>( return FutureBuilder<List<VideoT>>(
future: _data, // a previously-obtained Future<String> or null future: _data,
builder: (BuildContext context, AsyncSnapshot<List<VideoT>> snapshot) { builder: (BuildContext context, AsyncSnapshot<List<VideoT>> snapshot) {
if (snapshot.hasError) { if (snapshot.hasError) {
return Text("Error"); return Text("Error");
} else if (snapshot.hasData) { } else if (snapshot.hasData) {
return _mainGrid(snapshot.data!, width);
} else {
return _pageLoading();
}
},
);
}
Widget _pageLoading() {
return Column(children: const <Widget>[
SizedBox(
width: 60,
height: 60,
child: CircularProgressIndicator(),
),
Padding(
padding: EdgeInsets.only(top: 16),
child: Text('Awaiting result...'),
)
]);
}
Widget _mainGrid(List<VideoT> data, double width) {
return Stack( return Stack(
children: [ children: [
Column( Column(
@ -52,13 +80,13 @@ class _PreviewGridState extends State<PreviewGrid> {
// every tile should be at max 330 pixels long... // every tile should be at max 330 pixels long...
crossAxisCount: isTV() ? width ~/ 200 : width ~/ 275, crossAxisCount: isTV() ? width ~/ 200 : width ~/ 275,
// crossAxisCount: isTV() ? width ~/ 200 : width ~/ 330, // crossAxisCount: isTV() ? width ~/ 200 : width ~/ 330,
itemCount: snapshot.data!.length, itemCount: data.length,
mainAxisSpacing: 4, mainAxisSpacing: 4,
crossAxisSpacing: 4, crossAxisSpacing: 4,
padding: EdgeInsets.all(5), padding: EdgeInsets.all(5),
itemBuilder: (context, index) { itemBuilder: (context, index) {
return PreviewTile( return PreviewTile(
dta: snapshot.data![index], dta: data[index],
onLongPress: (img) { onLongPress: (img) {
setState(() { setState(() {
_previewImage = img; _previewImage = img;
@ -76,7 +104,13 @@ class _PreviewGridState extends State<PreviewGrid> {
if (widget.footerBuilder != null) widget.footerBuilder!(this), if (widget.footerBuilder != null) widget.footerBuilder!(this),
], ],
), ),
if (_previewImage != null) ...[ if (_previewImage != null) ..._buildPreviewImage(),
],
);
}
List<Widget> _buildPreviewImage() {
return [
BackdropFilter( BackdropFilter(
filter: ImageFilter.blur( filter: ImageFilter.blur(
sigmaX: 5.0, sigmaX: 5.0,
@ -90,26 +124,12 @@ class _PreviewGridState extends State<PreviewGrid> {
child: Center( child: Center(
child: Padding( child: Padding(
padding: EdgeInsets.symmetric(horizontal: 50), padding: EdgeInsets.symmetric(horizontal: 50),
child: ClipRRect(borderRadius: BorderRadius.circular(10.0), child: _previewImage!)), child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: _previewImage!),
), ),
), ),
],
],
);
} else {
return Column(children: const <Widget>[
SizedBox(
width: 60,
height: 60,
child: CircularProgressIndicator(),
), ),
Padding( ];
padding: EdgeInsets.only(top: 16),
child: Text('Awaiting result...'),
)
]);
}
},
);
} }
} }

View File

@ -17,12 +17,15 @@ class VideoT {
VideoT(this.title, this.id, this.ratio); VideoT(this.title, this.id, this.ratio);
factory VideoT.fromJson(dynamic json) { 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());
} }
} }
class PreviewTile extends StatefulWidget { class PreviewTile extends StatefulWidget {
const PreviewTile({Key? key, required this.dta, this.onLongPress, this.onLongPressEnd}) : super(key: key); const PreviewTile(
{Key? key, required this.dta, this.onLongPress, this.onLongPressEnd})
: super(key: key);
final VideoT dta; final VideoT dta;
final Function(Image img)? onLongPress; final Function(Image img)? onLongPress;
final Function? onLongPressEnd; final Function? onLongPressEnd;
@ -53,7 +56,8 @@ class _PreviewTileState extends State<PreviewTile> {
} }
Future<Image> loadData() async { Future<Image> loadData() async {
final data = await API.query("video", "readThumbnail", {'Movieid': widget.dta.id}); final data =
await API.query("video", "readThumbnail", {'Movieid': widget.dta.id});
final img = Image.memory( final img = Image.memory(
base64Decode(data.substring(23)), base64Decode(data.substring(23)),
@ -99,17 +103,20 @@ class _PreviewTileState extends State<PreviewTile> {
child: GestureDetector( child: GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
onLongPress: () { onLongPress: () {
if (widget.onLongPress != null) widget.onLongPress!(snapshot.data!); if (widget.onLongPress != null)
widget.onLongPress!(snapshot.data!);
}, },
onLongPressEnd: (details) { onLongPressEnd: (details) {
if (widget.onLongPressEnd != null) widget.onLongPressEnd!(); if (widget.onLongPressEnd != null)
widget.onLongPressEnd!();
}, },
child: InkWell( child: InkWell(
onTap: () { onTap: () {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => VideoScreen(metaData: widget.dta), builder: (context) =>
VideoScreen(metaData: widget.dta),
), ),
); );
}, },

View File

@ -17,11 +17,13 @@ class ShuffleScreen extends StatefulWidget {
class _ShuffleScreenState extends State<ShuffleScreen> { class _ShuffleScreenState extends State<ShuffleScreen> {
Future<List<VideoT>> loadData(int nr) async { Future<List<VideoT>> loadData(int nr) async {
final data = await API.query("video", "getRandomMovies", {'Number': nr, 'Seed': Random().nextInt(0x7fffffff)}); final data = await API.query("video", "getRandomMovies",
{'Number': nr, 'Seed': Random().nextInt(0x7fffffff)});
final d = jsonDecode(data); final d = jsonDecode(data);
List<VideoT> dta = (d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList(); List<VideoT> dta =
(d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList();
return dta; return dta;
} }

View File

@ -17,13 +17,13 @@ class VideoFeed extends StatefulWidget {
} }
class VideoFeedState extends State<VideoFeed> { class VideoFeedState extends State<VideoFeed> {
Future<List<VideoT>> loadData() async { Future<List<VideoT>> loadData() async {
final data = await API.query("video", "getMovies", {'Tag': 1, 'Sort': 0}); final data = await API.query("video", "getMovies", {'Tag': 1, 'Sort': 0});
final d = jsonDecode(data); final d = jsonDecode(data);
List<VideoT> dta = (d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList(); List<VideoT> dta =
(d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList();
return dta; return dta;
} }
@ -33,6 +33,8 @@ class VideoFeedState extends State<VideoFeed> {
double width = MediaQuery.of(context).size.width; double width = MediaQuery.of(context).size.width;
Log.d(width); Log.d(width);
return PreviewGrid(videoLoader: () => loadData(),); return PreviewGrid(
videoLoader: () => loadData(),
);
} }
} }

View File

@ -10,7 +10,6 @@ import 'package:video_player/video_player.dart';
import 'api/api.dart'; import 'api/api.dart';
import 'api/token.dart'; import 'api/token.dart';
import 'log/log.dart';
import 'platform.dart'; import 'platform.dart';
class VideoScreen extends StatefulWidget { class VideoScreen extends StatefulWidget {
@ -22,11 +21,13 @@ class VideoScreen extends StatefulWidget {
} }
class _VideoScreenState extends State<VideoScreen> { class _VideoScreenState extends State<VideoScreen> {
Player? _player = isDesktop() ? Player(id: Random().nextInt(0x7fffffff)) : null; Player? _player =
isDesktop() ? Player(id: Random().nextInt(0x7fffffff)) : null;
ChewieController? _chewieController; ChewieController? _chewieController;
void loadData() async { void loadData() async {
final data = await API.query("video", "loadVideo", {'MovieId': widget.metaData.id}); final data =
await API.query("video", "loadVideo", {'MovieId': widget.metaData.id});
final d = jsonDecode(data); final d = jsonDecode(data);
@ -46,7 +47,8 @@ class _VideoScreenState extends State<VideoScreen> {
autoStart: true, // default autoStart: true, // default
); );
} else { } else {
final VideoPlayerController _controller = VideoPlayerController.network(path); final VideoPlayerController _controller =
VideoPlayerController.network(path);
await _controller.initialize(); await _controller.initialize();
_chewieController = ChewieController( _chewieController = ChewieController(
@ -56,8 +58,7 @@ class _VideoScreenState extends State<VideoScreen> {
allowFullScreen: true, allowFullScreen: true,
allowMuting: true, allowMuting: true,
allowPlaybackSpeedChanging: true, allowPlaybackSpeedChanging: true,
zoomAndPan: true zoomAndPan: true);
);
setState(() {}); setState(() {});
} }
@ -70,14 +71,15 @@ class _VideoScreenState extends State<VideoScreen> {
if (isDesktop()) { if (isDesktop()) {
RawKeyboard.instance.addListener((value) { RawKeyboard.instance.addListener((value) {
if (value.logicalKey == LogicalKeyboardKey.arrowRight) { if (value.logicalKey == LogicalKeyboardKey.arrowRight) {
_player?.seek(_player!.position.position! + const Duration(seconds: 5)); _player
?.seek(_player!.position.position! + const Duration(seconds: 5));
} else if (value.logicalKey == LogicalKeyboardKey.arrowLeft) { } else if (value.logicalKey == LogicalKeyboardKey.arrowLeft) {
_player?.seek(_player!.position.position! + const Duration(seconds: -5)); _player
?.seek(_player!.position.position! + const Duration(seconds: -5));
} }
}); });
} }
loadData(); loadData();
// todo hide appbar after some seonds // todo hide appbar after some seonds
@ -108,8 +110,7 @@ class _VideoScreenState extends State<VideoScreen> {
return Video( return Video(
player: _player, player: _player,
scale: 1.0, // default scale: 1.0, // default
showControls: true showControls: true);
);
} }
Widget videoNotDesktop() { Widget videoNotDesktop() {

View File

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'api/api.dart'; import 'api/api.dart';
import 'api/token.dart'; import 'api/token.dart';
import 'log/log.dart';
class VideoScreen extends StatefulWidget { class VideoScreen extends StatefulWidget {
const VideoScreen({Key? key, required this.videoID}) : super(key: key); const VideoScreen({Key? key, required this.videoID}) : super(key: key);
@ -15,7 +16,8 @@ class VideoScreen extends StatefulWidget {
class _VideoScreenState extends State<VideoScreen> { class _VideoScreenState extends State<VideoScreen> {
void loadData() async { void loadData() async {
final data = await API.query("video", "loadVideo", {'MovieId': widget.videoID}); final data =
await API.query("video", "loadVideo", {'MovieId': widget.videoID});
final d = jsonDecode(data); final d = jsonDecode(data);
@ -25,8 +27,8 @@ class _VideoScreenState extends State<VideoScreen> {
final baseurl = token.domain; final baseurl = token.domain;
// todo not static middle path // todo not static middle path
final path = baseurl + "/videos/vids/" + url; final String path = baseurl + "/videos/vids/" + url;
Log.d(path);
} }
@override @override
@ -44,9 +46,7 @@ class _VideoScreenState extends State<VideoScreen> {
appBar: AppBar( appBar: AppBar(
title: const Text('Second Route'), title: const Text('Second Route'),
), ),
body: const Center( body: const Center(child: Text("Todo to implement")),
child: Text("Todo to implement")
),
); );
} }
} }

View File

@ -173,7 +173,7 @@ packages:
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.1.2"
flutter_secure_storage_linux: flutter_secure_storage_linux:
dependency: transitive dependency: transitive
description: description:

View File

@ -34,7 +34,7 @@ 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

View File

@ -11,7 +11,5 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:openmediacentermobile/main.dart'; import 'package:openmediacentermobile/main.dart';
void main() { void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async { testWidgets('Counter increments smoke test', (WidgetTester tester) async {});
});
} }