fix: graphic adjust dialog has to show image preview
This commit is contained in:
parent
461c8f6ae5
commit
8f3039f99e
|
|
@ -63,6 +63,7 @@ class MyApp extends StatelessWidget {
|
||||||
],
|
],
|
||||||
routerConfig: ref.watch(routerProvider),
|
routerConfig: ref.watch(routerProvider),
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
|
final router = ref.watch(routerProvider);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(AppLocalizations.of(context).appTitle),
|
title: Text(AppLocalizations.of(context).appTitle),
|
||||||
|
|
@ -73,7 +74,11 @@ class MyApp extends StatelessWidget {
|
||||||
label: Text(AppLocalizations.of(context).settings),
|
label: Text(AppLocalizations.of(context).settings),
|
||||||
onPressed:
|
onPressed:
|
||||||
() => showDialog<bool>(
|
() => showDialog<bool>(
|
||||||
context: context,
|
context:
|
||||||
|
router
|
||||||
|
.routerDelegate
|
||||||
|
.navigatorKey
|
||||||
|
.currentContext!,
|
||||||
builder: (_) => const SettingsDialog(),
|
builder: (_) => const SettingsDialog(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:pdf_signature/ui/features/pdf/widgets/pdf_screen.dart';
|
import 'package:pdf_signature/ui/features/pdf/widgets/pdf_screen.dart';
|
||||||
|
|
@ -79,6 +80,9 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||||
signatureCardRepositoryProvider.notifier,
|
signatureCardRepositoryProvider.notifier,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Create a navigator key for the router
|
||||||
|
final navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
|
||||||
// Create a late variable for the router
|
// Create a late variable for the router
|
||||||
late final GoRouter router;
|
late final GoRouter router;
|
||||||
|
|
||||||
|
|
@ -90,6 +94,7 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||||
final initialLocation = documentNotifier.debugState.loaded ? '/pdf' : '/';
|
final initialLocation = documentNotifier.debugState.loaded ? '/pdf' : '/';
|
||||||
|
|
||||||
router = GoRouter(
|
router = GoRouter(
|
||||||
|
navigatorKey: navigatorKey,
|
||||||
routes: [
|
routes: [
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/',
|
path: '/',
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,6 @@ class AdjustmentsPanel extends StatelessWidget {
|
||||||
runSpacing: 8,
|
runSpacing: 8,
|
||||||
crossAxisAlignment: WrapCrossAlignment.center,
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Checkbox(
|
|
||||||
key: const Key('chk_aspect_lock'),
|
|
||||||
value: aspectLocked,
|
|
||||||
onChanged: (v) => onAspectLockedChanged(v ?? false),
|
|
||||||
),
|
|
||||||
Text(AppLocalizations.of(context).lockAspectRatio),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Switch(
|
Switch(
|
||||||
key: const Key('swt_bg_removal'),
|
key: const Key('swt_bg_removal'),
|
||||||
value: bgRemoval,
|
value: bgRemoval,
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,51 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:pdf_signature/l10n/app_localizations.dart';
|
import 'package:pdf_signature/l10n/app_localizations.dart';
|
||||||
import 'adjustments_panel.dart';
|
import '../../pdf/widgets/adjustments_panel.dart';
|
||||||
// No live preview wiring in simplified dialog
|
import '../../../../domain/models/model.dart' as domain;
|
||||||
|
import 'rotated_signature_image.dart';
|
||||||
|
|
||||||
|
class ImageEditorResult {
|
||||||
|
final double rotation;
|
||||||
|
final domain.GraphicAdjust graphicAdjust;
|
||||||
|
|
||||||
|
const ImageEditorResult({
|
||||||
|
required this.rotation,
|
||||||
|
required this.graphicAdjust,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
class ImageEditorDialog extends StatefulWidget {
|
class ImageEditorDialog extends StatefulWidget {
|
||||||
const ImageEditorDialog({super.key});
|
const ImageEditorDialog({
|
||||||
|
super.key,
|
||||||
|
required this.asset,
|
||||||
|
required this.initialRotation,
|
||||||
|
required this.initialGraphicAdjust,
|
||||||
|
});
|
||||||
|
|
||||||
|
final domain.SignatureAsset asset;
|
||||||
|
final double initialRotation;
|
||||||
|
final domain.GraphicAdjust initialGraphicAdjust;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ImageEditorDialog> createState() => _ImageEditorDialogState();
|
State<ImageEditorDialog> createState() => _ImageEditorDialogState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ImageEditorDialogState extends State<ImageEditorDialog> {
|
class _ImageEditorDialogState extends State<ImageEditorDialog> {
|
||||||
// Local-only state for demo/tests; no persistence to repositories.
|
late bool _aspectLocked;
|
||||||
bool _aspectLocked = false;
|
late bool _bgRemoval;
|
||||||
bool _bgRemoval = false;
|
late double _contrast;
|
||||||
double _contrast = 1.0; // 0..2
|
late double _brightness;
|
||||||
double _brightness = 0.0; // -1..1
|
late double _rotation;
|
||||||
double _rotation = 0.0; // -180..180
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_aspectLocked = false; // Not persisted in GraphicAdjust
|
||||||
|
_bgRemoval = widget.initialGraphicAdjust.bgRemoval;
|
||||||
|
_contrast = widget.initialGraphicAdjust.contrast;
|
||||||
|
_brightness = widget.initialGraphicAdjust.brightness;
|
||||||
|
_rotation = widget.initialRotation;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
@ -37,7 +66,7 @@ class _ImageEditorDialogState extends State<ImageEditorDialog> {
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
// Preview placeholder; no actual processed bytes wired
|
// Preview with actual signature image
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 160,
|
height: 160,
|
||||||
child: DecoratedBox(
|
child: DecoratedBox(
|
||||||
|
|
@ -45,7 +74,13 @@ class _ImageEditorDialogState extends State<ImageEditorDialog> {
|
||||||
border: Border.all(color: Theme.of(context).dividerColor),
|
border: Border.all(color: Theme.of(context).dividerColor),
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child: const Center(child: Text('No signature loaded')),
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
child: RotatedSignatureImage(
|
||||||
|
bytes: widget.asset.bytes,
|
||||||
|
rotationDeg: _rotation,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
|
|
@ -84,7 +119,17 @@ class _ImageEditorDialogState extends State<ImageEditorDialog> {
|
||||||
children: [
|
children: [
|
||||||
TextButton(
|
TextButton(
|
||||||
key: const Key('btn_image_editor_close'),
|
key: const Key('btn_image_editor_close'),
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed:
|
||||||
|
() => Navigator.of(context).pop(
|
||||||
|
ImageEditorResult(
|
||||||
|
rotation: _rotation,
|
||||||
|
graphicAdjust: domain.GraphicAdjust(
|
||||||
|
contrast: _contrast,
|
||||||
|
brightness: _brightness,
|
||||||
|
bgRemoval: _bgRemoval,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
MaterialLocalizations.of(context).closeButtonLabel,
|
MaterialLocalizations.of(context).closeButtonLabel,
|
||||||
),
|
),
|
||||||
|
|
@ -112,6 +112,13 @@ class _RotatedSignatureImageState extends State<RotatedSignatureImage> {
|
||||||
filterQuality: widget.filterQuality,
|
filterQuality: widget.filterQuality,
|
||||||
alignment: widget.alignment,
|
alignment: widget.alignment,
|
||||||
semanticLabel: widget.semanticLabel,
|
semanticLabel: widget.semanticLabel,
|
||||||
|
errorBuilder: (context, error, stackTrace) {
|
||||||
|
// Return a placeholder for invalid images
|
||||||
|
return Container(
|
||||||
|
color: Colors.grey[300],
|
||||||
|
child: const Icon(Icons.broken_image, color: Colors.grey),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (angle != 0.0) {
|
if (angle != 0.0) {
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,12 @@ import 'dart:typed_data';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/l10n/app_localizations.dart';
|
import 'package:pdf_signature/l10n/app_localizations.dart';
|
||||||
// No direct model construction needed here
|
// 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_asset_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_card_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_card_repository.dart';
|
||||||
import '../../pdf/widgets/image_editor_dialog.dart';
|
import 'package:pdf_signature/domain/models/model.dart' hide SignatureCard;
|
||||||
|
import 'image_editor_dialog.dart';
|
||||||
import 'signature_card.dart';
|
import 'signature_card.dart';
|
||||||
|
|
||||||
/// Data for drag-and-drop is in signature_drag_data.dart
|
/// Data for drag-and-drop is in signature_drag_data.dart
|
||||||
|
|
@ -59,10 +60,20 @@ class _SignatureDrawerState extends ConsumerState<SignatureDrawer> {
|
||||||
.remove(card),
|
.remove(card),
|
||||||
onAdjust: () async {
|
onAdjust: () async {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
await showDialog(
|
final result = await showDialog<ImageEditorResult>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (_) => const ImageEditorDialog(),
|
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: () {
|
onTap: () {
|
||||||
// state = const Rect.fromLTWH(0.2, 0.2, 0.3, 0.15);
|
// state = const Rect.fromLTWH(0.2, 0.2, 0.3, 0.15);
|
||||||
|
|
@ -107,12 +118,22 @@ class _SignatureDrawerState extends ConsumerState<SignatureDrawer> {
|
||||||
await widget.onLoadSignatureFromFile();
|
await widget.onLoadSignatureFromFile();
|
||||||
final b = loaded;
|
final b = loaded;
|
||||||
if (b != null) {
|
if (b != null) {
|
||||||
|
final asset = SignatureAsset(
|
||||||
|
bytes: b,
|
||||||
|
name: 'image',
|
||||||
|
);
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(
|
||||||
signatureAssetRepositoryProvider
|
signatureAssetRepositoryProvider
|
||||||
.notifier,
|
.notifier,
|
||||||
)
|
)
|
||||||
.add(b, name: 'image');
|
.add(b, name: 'image');
|
||||||
|
ref
|
||||||
|
.read(
|
||||||
|
signatureCardRepositoryProvider
|
||||||
|
.notifier,
|
||||||
|
)
|
||||||
|
.addWithAsset(asset, 0.0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.image_outlined),
|
icon: const Icon(Icons.image_outlined),
|
||||||
|
|
@ -127,12 +148,22 @@ class _SignatureDrawerState extends ConsumerState<SignatureDrawer> {
|
||||||
final drawn = await widget.onOpenDrawCanvas();
|
final drawn = await widget.onOpenDrawCanvas();
|
||||||
final b = drawn;
|
final b = drawn;
|
||||||
if (b != null) {
|
if (b != null) {
|
||||||
|
final asset = SignatureAsset(
|
||||||
|
bytes: b,
|
||||||
|
name: 'drawing',
|
||||||
|
);
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(
|
||||||
signatureAssetRepositoryProvider
|
signatureAssetRepositoryProvider
|
||||||
.notifier,
|
.notifier,
|
||||||
)
|
)
|
||||||
.add(b, name: 'drawing');
|
.add(b, name: 'drawing');
|
||||||
|
ref
|
||||||
|
.read(
|
||||||
|
signatureCardRepositoryProvider
|
||||||
|
.notifier,
|
||||||
|
)
|
||||||
|
.addWithAsset(asset, 0.0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.gesture),
|
icon: const Icon(Icons.gesture),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue