feat: migrate to whole new data model and update relevant use

cases.
This commit is contained in:
insleker 2025-09-09 21:44:54 +08:00
parent fba880e1be
commit 380be43c05
16 changed files with 184 additions and 113 deletions

2
.gitignore vendored
View File

@ -135,3 +135,5 @@ AppDir/bundle/
appimage-build/
/*.AppImage
.vscode/settings.json
*.patch

View File

@ -2,25 +2,27 @@
## user stories
The following user stories may not use formal terminology as [meta-arch.md](./meta-arch.md) and use cases(`test/*.feature`), but use oral descriptions.
* name: [PDF browser](../test/features/pdf_browser.feature)
* role: user
* functionality: view and navigate PDF documents
* benefit: select page to add signature
* name: [load signature picture](../test/features/load_signature_picture.feature)
* name: [load signature](../test/features/load_signature.feature)
* role: user
* functionality: load a signature picture file
* functionality: load a signature asset file and create a signature card
* benefit: easily add signature to PDF
* name: [geometrically adjust signature picture](../test/features/geometrically_adjust_signature_picture.feature)
* role: user
* functionality: adjust the size and position of the signature picture
* functionality: adjust the scale, rotation and position of the signature placement on the PDF page
* benefit: ensure the signature fits well on the PDF page
* name: [graphically adjust signature picture](../test/features/graphically_adjust_signature_picture.feature)
* role: user
* functionality: background removal, contrast adjustment...
* functionality: background removal, contrast adjustment... to enhance the appearance of the signature asset within the signature card
* benefit: easily improve the appearance of the signature on the PDF without additional software.
* name: [draw signature](../test/features/draw_signature.feature)
* role: user
* functionality: draw a signature using mouse or touch input
* functionality: draw a signature asset using mouse or touch input
* benefit: create a custom signature directly on the PDF if no pre-made signature is available.
* name: [save signed PDF](../test/features/save_signed_pdf.feature)
* role: user
@ -28,7 +30,7 @@
* benefit: easily keep a copy of the signed document for records.
* name: [preferences for app](../test/features/app_preferences.feature)
* role: user
* functionality: configure app preferences such as `theme`, `language`.
* functionality: configure app preferences such as `language`, `theme`, `theme-color`.
* benefit: customize the app experience to better fit user needs
* name: [remember preferences](../test/features/remember_preferences.feature)
* role: user

View File

@ -11,6 +11,21 @@ The repo structure follows official [Package structure](https://docs.flutter.dev
* `test/widget/` contains UI widget(component) tests which focus on `View` from MVVM of each component.
* `integration_test/` for integration tests. They should be volatile to follow UI layout changes.
## Abstraction
### terminology
* signature asset
* image file of a signature, stored in the device or cloud storage
* can drawing from canvas
* signature card
* template of signature placement
* It will include modifications such as brightness, contrast, background removal, rotation of the signature asset.
* signature placement
* placed modified signature asset from signature card on a specific position on a specific page of a specific PDF document
* document
* PDF document to be signed
## key dependencies
* [pdfrx](https://pub.dev/packages/pdfrx)

View File

@ -1,32 +1,80 @@
import 'dart:typed_data';
import 'package:flutter/widgets.dart';
/// A simple library of signature images available to the user in the sidebar.
class SignatureAsset {
final String id; // unique id
final Uint8List bytes;
// List<List<Offset>>? strokes;
final String? name; // optional display name (e.g., filename)
const SignatureAsset({required this.id, required this.bytes, this.name});
}
class GraphicAdjust {
final double contrast;
final double brightness;
final bool bgRemoval;
const GraphicAdjust({
this.contrast = 1.0,
this.brightness = 0.0,
this.bgRemoval = false,
});
GraphicAdjust copyWith({
double? contrast,
double? brightness,
bool? bgRemoval,
}) => GraphicAdjust(
contrast: contrast ?? this.contrast,
brightness: brightness ?? this.brightness,
bgRemoval: bgRemoval ?? this.bgRemoval,
);
}
/**
* signature card is template of signature placement
*/
class SignatureCard {
final double rotationDeg;
final SignatureAsset asset;
GraphicAdjust graphicAdjust;
SignatureCard({required this.rotationDeg, required this.asset})
: graphicAdjust = GraphicAdjust();
}
/// Represents a single signature placement on a page combining both the
/// geometric rectangle (UI coordinate space) and the identifier of the
/// image/signature asset assigned to that placement.
class SignaturePlacement {
// The bounding box of this placement in UI coordinate space, implies scaling and position.
final Rect rect;
/// from `SignatureCard`
/// Rotation in degrees to apply when rendering/exporting this placement.
final double rotationDeg;
GraphicAdjust graphicAdjust;
final SignatureAsset asset;
/// Identifier of the image (e.g., filename / asset id) assigned to this placement.
/// Nullable to allow a placement reserved before an image is chosen.
final String? imageId;
const SignaturePlacement({
SignaturePlacement({
required this.rect,
this.imageId,
required this.asset,
this.rotationDeg = 0.0,
});
GraphicAdjust graphicAdjust = const GraphicAdjust(),
}) : graphicAdjust = graphicAdjust;
SignaturePlacement copyWith({
Rect? rect,
String? imageId,
double? rotationDeg,
required Rect rect,
required SignatureAsset asset,
double rotationDeg = 0.0,
GraphicAdjust graphicAdjust = const GraphicAdjust(),
}) => SignaturePlacement(
rect: rect ?? this.rect,
imageId: imageId ?? this.imageId,
rotationDeg: rotationDeg ?? this.rotationDeg,
rect: rect,
asset: asset,
rotationDeg: rotationDeg,
graphicAdjust: graphicAdjust,
);
}

View File

@ -2,6 +2,7 @@ import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:pdf_signature/l10n/app_localizations.dart';
import 'package:pdf_signature/data/model/model.dart';
import '../../../../data/services/export_providers.dart';
import '../../signature/view_model/signature_controller.dart';

View File

@ -1,13 +1,6 @@
import 'dart:typed_data';
import 'package:flutter_riverpod/flutter_riverpod.dart';
/// A simple library of signature images available to the user in the sidebar.
class SignatureAsset {
final String id; // unique id
final Uint8List bytes;
final String? name; // optional display name (e.g., filename)
const SignatureAsset({required this.id, required this.bytes, this.name});
}
import 'package:pdf_signature/data/model/model.dart';
class SignatureLibraryController extends StateNotifier<List<SignatureAsset>> {
SignatureLibraryController() : super(const []);

View File

@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import '../view_model/signature_library.dart';
import 'package:pdf_signature/data/model/model.dart';
import 'signature_drag_data.dart';
import 'rotated_signature_image.dart';
import 'package:pdf_signature/l10n/app_localizations.dart';

View File

@ -1,10 +1,10 @@
Feature: draw signature
Feature: draw signature asset
Scenario: Draw with mouse or touch and place on page
Given an empty signature canvas
When the user draws strokes and confirms
Then a signature image is created
And it is placed on the selected page
Then a signature asset is created
And signature placement occurs on the selected page
Scenario: Clear and redraw
Given a drawn signature exists in the canvas

View File

@ -1,12 +1,13 @@
Feature: geometrically adjust signature picture
Feature: geometrically adjust signature asset
Scenario: Resize and move the signature within page bounds
Given a signature image is placed on the page
Given a signature asset is placed on the page
When the user drags handles to resize and drags to reposition
Then the size and position update in real time
And the signature remains within the page area
And the signature placement remains within the page area
Scenario: Lock aspect ratio while resizing
Given a signature image is selected
When the user enables aspect ratio lock and resizes
Then the image scales proportionally
Scenario: Rotate the signature
Given a signature asset is placed on the page
When the user uses rotate controls
Then the signature placement rotates around its center in real time
And resize to fit within bounding box

View File

@ -1,13 +1,13 @@
Feature: graphically adjust signature picture
Feature: graphically adjust signature asset
Scenario: Remove background
Given a signature image is selected
Given a signature asset is selected
When the user enables background removal
Then near-white background becomes transparent in the preview
And the user can apply the change
Scenario: Adjust contrast and brightness
Given a signature image is selected
Given a signature asset is selected
When the user changes contrast and brightness controls
Then the preview updates immediately
And the user can apply or reset adjustments

View File

@ -0,0 +1,27 @@
Feature: load signature asset
Scenario Outline: Handle invalid or unsupported files
Given the user selects "<file>"
When the app attempts to load the asset
Then the user is notified of the issue
And the asset is not added to the document
Examples:
| file |
| 'corrupted.png' |
| 'signature.bmp' |
| 'empty.jpg' |
Scenario: Import a signature asset
When the user chooses a image file as a signature asset
Then the asset is loaded and shown as a signature asset
Scenario: Import a signature card
When the user chooses a signature asset to created a signature card
Then the asset is loaded and shown as a signature card
Scenario: Import a signature placement
Given a created signature card
When the user drags this signature card on the page of the document to place a signature placement
Then a signature placement appears on the page based on the signature card

View File

@ -1,18 +0,0 @@
Feature: load signature picture
Scenario: Import a signature image
Given a PDF page is selected for signing
When the user chooses a signature image file
Then the image is loaded and shown as a signature asset
Scenario Outline: Handle invalid or unsupported files
Given the user selects "<file>"
When the app attempts to load the image
Then the user is notified of the issue
And the image is not added to the document
Examples:
| file |
| 'corrupted.png' |
| 'signature.bmp' |
| 'empty.jpg' |

View File

@ -1,9 +1,9 @@
Feature: PDF browser
Feature: document browser
Background:
Given a sample multi-page PDF (5 pages) is available
Given a sample multi-page document (5 pages) is available
Scenario: Open a PDF and navigate pages
Scenario: Open a document and navigate pages
When the user opens the document
Then the first page is displayed
And the user can move to the next or previous page
@ -47,6 +47,6 @@ Feature: PDF browser
Then the last page is displayed (page {5})
And the page label shows "Page {5} of {5}"
Scenario: Go to is disabled when no PDF is loaded
Scenario: Go to is disabled when no document is loaded
Given no document is open
Then the Go to input cannot be used

View File

@ -1,26 +1,26 @@
Feature: save signed PDF
Feature: save signed document
Scenario: Export the signed document to a new file
Given a PDF is open and contains at least one placed signature
Given a document is open and contains at least one signature placement
When the user saves/exports the document
Then a new PDF file is saved at specified full path, location and file name
And the signatures appear on the corresponding page in the output
Then a new document file is saved at specified full path, location and file name
And the signature placements appear on the corresponding page in the output
And keep other unchanged content(pages) intact in the output
Scenario: Vector-accurate stamping into PDF page coordinates
Given a signature is placed with a position and size relative to the page
Given a signature placement is placed with a position and size relative to the page
When the user saves/exports the document
Then the signature is stamped at the exact PDF page coordinates and size
Then the signature placement is stamped at the exact PDF page coordinates and size
And the stamp remains crisp at any zoom level (not rasterized by the screen)
And other page content remains vector and unaltered
Scenario: Prevent saving when nothing is placed
Given a PDF is open with no signatures placed
Given a document is open with no signature placements placed
When the user attempts to save
Then the user is notified there is nothing to save
Scenario: Loading sign when exporting/saving files
Given a signature is placed with a position and size relative to the page
Given a signature placement is placed with a position and size relative to the page
When the user starts exporting the document
And the export process is not yet finished
Then the user is notified that the export is still in progress

View File

@ -1,30 +1,30 @@
Feature: support multiple signature pictures
Feature: support multiple signature assets
Scenario: Place signatures on different pages with different images
Given a multi-page PDF is open
When the user places a signature from picture <first_image> on page <first_page>
And the user places a signature from picture <second_image> on page <second_page>
Then both signatures are shown on their respective pages
Scenario: Place signature placements on different pages with different assets
Given a multi-page document is open
When the user places a signature placement from asset <first_asset> on page <first_page>
And the user places a signature placement from asset <second_asset> on page <second_page>
Then both signature placements are shown on their respective pages
Examples:
# Same page, same image
# Same page, different images
# Different pages, same image
# Different pages, different images
| first_image | first_page | second_image | second_page |
# Same page, same asset
# Same page, different assets
# Different pages, same asset
# Different pages, different assets
| first_asset | first_page | second_asset | second_page |
| 'alice.png' | 1 | 'alice.png' | 1 |
| 'alice.png' | 1 | 'bob.png' | 1 |
| 'alice.png' | 1 | 'bob.png' | 3 |
| 'bob.png' | 2 | 'alice.png' | 5 |
Scenario: Reuse the same image for more than one signature
Given a signature image is loaded or drawn
Scenario: Reuse the same asset for more than one signature placement
Given a signature asset is loaded or drawn
When the user places it in multiple locations in the document
Then identical signature instances appear in each location
And adjusting one instance does not affect the others
Scenario: Save/export uses the assigned image for each signature
Given a PDF is open and contains multiple placed signatures across pages
Scenario: Save/export uses the assigned asset for each signature placement
Given a document is open and contains multiple placed signature placements across pages
When the user saves/exports the document
Then all placed signatures appear on their corresponding pages in the output
Then all placed signature placements appear on their corresponding pages in the output
And other page content remains unaltered

View File

@ -1,38 +1,38 @@
Feature: support multiple signatures
Feature: support multiple signature placements
Scenario: Place signatures on different pages
Given a multi-page PDF is open
When the user places a signature on page {1}
And the user navigates to page {3} and places another signature
Then both signatures are shown on their respective pages
Scenario: Place signature placements on different pages
Given a multi-page document is open
When the user places a signature placement on page {1}
And the user navigates to page {3} and places another signature placement
Then both signature placements are shown on their respective pages
Scenario: Place multiple signatures on the same page independently
Given a PDF page is selected for signing
When the user places two signatures on the same page
Then each signature can be dragged and resized independently
Scenario: Place multiple signature placements on the same page independently
Given a document page is selected for signing
When the user places two signature placements on the same page
Then each signature placement can be dragged and resized independently
And dragging or resizing one does not change the other
Scenario: Reuse the same signature asset in multiple locations
Given a signature image is loaded or drawn
When the user places it in multiple locations in the document
Then identical signature instances appear in each location
And adjusting one instance does not affect the others
Given a signature asset loaded or drawn is wrapped in a signature card
When the user drags it on the page of the document to place signature placements in multiple locations in the document
Then identical signature placements appear in each location
And adjusting one of the signature placements does not affect the others
Scenario: Remove one of many signatures
Given three signatures are placed on the current page
When the user deletes one selected signature
Then only the selected signature is removed
And the other signatures remain unchanged
Scenario: Remove one of many signature placements
Given three signature placements are placed on the current page
When the user deletes one selected signature placement
Then only the selected signature placement is removed
And the other signature placements remain unchanged
Scenario: Keep earlier signatures while navigating between pages
Given a signature is placed on page {2}
When the user navigates to page {5} and places another signature
Then the signature on page {2} remains
And the signature on page {5} is shown on page {5}
Scenario: Keep earlier signature placements while navigating between pages
Given a signature placement is placed on page {2}
When the user navigates to page {5} and places another signature placement
Then the signature placement on page {2} remains
And the signature placement on page {5} is shown on page {5}
Scenario: Save a document with multiple signatures across pages
Given a PDF is open and contains multiple placed signatures across pages
Scenario: Save a document with multiple signature placements across pages
Given a document is open and contains multiple placed signature placements across pages
When the user saves/exports the document
Then all placed signatures appear on their corresponding pages in the output
Then all placed signature placements appear on their corresponding pages in the output
And other page content remains unaltered