feat-insert-service (#5)
Reviewed-on: http://catelliub.zapto.org:3000/brontomark/flux/pulls/5 Co-authored-by: mark-cachy <marco@catelli.it> Co-committed-by: mark-cachy <marco@catelli.it>
This commit is contained in:
61
lib/core/widgets/image_viewer_widget.dart
Normal file
61
lib/core/widgets/image_viewer_widget.dart
Normal file
@@ -0,0 +1,61 @@
|
||||
import 'dart:typed_data';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart'; // <--- AGGIUNGI QUESTO
|
||||
|
||||
class ImageViewerWidget extends StatelessWidget {
|
||||
final String? storagePath; // ATTENZIONE: Ora contiene lo storagePath!
|
||||
final Uint8List? bytes;
|
||||
|
||||
const ImageViewerWidget({super.key, this.storagePath, this.bytes})
|
||||
: assert(
|
||||
(storagePath != null && storagePath != '') || bytes != null,
|
||||
'Errore: Devi fornire un Path valido o i bytes del file!',
|
||||
);
|
||||
|
||||
// Funzione che chiede le chiavi a Supabase
|
||||
Future<String> _getSignedUrl() async {
|
||||
return await Supabase.instance.client.storage
|
||||
.from('documents')
|
||||
.createSignedUrl(storagePath!, 60); // Link che si autodistrugge in 60s
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.close, color: Colors.black),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
),
|
||||
body: InteractiveViewer(
|
||||
maxScale: 5.0,
|
||||
child: Center(
|
||||
// Se abbiamo i byte, mostriamo subito. Altrimenti usiamo il FutureBuilder!
|
||||
child: bytes != null
|
||||
? Image.memory(bytes!)
|
||||
: FutureBuilder<String>(
|
||||
future: _getSignedUrl(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return const CircularProgressIndicator();
|
||||
}
|
||||
if (snapshot.hasError) {
|
||||
return const Text(
|
||||
"Errore caricamento immagine (Permessi negati?)",
|
||||
style: TextStyle(color: Colors.red),
|
||||
);
|
||||
}
|
||||
if (snapshot.hasData) {
|
||||
return Image.network(snapshot.data!);
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
97
lib/core/widgets/pdf_viewer_widget.dart
Normal file
97
lib/core/widgets/pdf_viewer_widget.dart
Normal file
@@ -0,0 +1,97 @@
|
||||
import 'dart:typed_data';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:pdfx/pdfx.dart';
|
||||
import 'package:internet_file/internet_file.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
|
||||
class PdfViewerWidget extends StatefulWidget {
|
||||
final String? storagePath;
|
||||
final Uint8List? bytes;
|
||||
|
||||
const PdfViewerWidget({super.key, this.storagePath, this.bytes})
|
||||
: assert(
|
||||
(storagePath != null && storagePath != '') || bytes != null,
|
||||
'Errore: Devi fornire un URL valido o i bytes del file!',
|
||||
);
|
||||
|
||||
@override
|
||||
State<PdfViewerWidget> createState() => _PdfViewerWidgetState();
|
||||
}
|
||||
|
||||
class _PdfViewerWidgetState extends State<PdfViewerWidget> {
|
||||
late PdfControllerPinch _pdfController;
|
||||
bool _isLoading = true;
|
||||
String? _errorMessage;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_initPdf();
|
||||
}
|
||||
|
||||
Future<void> _initPdf() async {
|
||||
try {
|
||||
Uint8List pdfData;
|
||||
|
||||
if (widget.bytes != null) {
|
||||
// SCENARIO 1: Pratica in bozza, file appena scelto (Locale)
|
||||
pdfData = widget.bytes!;
|
||||
} else if (widget.storagePath != null && widget.storagePath!.isNotEmpty) {
|
||||
// SCENARIO 2: Pratica salvata, scarichiamo da Supabase (Remoto)
|
||||
final signedUrl = await GetIt.I
|
||||
.get<SupabaseClient>()
|
||||
.storage
|
||||
.from('documents')
|
||||
.createSignedUrl(widget.storagePath!, 60);
|
||||
pdfData = await InternetFile.get(signedUrl);
|
||||
} else {
|
||||
throw Exception("Nessun documento trovato");
|
||||
}
|
||||
|
||||
_pdfController = PdfControllerPinch(
|
||||
document: PdfDocument.openData(pdfData),
|
||||
);
|
||||
|
||||
if (mounted) setState(() => _isLoading = false);
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_errorMessage = e.toString();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_pdfController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_isLoading) {
|
||||
return const Scaffold(body: Center(child: CircularProgressIndicator()));
|
||||
}
|
||||
|
||||
if (_errorMessage != null) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(leading: const CloseButton()),
|
||||
body: Center(child: Text("Errore: $_errorMessage")),
|
||||
);
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("Anteprima PDF"),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
),
|
||||
body: PdfViewPinch(controller: _pdfController),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user