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:
paths:
- 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"
android {
compileSdkVersion 33
compileSdkVersion flutter.compileSdkVersion
compileOptions {
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).
applicationId "eu.heili.openmediacentermobile"
minSdkVersion 21
targetSdkVersion 30
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}

View File

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

View File

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

View File

@ -19,8 +19,8 @@ class App extends StatelessWidget {
} else {
return const MaterialApp(
home: DrawerPage(
title: 'OpenMediaCenter',
));
title: 'OpenMediaCenter',
));
}
}
}

View File

@ -18,7 +18,6 @@ class _LoginScreenState extends State<LoginScreen> {
final TextEditingController _domainTextController = TextEditingController();
final TextEditingController _passwordTextController = TextEditingController();
String error = "";
bool _loginActive = false;
Future<String> login(String password, String domain) async {
Log.i("logging in...");
@ -64,7 +63,8 @@ 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,
@ -79,7 +79,8 @@ 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: [
@ -123,7 +124,8 @@ 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,
@ -132,18 +134,23 @@ class _LoginScreenState extends State<LoginScreen> {
color: Colors.white,
onPressed: () async {
Log.d("clickkked");
final pwd = _passwordTextController.value.text;
final domain = _domainTextController.value.text;
final pwd =
_passwordTextController.value.text;
final domain =
_domainTextController.value.text;
var err = "";
if (domain.startsWith("https://") || domain.startsWith("http://")) {
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);
err = await login(
pwd, "https://" + domain);
if (err.isEmpty) return;
err = await login(pwd, "http://" + domain);
err = await login(
pwd, "http://" + domain);
if (err.isEmpty) return;
}

View File

@ -1,4 +1,4 @@
import "package:dart_vlc/dart_vlc.dart";
import "package:dart_vlc/dart_vlc.dart";
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:openmediacentermobile/app.dart';
@ -11,7 +11,6 @@ void main() async {
Log.i("App init!");
DartVLC.initialize();
if (isDesktop()) {
} else {
await loadDeviceInfo();
}

View File

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

View File

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

View File

@ -17,12 +17,15 @@ 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());
}
}
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 Function(Image img)? onLongPress;
final Function? onLongPressEnd;
@ -53,7 +56,8 @@ class _PreviewTileState extends State<PreviewTile> {
}
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(
base64Decode(data.substring(23)),
@ -99,17 +103,20 @@ class _PreviewTileState extends State<PreviewTile> {
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onLongPress: () {
if (widget.onLongPress != null) widget.onLongPress!(snapshot.data!);
if (widget.onLongPress != null)
widget.onLongPress!(snapshot.data!);
},
onLongPressEnd: (details) {
if (widget.onLongPressEnd != null) widget.onLongPressEnd!();
if (widget.onLongPressEnd != null)
widget.onLongPressEnd!();
},
child: InkWell(
onTap: () {
Navigator.push(
context,
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> {
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);
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;
}

View File

@ -17,13 +17,13 @@ class VideoFeed extends StatefulWidget {
}
class VideoFeedState extends State<VideoFeed> {
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();
List<VideoT> dta =
(d['Videos'] as List).map((e) => VideoT.fromJson(e)).toList();
return dta;
}
@ -33,6 +33,8 @@ class VideoFeedState extends State<VideoFeed> {
double width = MediaQuery.of(context).size.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/token.dart';
import 'log/log.dart';
import 'platform.dart';
class VideoScreen extends StatefulWidget {
@ -22,11 +21,13 @@ class VideoScreen extends StatefulWidget {
}
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;
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);
@ -46,18 +47,18 @@ class _VideoScreenState extends State<VideoScreen> {
autoStart: true, // default
);
} else {
final VideoPlayerController _controller = VideoPlayerController.network(path);
final VideoPlayerController _controller =
VideoPlayerController.network(path);
await _controller.initialize();
_chewieController = ChewieController(
videoPlayerController: _controller,
autoPlay: true,
looping: true,
allowFullScreen: true,
allowMuting: true,
allowPlaybackSpeedChanging: true,
zoomAndPan: true
);
videoPlayerController: _controller,
autoPlay: true,
looping: true,
allowFullScreen: true,
allowMuting: true,
allowPlaybackSpeedChanging: true,
zoomAndPan: true);
setState(() {});
}
@ -67,17 +68,18 @@ class _VideoScreenState extends State<VideoScreen> {
void initState() {
super.initState();
if(isDesktop()){
if (isDesktop()) {
RawKeyboard.instance.addListener((value) {
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) {
_player?.seek(_player!.position.position! + const Duration(seconds: -5));
_player
?.seek(_player!.position.position! + const Duration(seconds: -5));
}
});
}
loadData();
// todo hide appbar after some seonds
@ -106,10 +108,9 @@ class _VideoScreenState extends State<VideoScreen> {
Widget videoDesktop() {
return Video(
player: _player,
scale: 1.0, // default
showControls: true
);
player: _player,
scale: 1.0, // default
showControls: true);
}
Widget videoNotDesktop() {

View File

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

View File

@ -173,7 +173,7 @@ packages:
name: flutter_secure_storage
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.0"
version: "5.1.2"
flutter_secure_storage_linux:
dependency: transitive
description:

View File

@ -34,7 +34,7 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
flutter_secure_storage: ^6.0.0
flutter_secure_storage: ^5.0.2
logger: ^1.1.0
http: ^0.13.4
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';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
});
testWidgets('Counter increments smoke test', (WidgetTester tester) async {});
}