pdf_signature/lib/ui/features/signature/widgets/signature_drawer.dart

182 lines
7.1 KiB
Dart

import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:pdf_signature/l10n/app_localizations.dart';
// Direct model construction is needed for creating SignatureAssets
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
import 'package:pdf_signature/data/repositories/signature_card_repository.dart';
import 'package:pdf_signature/domain/models/model.dart' hide SignatureCard;
import 'image_editor_dialog.dart';
import 'signature_card.dart';
/// Data for drag-and-drop is in signature_drag_data.dart
class SignatureDrawer extends ConsumerStatefulWidget {
const SignatureDrawer({
super.key,
required this.disabled,
required this.onLoadSignatureFromFile,
required this.onOpenDrawCanvas,
});
final bool disabled;
// Return the loaded bytes (if any) so we can add the exact image to the library immediately.
final Future<Uint8List?> Function() onLoadSignatureFromFile;
// Return the drawn bytes (if any) so we can add it to the library immediately.
final Future<Uint8List?> Function() onOpenDrawCanvas;
@override
ConsumerState<SignatureDrawer> createState() => _SignatureDrawerState();
}
class _SignatureDrawerState extends ConsumerState<SignatureDrawer> {
@override
Widget build(BuildContext context) {
final l = AppLocalizations.of(context);
final library = ref.watch(signatureCardRepositoryProvider);
// Exporting flag lives in ui_services; keep drawer interactive regardless here.
final isExporting = false;
final disabled = widget.disabled || isExporting;
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (library.isNotEmpty) ...[
for (final card in library) ...[
Card(
margin: EdgeInsets.zero,
child: Padding(
padding: const EdgeInsets.all(12),
child: SignatureCard(
key: ValueKey('sig_card_${library.indexOf(card)}'),
asset: card.asset,
rotationDeg: card.rotationDeg,
graphicAdjust: card.graphicAdjust,
disabled: disabled,
onDelete:
() => ref
.read(signatureCardRepositoryProvider.notifier)
.remove(card),
onAdjust: () async {
if (!mounted) return;
final result = await showDialog<ImageEditorResult>(
context: context,
builder:
(_) => ImageEditorDialog(
asset: card.asset,
initialRotation: card.rotationDeg,
initialGraphicAdjust: card.graphicAdjust,
),
);
if (result != null && mounted) {
ref
.read(signatureCardRepositoryProvider.notifier)
.update(card, result.rotation, result.graphicAdjust);
}
},
onTap: () {
// state = const Rect.fromLTWH(0.2, 0.2, 0.3, 0.15);
},
),
),
),
const SizedBox(height: 12),
],
],
if (library.isEmpty)
Card(
margin: EdgeInsets.zero,
child: Padding(
padding: const EdgeInsets.all(12),
child: Text(l.noSignatureLoaded),
),
),
Card(
margin: EdgeInsets.zero,
child: Padding(
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
l.createNewSignature,
style: Theme.of(context).textTheme.titleSmall,
),
const SizedBox(height: 8),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
OutlinedButton.icon(
key: const Key('btn_drawer_load_signature'),
onPressed:
disabled
? null
: () async {
final loaded =
await widget.onLoadSignatureFromFile();
final b = loaded;
if (b != null) {
final asset = SignatureAsset(
bytes: b,
name: 'image',
);
ref
.read(
signatureAssetRepositoryProvider
.notifier,
)
.add(b, name: 'image');
ref
.read(
signatureCardRepositoryProvider
.notifier,
)
.addWithAsset(asset, 0.0);
}
},
icon: const Icon(Icons.image_outlined),
label: Text(l.loadSignatureFromFile),
),
OutlinedButton.icon(
key: const Key('btn_drawer_draw_signature'),
onPressed:
disabled
? null
: () async {
final drawn = await widget.onOpenDrawCanvas();
final b = drawn;
if (b != null) {
final asset = SignatureAsset(
bytes: b,
name: 'drawing',
);
ref
.read(
signatureAssetRepositoryProvider
.notifier,
)
.add(b, name: 'drawing');
ref
.read(
signatureCardRepositoryProvider
.notifier,
)
.addWithAsset(asset, 0.0);
}
},
icon: const Icon(Icons.gesture),
label: Text(l.drawSignature),
),
],
),
],
),
),
),
],
);
}
}