import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:openmediacentermobile/videoscreen_desktop.dart' if (dart.library.html) 'package:openmediacentermobile/videoscreen_web.dart' if (dart.library.io) 'package:openmediacentermobile/videoscreen_desktop.dart'; import 'api/api.dart'; import 'platform.dart'; // todo put this type in sperate class! class VideoT { int id; String title; double ratio; 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()); } } class PreviewTile extends StatefulWidget { 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(); } class _PreviewTileState extends State { late Future _preview; @override void initState() { super.initState(); _preview = loadData(); } @override void didUpdateWidget(PreviewTile oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.dta != widget.dta) { setState(() { _preview = loadData(); }); } } Future 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 FutureBuilder( future: _preview, // a previously-obtained Future or null builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.hasError) { return Text("Error"); } else if (snapshot.hasData) { return ClipRRect( borderRadius: BorderRadius.circular(20.0), child: Stack( children: [ Container( child: Column( children: [ Text( widget.dta.title, style: TextStyle(fontSize: isTV() ? 8 : 10.5), overflow: TextOverflow.clip, maxLines: 1, ), snapshot.data! ], ), color: Color(0x6a94a6ff), ), Positioned.fill( child: Material( color: Colors.transparent, 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), ), ); }, ), ), ), ), ], ), ); } else { return Column(children: const [ SizedBox(height: 100), SizedBox( width: 60, height: 60, child: CircularProgressIndicator(), ), Padding( padding: EdgeInsets.only(top: 16), child: Text('Awaiting result...'), ), SizedBox(height: 100), ]); } }, ); } }