fix: graphic adjust dialog has to show image preview

This commit is contained in:
insleker 2025-09-12 22:44:00 +08:00
parent 461c8f6ae5
commit 8f3039f99e
6 changed files with 110 additions and 24 deletions

View File

@ -63,6 +63,7 @@ class MyApp extends StatelessWidget {
],
routerConfig: ref.watch(routerProvider),
builder: (context, child) {
final router = ref.watch(routerProvider);
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context).appTitle),
@ -73,7 +74,11 @@ class MyApp extends StatelessWidget {
label: Text(AppLocalizations.of(context).settings),
onPressed:
() => showDialog<bool>(
context: context,
context:
router
.routerDelegate
.navigatorKey
.currentContext!,
builder: (_) => const SettingsDialog(),
),
),

View File

@ -1,4 +1,5 @@
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:pdf_signature/ui/features/pdf/widgets/pdf_screen.dart';
@ -79,6 +80,9 @@ final routerProvider = Provider<GoRouter>((ref) {
signatureCardRepositoryProvider.notifier,
);
// Create a navigator key for the router
final navigatorKey = GlobalKey<NavigatorState>();
// Create a late variable for the router
late final GoRouter router;
@ -90,6 +94,7 @@ final routerProvider = Provider<GoRouter>((ref) {
final initialLocation = documentNotifier.debugState.loaded ? '/pdf' : '/';
router = GoRouter(
navigatorKey: navigatorKey,
routes: [
GoRoute(
path: '/',

View File

@ -33,13 +33,6 @@ class AdjustmentsPanel extends StatelessWidget {
runSpacing: 8,
crossAxisAlignment: WrapCrossAlignment.center,
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(
key: const Key('swt_bg_removal'),
value: bgRemoval,

View File

@ -1,22 +1,51 @@
import 'package:flutter/material.dart';
import 'package:pdf_signature/l10n/app_localizations.dart';
import 'adjustments_panel.dart';
// No live preview wiring in simplified dialog
import '../../pdf/widgets/adjustments_panel.dart';
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 {
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
State<ImageEditorDialog> createState() => _ImageEditorDialogState();
}
class _ImageEditorDialogState extends State<ImageEditorDialog> {
// Local-only state for demo/tests; no persistence to repositories.
bool _aspectLocked = false;
bool _bgRemoval = false;
double _contrast = 1.0; // 0..2
double _brightness = 0.0; // -1..1
double _rotation = 0.0; // -180..180
late bool _aspectLocked;
late bool _bgRemoval;
late double _contrast;
late double _brightness;
late double _rotation;
@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
Widget build(BuildContext context) {
@ -37,7 +66,7 @@ class _ImageEditorDialogState extends State<ImageEditorDialog> {
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 12),
// Preview placeholder; no actual processed bytes wired
// Preview with actual signature image
SizedBox(
height: 160,
child: DecoratedBox(
@ -45,7 +74,13 @@ class _ImageEditorDialogState extends State<ImageEditorDialog> {
border: Border.all(color: Theme.of(context).dividerColor),
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),
@ -84,7 +119,17 @@ class _ImageEditorDialogState extends State<ImageEditorDialog> {
children: [
TextButton(
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(
MaterialLocalizations.of(context).closeButtonLabel,
),

View File

@ -112,6 +112,13 @@ class _RotatedSignatureImageState extends State<RotatedSignatureImage> {
filterQuality: widget.filterQuality,
alignment: widget.alignment,
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) {

View File

@ -2,11 +2,12 @@ import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.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_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';
/// Data for drag-and-drop is in signature_drag_data.dart
@ -59,10 +60,20 @@ class _SignatureDrawerState extends ConsumerState<SignatureDrawer> {
.remove(card),
onAdjust: () async {
if (!mounted) return;
await showDialog(
final result = await showDialog<ImageEditorResult>(
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: () {
// state = const Rect.fromLTWH(0.2, 0.2, 0.3, 0.15);
@ -107,12 +118,22 @@ class _SignatureDrawerState extends ConsumerState<SignatureDrawer> {
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),
@ -127,12 +148,22 @@ class _SignatureDrawerState extends ConsumerState<SignatureDrawer> {
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),