import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; import '../api/video_api.dart'; import '../db/database.dart'; import '../log/log.dart'; import '../types/video.dart'; import '../utils/platform.dart'; import '../video_screen/videoscreen.dart'; 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 insert(int id, Uint8List pic) async { await Db().db().insert( 'previews', {'id': id, 'thumbnail': pic}, conflictAlgorithm: ConflictAlgorithm.replace, ); } Future loadData() async { Uint8List data; final id = widget.dta.id; if (kIsWeb) { data = await fetchThumbnail(id); } else { final List> prev = await Db().db().query('previews', where: "id=$id"); if (prev.isEmpty) { data = await fetchThumbnail(id); insert(id, data); Log.d("Adding $id to db"); } else { data = prev.first["thumbnail"] as Uint8List; Log.d("using cached preview for $id"); } } final img = Image.memory( data, width: double.infinity, fit: BoxFit.fitWidth, ); // precache image to avoid loading time to render image if(context.mounted) await precacheImage(img.image, context); return img; } Widget _buildLoader() { return Column(children: const [ SizedBox(height: 50), SizedBox( width: 60, height: 60, child: CircularProgressIndicator(), ), Padding( padding: EdgeInsets.only(top: 16), child: Text('Awaiting result...'), ), SizedBox(height: 50), ]); } Widget _buildTile(Image image) { return ClipRRect( borderRadius: BorderRadius.circular(20.0), child: Stack( children: [ Container( color: const Color(0xff3f3f3f), child: Column( children: [ ClipRRect( borderRadius: BorderRadius.circular(20.0), child: image, ), const SizedBox( height: 3, ), Text( widget.dta.title, style: TextStyle( fontSize: isTV() ? 8 : 10.5, color: const Color(0xffe9e9e9)), overflow: TextOverflow.clip, maxLines: 1, ), const SizedBox( height: 3, ), ], ), ), Positioned.fill( child: Material( color: Colors.transparent, child: GestureDetector( behavior: HitTestBehavior.translucent, onLongPress: () { if (widget.onLongPress != null) widget.onLongPress!(image); }, onLongPressEnd: (details) { if (widget.onLongPressEnd != null) widget.onLongPressEnd!(); }, child: InkWell( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => VideoScreen(metaData: widget.dta), ), ); }, ), ), ), ), ], ), ); } @override Widget build(BuildContext context) { return ConstrainedBox( constraints: const BoxConstraints(minHeight: 200, minWidth: 200), child: FutureBuilder( future: _preview, // a previously-obtained Future or null builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.connectionState != ConnectionState.done) { return _buildLoader(); } if (snapshot.hasError) { return Text("Error"); } else if (snapshot.hasData) { return _buildTile(snapshot.data!); } else { return _buildLoader(); } }, ), ); } }