add a preview if longpressing preview

This commit is contained in:
lukas-heiligenbrunner 2022-08-21 22:44:12 +02:00
parent 51b4d4b38d
commit 74e2afee98
10 changed files with 161 additions and 85 deletions

View File

@ -4,6 +4,7 @@
<application
android:label="openmediacentermobile"
android:name="${applicationName}"
android:usesCleartextTraffic="true"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"

View File

@ -3,12 +3,10 @@ import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:openmediacentermobile/api/token.dart';
import 'package:openmediacentermobile/log/log.dart';
class API {
static Future<String> query(
String apinode, String action, Object payload) async {
final Completer<String> cmpl = Completer();
final t = await Token.getInstance().getToken();
if (t != null) {
final resp = await http.post(
@ -20,11 +18,9 @@ class API {
body: jsonEncode(payload),
);
cmpl.complete(resp.body);
return resp.body;
} else {
cmpl.complete("");
return "";
}
return cmpl.future;
}
}

View File

@ -21,7 +21,7 @@ class _LoginScreenState extends State<LoginScreen> {
Future<String> login(String password, String domain) async {
Log.i("logging in...");
final compl = Completer<String>();
// final compl = Completer<String>();
final resp = await http.post(
Uri.parse(domain + '/api/login/login'),
headers: <String, String>{
@ -33,7 +33,9 @@ class _LoginScreenState extends State<LoginScreen> {
);
if (resp.statusCode != 200) {
compl.complete(resp.body);
return resp.body;
// compl.complete(resp.body);
} else {
final json = jsonDecode(resp.body);
final token = json["Token"];
@ -41,12 +43,14 @@ class _LoginScreenState extends State<LoginScreen> {
Token.getInstance().setToken(token, domain);
LoginContext.of(context).onLoggin(true);
compl.complete("");
return "";
// compl.complete("");
}
// LoginContext.of(context).onLoggin(true);
return compl.future;
// return compl.future;
}
@override

99
lib/preview_grid.dart Normal file
View File

@ -0,0 +1,99 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:openmediacentermobile/platform.dart';
import 'package:openmediacentermobile/preview_tile.dart';
class PreviewGrid extends StatefulWidget {
const PreviewGrid({Key? key, required this.videoLoader}) : super(key: key);
final Future<List<VideoT>> Function() videoLoader;
@override
State<PreviewGrid> createState() => _PreviewGridState();
}
class _PreviewGridState extends State<PreviewGrid> {
late Future<List<VideoT>> _data;
Image? _previewImage;
@override
void initState() {
super.initState();
_data = widget.videoLoader();
}
@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.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 Stack(
children: [
MasonryGridView.count(
// every tile should be at max 330 pixels long...
crossAxisCount: isTV() ? width ~/ 200 : width ~/ 275,
// crossAxisCount: isTV() ? width ~/ 200 : width ~/ 330,
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 (_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!)),
),
),
],
],
);
} 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

@ -1,6 +1,5 @@
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:openmediacentermobile/videoscreen_desktop.dart'
if (dart.library.html) 'package:openmediacentermobile/videoscreen_web.dart'
@ -23,8 +22,10 @@ class VideoT {
}
class PreviewTile extends StatefulWidget {
const PreviewTile({Key? key, required this.dta}) : 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;
@override
_PreviewTileState createState() => _PreviewTileState();
@ -80,22 +81,39 @@ class _PreviewTileState extends State<PreviewTile> {
children: [
Container(
child: Column(
children: [Text(widget.dta.title, style: TextStyle(fontSize: isTV() ? 8 : 12)), snapshot.data!],
children: [
Text(
widget.dta.title,
style: TextStyle(fontSize: isTV() ? 8 : 10.5),
overflow: TextOverflow.clip,
maxLines: 1,
),
snapshot.data!
],
),
color: Colors.green,
color: Color(0xFF6CE56F),
),
Positioned.fill(
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => VideoScreen(MetaData: widget.dta),
),
);
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onLongPress: () {
if (widget.onLongPress != null) widget.onLongPress!(snapshot.data!);
},
onLongPressEnd: (details) {
if (widget.onLongPressEnd != null) widget.onLongPressEnd!();
},
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => VideoScreen(MetaData: widget.dta),
),
);
},
),
),
),
),

View File

@ -51,18 +51,23 @@ class _ShuffleScreenState extends State<ShuffleScreen> {
crossAxisCount: isTV() ? width ~/ 200 : width ~/ 330,
mainAxisSpacing: 4,
crossAxisSpacing: 4,
padding: EdgeInsets.all(5),
itemCount: 4,
itemBuilder: (context, index) {
return PreviewTile(dta: snapshot.data![index]);
},
),
const SizedBox(height: 25,),
TextButton.icon(onPressed: () {
setState(() {
_data = loadData();
});
}, icon: const Icon(Icons.update), label: const Text("Shuffle"))
const SizedBox(
height: 25,
),
TextButton.icon(
onPressed: () {
setState(() {
_data = loadData();
});
},
icon: const Icon(Icons.update),
label: const Text("Shuffle"))
]);
} else {
return Column(children: const <Widget>[

View File

@ -2,11 +2,10 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:openmediacentermobile/api/api.dart';
import 'package:openmediacentermobile/preview_grid.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);
@ -18,7 +17,6 @@ class VideoFeed extends StatefulWidget {
}
class VideoFeedState extends State<VideoFeed> {
late Future<List<VideoT>> _data;
Future<List<VideoT>> loadData() async {
final data = await API.query("video", "getMovies", {'Tag': 1, 'Sort': 0});
@ -30,47 +28,11 @@ class VideoFeedState extends State<VideoFeed> {
return dta;
}
@override
void initState() {
super.initState();
_data = loadData();
}
@override
Widget build(BuildContext context) {
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) {
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...'),
)
]);
}
},
);
return PreviewGrid(videoLoader: () => loadData(),);
}
}

View File

@ -53,6 +53,10 @@ class _VideoScreenState extends State<VideoScreen> {
videoPlayerController: _controller,
autoPlay: true,
looping: true,
allowFullScreen: true,
allowMuting: true,
allowPlaybackSpeedChanging: true,
zoomAndPan: true
);
setState(() {});

View File

@ -56,7 +56,7 @@ packages:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0"
version: "1.16.0"
csslib:
dependency: transitive
description:
@ -133,7 +133,7 @@ packages:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.3.0"
ffi:
dependency: transitive
description:
@ -526,5 +526,5 @@ packages:
source: hosted
version: "0.2.0+1"
sdks:
dart: ">=2.16.0-100.0.dev <3.0.0"
dart: ">=2.17.0-0 <3.0.0"
flutter: ">=2.8.0"

View File

@ -12,19 +12,6 @@ import 'package:openmediacentermobile/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const MyApp());
// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}