import 'dart:developer'; import 'dart:io'; import 'package:flutter/material.dart'; // Removed unnecessary import import 'package:hub/flutter_flow/index.dart'; import 'package:hub/shared/utils/dialog_util.dart'; import 'package:hub/shared/widgets.dart'; import 'package:path_provider/path_provider.dart'; import 'package:pdfx/pdfx.dart'; import 'package:share_plus/share_plus.dart'; import 'package:http/http.dart' as http; typedef ReadViewController = PdfController; typedef DocumentType = PdfDocument; abstract interface class Viewer extends StatelessComponent { final String src; const Viewer({ super.key, required this.src, }); @override Widget build(BuildContext context) { return buildViewer(context); } Widget buildViewer(BuildContext context); } class ReadView extends StatefulWidget { final String url; final String title; final VoidCallback onError; const ReadView({ super.key, required this.onError, required this.url, required this.title, }); @override State createState() => ReadViewState(); } class ReadViewState extends State { Future _initializePdf() async { try { final file = await downloadPdf(widget.url); final Future document = DocumentType.openFile(file.path); return ReadViewController(document: document); } catch (e) { final message = FFLocalizations.of(context).getVariableText( ptText: 'Erro ao baixar o PDF', enText: 'Error downloading PDF', ); return Future.error(message); } } Future downloadPdf(String url) async { try { final response = await http.get(Uri.parse(url)); if (response.statusCode == 200) { final bytes = response.bodyBytes; final dir = await getTemporaryDirectory(); final file = File('${dir.path}/downloaded.pdf'); await file.writeAsBytes(bytes); return file; } else { throw Exception('Falha ao baixar o PDF'); } } catch (e) { final message = FFLocalizations.of(context).getVariableText( ptText: 'Erro ao baixar o PDF', enText: 'Error downloading PDF', ); await throwError(message, e); rethrow; } } Future throwError(String message, dynamic error) async { log('$message: $error'); await DialogUtil.error(context, message) .whenComplete(() => widget.onError()); } @override Widget build(BuildContext context) { return Stack( children: [ _buildPDFViewer(context), buildShareButton(context), ], ); } Positioned buildShareButton(BuildContext context) { final theme = FlutterFlowTheme.of(context); return Positioned( bottom: 10, right: 10, child: IconButton( icon: Icon( Icons.share, color: theme.primaryText, ), color: theme.primaryText, onPressed: onShare, ), ); } Future onShare() async { try { final Uri uri = Uri.parse(widget.url); final response = await http.get(uri); if (response.statusCode == 200) { final XFile xfile = XFile.fromData(response.bodyBytes, name: '${widget.title}.pdf', mimeType: 'application/pdf'); await Share.shareXFiles([xfile], text: 'Confira este PDF!'); } else { throw Exception( 'Erro ao compartilhar o arquivo: ${response.statusCode}'); } } catch (e) { final message = FFLocalizations.of(context).getVariableText( ptText: 'Erro ao compartilhar o arquivo', enText: 'Error sharing file', ); await throwError(message, e); } } Widget buildLoadingIndicator(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(vertical: 15), child: Center( child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation( FlutterFlowTheme.of(context).primary, ), ), ), ); } Widget _buildPDFViewer(BuildContext context) => Padding( padding: EdgeInsets.all(10), child: FutureBuilder( future: _initializePdf(), builder: (context, snapshot) { if (!snapshot.hasData) return buildLoadingIndicator(context); if (snapshot.error != null) { return buildLoadingIndicator(context); } if (snapshot.connectionState == ConnectionState.waiting) { return buildLoadingIndicator(context); } return PdfView( controller: snapshot.data!, renderer: (PdfPage page) => page.render( width: page.width * 2, height: page.height * 2, cropRect: Rect.fromLTWH( 10.0, 10.0, page.width * 2, page.height * 2), forPrint: false, quality: 100, format: PdfPageImageFormat.jpeg, backgroundColor: '#ffffff', ), scrollDirection: Axis.vertical, ); }), ); }