feat: move `model.dart` to `/lib/domain/models/`
This commit is contained in:
parent
c1b7824cbd
commit
948999fe8e
|
@ -7,7 +7,52 @@
|
||||||
|
|
||||||
## Package structure
|
## Package structure
|
||||||
|
|
||||||
The repo structure follows official [Package structure](https://docs.flutter.dev/app-architecture/case-study#package-structure) with slight modifications.
|
The repo structure follows official [Package structure](https://docs.flutter.dev/app-architecture/case-study#package-structure).
|
||||||
|
|
||||||
|
```
|
||||||
|
lib
|
||||||
|
├─┬─ ui
|
||||||
|
│ ├─┬─ core
|
||||||
|
│ │ ├─┬─ ui
|
||||||
|
│ │ │ └─── <shared widgets>
|
||||||
|
│ │ └─── themes
|
||||||
|
│ └─┬─ <FEATURE NAME>
|
||||||
|
│ ├─┬─ view_model
|
||||||
|
│ │ └─── <view_model class>.dart
|
||||||
|
│ └─┬─ widgets
|
||||||
|
│ ├── <feature name>_screen.dart
|
||||||
|
│ └── <other widgets>
|
||||||
|
├─┬─ domain
|
||||||
|
│ └─┬─ models
|
||||||
|
│ └─── <model name>.dart
|
||||||
|
├─┬─ data
|
||||||
|
│ ├─┬─ repositories
|
||||||
|
│ │ └─── <repository class>.dart
|
||||||
|
│ ├─┬─ services
|
||||||
|
│ │ └─── <service class>.dart
|
||||||
|
│ └─┬─ model
|
||||||
|
│ └─── <api model class>.dart
|
||||||
|
├─── config
|
||||||
|
├─── utils
|
||||||
|
├─── routing
|
||||||
|
├─── main_staging.dart
|
||||||
|
├─── main_development.dart
|
||||||
|
└─── main.dart
|
||||||
|
|
||||||
|
// The test folder contains unit and widget tests
|
||||||
|
test
|
||||||
|
├─── data
|
||||||
|
├─── domain
|
||||||
|
├─── ui
|
||||||
|
└─── utils
|
||||||
|
|
||||||
|
// The testing folder contains mocks other classes need to execute tests
|
||||||
|
testing
|
||||||
|
├─── fakes
|
||||||
|
└─── models
|
||||||
|
```
|
||||||
|
|
||||||
|
But with slight modifications.
|
||||||
|
|
||||||
* put each `<FEATURE NAME>/`s in `features/` sub-directory under `ui/`.
|
* put each `<FEATURE NAME>/`s in `features/` sub-directory under `ui/`.
|
||||||
* `test/features/` contains BDD unit tests for each feature. It focuses on pure logic, therefore will not access `View` but `ViewModel` and `Model`.
|
* `test/features/` contains BDD unit tests for each feature. It focuses on pure logic, therefore will not access `View` but `ViewModel` and `Model`.
|
||||||
|
@ -21,15 +66,15 @@ Some rule of thumb:
|
||||||
|
|
||||||
### terminology
|
### terminology
|
||||||
|
|
||||||
* signature asset
|
* `signature asset`
|
||||||
* image file of a signature, stored in the device or cloud storage
|
* image file of a signature, stored in the device or cloud storage
|
||||||
* can drawing from canvas
|
* can drawing from canvas
|
||||||
* signature card
|
* `signature card`
|
||||||
* template of signature placement
|
* template of signature placement
|
||||||
* It will include modifications such as brightness, contrast, background removal, rotation of the signature asset.
|
* It will include modifications such as brightness, contrast, background removal, rotation of the signature asset.
|
||||||
* signature placement
|
* `signature placement`
|
||||||
* placed modified signature asset from signature card on a specific position on a specific page of a specific PDF document
|
* placed modified signature asset from signature card on a specific position on a specific page of a specific PDF document
|
||||||
* document
|
* `document`
|
||||||
* PDF document to be signed
|
* PDF document to be signed
|
||||||
|
|
||||||
## key dependencies
|
## key dependencies
|
||||||
|
|
|
@ -7,7 +7,7 @@ import 'package:image/image.dart' as img;
|
||||||
|
|
||||||
import 'package:pdf_signature/data/services/export_service.dart';
|
import 'package:pdf_signature/data/services/export_service.dart';
|
||||||
import 'package:pdf_signature/data/services/export_providers.dart';
|
import 'package:pdf_signature/data/services/export_providers.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/ui/features/pdf/widgets/pdf_screen.dart';
|
import 'package:pdf_signature/ui/features/pdf/widgets/pdf_screen.dart';
|
||||||
|
@ -32,8 +32,8 @@ void main() {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
ProviderScope(
|
ProviderScope(
|
||||||
overrides: [
|
overrides: [
|
||||||
pdfProvider.overrideWith(
|
documentRepositoryProvider.overrideWith(
|
||||||
(ref) => PdfController()..openPicked(path: 'test.pdf'),
|
(ref) => DocumentStateNotifier()..openPicked(path: 'test.pdf'),
|
||||||
),
|
),
|
||||||
signatureProvider.overrideWith(
|
signatureProvider.overrideWith(
|
||||||
(ref) => SignatureController()..placeDefaultRect(),
|
(ref) => SignatureController()..placeDefaultRect(),
|
||||||
|
@ -85,11 +85,11 @@ void main() {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
ProviderScope(
|
ProviderScope(
|
||||||
overrides: [
|
overrides: [
|
||||||
pdfProvider.overrideWith(
|
documentRepositoryProvider.overrideWith(
|
||||||
(ref) => PdfController()..openPicked(path: 'test.pdf'),
|
(ref) => DocumentStateNotifier()..openPicked(path: 'test.pdf'),
|
||||||
),
|
),
|
||||||
signatureLibraryProvider.overrideWith((ref) {
|
signatureAssetRepositoryProvider.overrideWith((ref) {
|
||||||
final c = SignatureLibraryController();
|
final c = SignatureAssetRepository();
|
||||||
c.add(sigBytes, name: 'image');
|
c.add(sigBytes, name: 'image');
|
||||||
return c;
|
return c;
|
||||||
}),
|
}),
|
||||||
|
@ -121,11 +121,11 @@ void main() {
|
||||||
final container = ProviderScope.containerOf(ctx);
|
final container = ProviderScope.containerOf(ctx);
|
||||||
final sigState = container.read(signatureProvider);
|
final sigState = container.read(signatureProvider);
|
||||||
final r = sigState.rect!;
|
final r = sigState.rect!;
|
||||||
final lib = container.read(signatureLibraryProvider);
|
final lib = container.read(signatureAssetRepositoryProvider);
|
||||||
final asset = lib.isNotEmpty ? lib.first : null;
|
final asset = lib.isNotEmpty ? lib.first : null;
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(page: pdf.currentPage, rect: r, asset: asset);
|
.addPlacement(page: pdf.currentPage, rect: r, asset: asset);
|
||||||
container.read(signatureProvider.notifier).clearActiveOverlay();
|
container.read(signatureProvider.notifier).clearActiveOverlay();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
|
@ -98,7 +98,7 @@ class _RootHomeSwitcher extends ConsumerWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final pdf = ref.watch(pdfProvider);
|
final pdf = ref.watch(documentRepositoryProvider);
|
||||||
if (!pdf.loaded) {
|
if (!pdf.loaded) {
|
||||||
return const WelcomeScreen();
|
return const WelcomeScreen();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,206 +0,0 @@
|
||||||
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;
|
|
||||||
final GraphicAdjust graphicAdjust;
|
|
||||||
|
|
||||||
const SignatureCard({
|
|
||||||
required this.rotationDeg,
|
|
||||||
required this.asset,
|
|
||||||
this.graphicAdjust = const GraphicAdjust(),
|
|
||||||
});
|
|
||||||
|
|
||||||
SignatureCard copyWith({
|
|
||||||
double? rotationDeg,
|
|
||||||
SignatureAsset? asset,
|
|
||||||
GraphicAdjust? graphicAdjust,
|
|
||||||
}) => SignatureCard(
|
|
||||||
rotationDeg: rotationDeg ?? this.rotationDeg,
|
|
||||||
asset: asset ?? this.asset,
|
|
||||||
graphicAdjust: graphicAdjust ?? this.graphicAdjust,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents a single signature placement on a page combining both the
|
|
||||||
/// geometric rectangle (UI coordinate space) and the 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;
|
|
||||||
|
|
||||||
/// Rotation in degrees to apply when rendering/exporting this placement.
|
|
||||||
final double rotationDeg;
|
|
||||||
final GraphicAdjust graphicAdjust;
|
|
||||||
final SignatureAsset asset;
|
|
||||||
|
|
||||||
const SignaturePlacement({
|
|
||||||
required this.rect,
|
|
||||||
required this.asset,
|
|
||||||
this.rotationDeg = 0.0,
|
|
||||||
this.graphicAdjust = const GraphicAdjust(),
|
|
||||||
});
|
|
||||||
|
|
||||||
SignaturePlacement copyWith({
|
|
||||||
Rect? rect,
|
|
||||||
SignatureAsset? asset,
|
|
||||||
double? rotationDeg,
|
|
||||||
GraphicAdjust? graphicAdjust,
|
|
||||||
}) => SignaturePlacement(
|
|
||||||
rect: rect ?? this.rect,
|
|
||||||
asset: asset ?? this.asset,
|
|
||||||
rotationDeg: rotationDeg ?? this.rotationDeg,
|
|
||||||
graphicAdjust: graphicAdjust ?? this.graphicAdjust,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class PdfState {
|
|
||||||
final bool loaded;
|
|
||||||
final int pageCount;
|
|
||||||
final int currentPage;
|
|
||||||
final String? pickedPdfPath;
|
|
||||||
final Uint8List? pickedPdfBytes;
|
|
||||||
final int? signedPage;
|
|
||||||
// Multiple signature placements per page, each combines geometry and asset.
|
|
||||||
final Map<int, List<SignaturePlacement>> placementsByPage;
|
|
||||||
// UI state: selected placement index on the current page (if any)
|
|
||||||
final int? selectedPlacementIndex;
|
|
||||||
const PdfState({
|
|
||||||
required this.loaded,
|
|
||||||
required this.pageCount,
|
|
||||||
required this.currentPage,
|
|
||||||
this.pickedPdfPath,
|
|
||||||
this.pickedPdfBytes,
|
|
||||||
this.signedPage,
|
|
||||||
this.placementsByPage = const {},
|
|
||||||
this.selectedPlacementIndex,
|
|
||||||
});
|
|
||||||
factory PdfState.initial() => const PdfState(
|
|
||||||
loaded: false,
|
|
||||||
pageCount: 0,
|
|
||||||
currentPage: 1,
|
|
||||||
pickedPdfBytes: null,
|
|
||||||
signedPage: null,
|
|
||||||
placementsByPage: {},
|
|
||||||
selectedPlacementIndex: null,
|
|
||||||
);
|
|
||||||
PdfState copyWith({
|
|
||||||
bool? loaded,
|
|
||||||
int? pageCount,
|
|
||||||
int? currentPage,
|
|
||||||
String? pickedPdfPath,
|
|
||||||
Uint8List? pickedPdfBytes,
|
|
||||||
int? signedPage,
|
|
||||||
Map<int, List<SignaturePlacement>>? placementsByPage,
|
|
||||||
int? selectedPlacementIndex,
|
|
||||||
}) => PdfState(
|
|
||||||
loaded: loaded ?? this.loaded,
|
|
||||||
pageCount: pageCount ?? this.pageCount,
|
|
||||||
currentPage: currentPage ?? this.currentPage,
|
|
||||||
pickedPdfPath: pickedPdfPath ?? this.pickedPdfPath,
|
|
||||||
pickedPdfBytes: pickedPdfBytes ?? this.pickedPdfBytes,
|
|
||||||
signedPage: signedPage ?? this.signedPage,
|
|
||||||
placementsByPage: placementsByPage ?? this.placementsByPage,
|
|
||||||
selectedPlacementIndex:
|
|
||||||
selectedPlacementIndex ?? this.selectedPlacementIndex,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class SignatureState {
|
|
||||||
final Rect? rect;
|
|
||||||
final bool aspectLocked;
|
|
||||||
final bool bgRemoval;
|
|
||||||
final double contrast;
|
|
||||||
final double brightness;
|
|
||||||
// Rotation in degrees applied to the signature image when rendering/exporting
|
|
||||||
final double rotation;
|
|
||||||
final List<List<Offset>> strokes;
|
|
||||||
final Uint8List? imageBytes;
|
|
||||||
// The signature asset the current overlay is based on (from library)
|
|
||||||
final SignatureAsset? asset;
|
|
||||||
// When true, the active signature overlay is movable/resizable and should not be exported.
|
|
||||||
// When false, the overlay is confirmed (unmovable) and eligible for export.
|
|
||||||
final bool editingEnabled;
|
|
||||||
const SignatureState({
|
|
||||||
required this.rect,
|
|
||||||
required this.aspectLocked,
|
|
||||||
required this.bgRemoval,
|
|
||||||
required this.contrast,
|
|
||||||
required this.brightness,
|
|
||||||
this.rotation = 0.0,
|
|
||||||
required this.strokes,
|
|
||||||
this.imageBytes,
|
|
||||||
this.asset,
|
|
||||||
this.editingEnabled = false,
|
|
||||||
});
|
|
||||||
factory SignatureState.initial() => const SignatureState(
|
|
||||||
rect: null,
|
|
||||||
aspectLocked: false,
|
|
||||||
bgRemoval: false,
|
|
||||||
contrast: 1.0,
|
|
||||||
brightness: 0.0,
|
|
||||||
rotation: 0.0,
|
|
||||||
strokes: [],
|
|
||||||
imageBytes: null,
|
|
||||||
asset: null,
|
|
||||||
editingEnabled: false,
|
|
||||||
);
|
|
||||||
SignatureState copyWith({
|
|
||||||
Rect? rect,
|
|
||||||
bool? aspectLocked,
|
|
||||||
bool? bgRemoval,
|
|
||||||
double? contrast,
|
|
||||||
double? brightness,
|
|
||||||
double? rotation,
|
|
||||||
List<List<Offset>>? strokes,
|
|
||||||
Uint8List? imageBytes,
|
|
||||||
SignatureAsset? asset,
|
|
||||||
bool? editingEnabled,
|
|
||||||
}) => SignatureState(
|
|
||||||
rect: rect ?? this.rect,
|
|
||||||
aspectLocked: aspectLocked ?? this.aspectLocked,
|
|
||||||
bgRemoval: bgRemoval ?? this.bgRemoval,
|
|
||||||
contrast: contrast ?? this.contrast,
|
|
||||||
brightness: brightness ?? this.brightness,
|
|
||||||
rotation: rotation ?? this.rotation,
|
|
||||||
strokes: strokes ?? this.strokes,
|
|
||||||
imageBytes: imageBytes ?? this.imageBytes,
|
|
||||||
asset: asset ?? this.asset,
|
|
||||||
editingEnabled: editingEnabled ?? this.editingEnabled,
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -2,57 +2,39 @@ 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 '../../../../data/model/model.dart';
|
import '../../domain/models/model.dart';
|
||||||
|
|
||||||
class PdfController extends StateNotifier<PdfState> {
|
class DocumentStateNotifier extends StateNotifier<Document> {
|
||||||
PdfController() : super(PdfState.initial());
|
DocumentStateNotifier() : super(Document.initial());
|
||||||
static const int samplePageCount = 5;
|
|
||||||
|
|
||||||
@visibleForTesting
|
@visibleForTesting
|
||||||
void openSample() {
|
void openSample() {
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
loaded: true,
|
loaded: true,
|
||||||
pageCount: samplePageCount,
|
pageCount: 5,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pickedPdfPath: null,
|
|
||||||
signedPage: null,
|
|
||||||
placementsByPage: {},
|
placementsByPage: {},
|
||||||
selectedPlacementIndex: null,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void openPicked({
|
void openPicked({
|
||||||
required String path,
|
required String path,
|
||||||
int pageCount = samplePageCount,
|
required int pageCount,
|
||||||
Uint8List? bytes,
|
Uint8List? bytes,
|
||||||
}) {
|
}) {
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
loaded: true,
|
loaded: true,
|
||||||
pageCount: pageCount,
|
pageCount: pageCount,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pickedPdfPath: path,
|
|
||||||
pickedPdfBytes: bytes,
|
pickedPdfBytes: bytes,
|
||||||
signedPage: null,
|
|
||||||
placementsByPage: {},
|
placementsByPage: {},
|
||||||
selectedPlacementIndex: null,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void jumpTo(int page) {
|
void jumpTo(int page) {
|
||||||
if (!state.loaded) return;
|
if (!state.loaded) return;
|
||||||
final clamped = page.clamp(1, state.pageCount);
|
final clamped = page.clamp(1, state.pageCount);
|
||||||
state = state.copyWith(currentPage: clamped, selectedPlacementIndex: null);
|
state = state.copyWith(currentPage: clamped);
|
||||||
}
|
|
||||||
|
|
||||||
// Set or clear the page that will receive the signature overlay.
|
|
||||||
void setSignedPage(int? page) {
|
|
||||||
if (!state.loaded) return;
|
|
||||||
if (page == null) {
|
|
||||||
state = state.copyWith(signedPage: null, selectedPlacementIndex: null);
|
|
||||||
} else {
|
|
||||||
final clamped = page.clamp(1, state.pageCount);
|
|
||||||
state = state.copyWith(signedPage: clamped, selectedPlacementIndex: null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPageCount(int count) {
|
void setPageCount(int count) {
|
||||||
|
@ -80,7 +62,7 @@ class PdfController extends StateNotifier<PdfState> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
map[p] = list;
|
map[p] = list;
|
||||||
state = state.copyWith(placementsByPage: map, selectedPlacementIndex: null);
|
state = state.copyWith(placementsByPage: map);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updatePlacementRotation({
|
void updatePlacementRotation({
|
||||||
|
@ -111,10 +93,7 @@ class PdfController extends StateNotifier<PdfState> {
|
||||||
} else {
|
} else {
|
||||||
map[p] = list;
|
map[p] = list;
|
||||||
}
|
}
|
||||||
state = state.copyWith(
|
state = state.copyWith(placementsByPage: map);
|
||||||
placementsByPage: map,
|
|
||||||
selectedPlacementIndex: null,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,27 +121,6 @@ class PdfController extends StateNotifier<PdfState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void selectPlacement(int? index) {
|
|
||||||
if (!state.loaded) return;
|
|
||||||
// Only allow valid index on current page; otherwise clear
|
|
||||||
if (index == null) {
|
|
||||||
state = state.copyWith(selectedPlacementIndex: null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final list = state.placementsByPage[state.currentPage] ?? const [];
|
|
||||||
if (index >= 0 && index < list.length) {
|
|
||||||
state = state.copyWith(selectedPlacementIndex: index);
|
|
||||||
} else {
|
|
||||||
state = state.copyWith(selectedPlacementIndex: null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void deleteSelectedPlacement() {
|
|
||||||
final idx = state.selectedPlacementIndex;
|
|
||||||
if (idx == null) return;
|
|
||||||
removePlacement(page: state.currentPage, index: idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Programmatic reassignment of images has been removed.
|
// NOTE: Programmatic reassignment of images has been removed.
|
||||||
|
|
||||||
// Convenience to get asset for a placement
|
// Convenience to get asset for a placement
|
||||||
|
@ -173,6 +131,7 @@ class PdfController extends StateNotifier<PdfState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final pdfProvider = StateNotifierProvider<PdfController, PdfState>(
|
final documentRepositoryProvider =
|
||||||
(ref) => PdfController(),
|
StateNotifierProvider<DocumentStateNotifier, Document>(
|
||||||
);
|
(ref) => DocumentStateNotifier(),
|
||||||
|
);
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
|
|
||||||
class SignatureLibraryController extends StateNotifier<List<SignatureAsset>> {
|
///
|
||||||
SignatureLibraryController() : super(const []);
|
class SignatureAssetRepository extends StateNotifier<List<SignatureAsset>> {
|
||||||
|
SignatureAssetRepository() : super(const []);
|
||||||
|
|
||||||
String add(Uint8List bytes, {String? name}) {
|
String add(Uint8List bytes, {String? name}) {
|
||||||
// Always add a new asset (allow duplicates). This lets users create multiple cards
|
// Always add a new asset (allow duplicates). This lets users create multiple cards
|
||||||
|
@ -27,7 +28,7 @@ class SignatureLibraryController extends StateNotifier<List<SignatureAsset>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final signatureLibraryProvider =
|
final signatureAssetRepositoryProvider =
|
||||||
StateNotifierProvider<SignatureLibraryController, List<SignatureAsset>>(
|
StateNotifierProvider<SignatureAssetRepository, List<SignatureAsset>>(
|
||||||
(ref) => SignatureLibraryController(),
|
(ref) => SignatureAssetRepository(),
|
||||||
);
|
);
|
|
@ -6,15 +6,18 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:image/image.dart' as img;
|
import 'package:image/image.dart' as img;
|
||||||
import 'package:pdf_signature/l10n/app_localizations.dart';
|
import 'package:pdf_signature/l10n/app_localizations.dart';
|
||||||
|
|
||||||
import '../../../../data/model/model.dart';
|
import '../../domain/models/model.dart';
|
||||||
import 'pdf_repository.dart';
|
import 'pdf_repository.dart';
|
||||||
|
|
||||||
class SignatureController extends StateNotifier<SignatureState> {
|
class SignatureController extends StateNotifier<SignatureCard> {
|
||||||
SignatureController() : super(SignatureState.initial());
|
final Ref ref;
|
||||||
|
SignatureController(this.ref) : super(SignatureCard.initial());
|
||||||
static const Size pageSize = Size(400, 560);
|
static const Size pageSize = Size(400, 560);
|
||||||
|
|
||||||
void resetForNewPage() {
|
void resetForNewPage() {
|
||||||
state = SignatureState.initial();
|
state = SignatureCard.initial();
|
||||||
|
ref.read(currentRectProvider.notifier).setRect(null);
|
||||||
|
ref.read(editingEnabledProvider.notifier).set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@visibleForTesting
|
@visibleForTesting
|
||||||
|
@ -26,19 +29,22 @@ class SignatureController extends StateNotifier<SignatureState> {
|
||||||
final cy = pageSize.height * (0.1 + rand.nextDouble() * 0.8);
|
final cy = pageSize.height * (0.1 + rand.nextDouble() * 0.8);
|
||||||
Rect r = Rect.fromCenter(center: Offset(cx, cy), width: w, height: h);
|
Rect r = Rect.fromCenter(center: Offset(cx, cy), width: w, height: h);
|
||||||
r = _clampRectToPage(r);
|
r = _clampRectToPage(r);
|
||||||
state = state.copyWith(rect: r, editingEnabled: true);
|
ref.read(currentRectProvider.notifier).setRect(r);
|
||||||
|
ref.read(editingEnabledProvider.notifier).set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadSample() {
|
void loadSample() {
|
||||||
final w = 120.0, h = 60.0;
|
final w = 120.0, h = 60.0;
|
||||||
state = state.copyWith(
|
ref
|
||||||
rect: Rect.fromCenter(
|
.read(currentRectProvider.notifier)
|
||||||
|
.setRect(
|
||||||
|
Rect.fromCenter(
|
||||||
center: Offset(pageSize.width / 2, pageSize.height * 0.75),
|
center: Offset(pageSize.width / 2, pageSize.height * 0.75),
|
||||||
width: w,
|
width: w,
|
||||||
height: h,
|
height: h,
|
||||||
),
|
),
|
||||||
editingEnabled: true,
|
|
||||||
);
|
);
|
||||||
|
ref.read(editingEnabledProvider.notifier).set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setInvalidSelected(BuildContext context) {
|
void setInvalidSelected(BuildContext context) {
|
||||||
|
@ -56,17 +62,19 @@ class SignatureController extends StateNotifier<SignatureState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void drag(Offset delta) {
|
void drag(Offset delta) {
|
||||||
if (state.rect == null || !state.editingEnabled) return;
|
final currentRect = ref.read(currentRectProvider);
|
||||||
final moved = state.rect!.shift(delta);
|
if (currentRect == null || !ref.read(editingEnabledProvider)) return;
|
||||||
state = state.copyWith(rect: _clampRectToPage(moved));
|
final moved = currentRect.shift(delta);
|
||||||
|
ref.read(currentRectProvider.notifier).setRect(_clampRectToPage(moved));
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize(Offset delta) {
|
void resize(Offset delta) {
|
||||||
if (state.rect == null || !state.editingEnabled) return;
|
final currentRect = ref.read(currentRectProvider);
|
||||||
final r = state.rect!;
|
if (currentRect == null || !ref.read(editingEnabledProvider)) return;
|
||||||
|
final r = currentRect;
|
||||||
double newW = r.width + delta.dx;
|
double newW = r.width + delta.dx;
|
||||||
double newH = r.height + delta.dy;
|
double newH = r.height + delta.dy;
|
||||||
if (state.aspectLocked) {
|
if (ref.read(aspectLockedProvider)) {
|
||||||
final aspect = r.width / r.height;
|
final aspect = r.width / r.height;
|
||||||
// Keep ratio based on the dominant proportional delta
|
// Keep ratio based on the dominant proportional delta
|
||||||
final dxRel = (delta.dx / r.width).abs();
|
final dxRel = (delta.dx / r.width).abs();
|
||||||
|
@ -90,7 +98,7 @@ class SignatureController extends StateNotifier<SignatureState> {
|
||||||
newH *= minScale;
|
newH *= minScale;
|
||||||
Rect resized = Rect.fromLTWH(r.left, r.top, newW, newH);
|
Rect resized = Rect.fromLTWH(r.left, r.top, newW, newH);
|
||||||
resized = _clampRectPositionToPage(resized);
|
resized = _clampRectPositionToPage(resized);
|
||||||
state = state.copyWith(rect: resized);
|
ref.read(currentRectProvider.notifier).setRect(resized);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Unlocked aspect: clamp each dimension independently
|
// Unlocked aspect: clamp each dimension independently
|
||||||
|
@ -98,7 +106,7 @@ class SignatureController extends StateNotifier<SignatureState> {
|
||||||
newH = newH.clamp(20.0, pageSize.height);
|
newH = newH.clamp(20.0, pageSize.height);
|
||||||
Rect resized = Rect.fromLTWH(r.left, r.top, newW, newH);
|
Rect resized = Rect.fromLTWH(r.left, r.top, newW, newH);
|
||||||
resized = _clampRectToPage(resized);
|
resized = _clampRectToPage(resized);
|
||||||
state = state.copyWith(rect: resized);
|
ref.read(currentRectProvider.notifier).setRect(resized);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect _clampRectToPage(Rect r) {
|
Rect _clampRectToPage(Rect r) {
|
||||||
|
@ -116,89 +124,98 @@ class SignatureController extends StateNotifier<SignatureState> {
|
||||||
return Rect.fromLTWH(left, top, r.width, r.height);
|
return Rect.fromLTWH(left, top, r.width, r.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void toggleAspect(bool v) => state = state.copyWith(aspectLocked: v);
|
void toggleAspect(bool v) => ref.read(aspectLockedProvider.notifier).set(v);
|
||||||
void setBgRemoval(bool v) => state = state.copyWith(bgRemoval: v);
|
void setBgRemoval(bool v) =>
|
||||||
void setContrast(double v) => state = state.copyWith(contrast: v);
|
|
||||||
void setBrightness(double v) => state = state.copyWith(brightness: v);
|
|
||||||
void setRotation(double deg) => state = state.copyWith(rotation: deg);
|
|
||||||
|
|
||||||
void setStrokes(List<List<Offset>> strokes) =>
|
|
||||||
state = state.copyWith(strokes: strokes);
|
|
||||||
void ensureRectForStrokes() {
|
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
rect:
|
graphicAdjust: state.graphicAdjust.copyWith(bgRemoval: v),
|
||||||
state.rect ??
|
);
|
||||||
|
void setContrast(double v) =>
|
||||||
|
state = state.copyWith(
|
||||||
|
graphicAdjust: state.graphicAdjust.copyWith(contrast: v),
|
||||||
|
);
|
||||||
|
void setBrightness(double v) =>
|
||||||
|
state = state.copyWith(
|
||||||
|
graphicAdjust: state.graphicAdjust.copyWith(brightness: v),
|
||||||
|
);
|
||||||
|
void setRotation(double deg) => state = state.copyWith(rotationDeg: deg);
|
||||||
|
|
||||||
|
void ensureRectForStrokes() {
|
||||||
|
if (ref.read(currentRectProvider) == null) {
|
||||||
|
ref
|
||||||
|
.read(currentRectProvider.notifier)
|
||||||
|
.setRect(
|
||||||
Rect.fromCenter(
|
Rect.fromCenter(
|
||||||
center: Offset(pageSize.width / 2, pageSize.height * 0.75),
|
center: Offset(pageSize.width / 2, pageSize.height * 0.75),
|
||||||
width: 140,
|
width: 140,
|
||||||
height: 70,
|
height: 70,
|
||||||
),
|
),
|
||||||
editingEnabled: true,
|
|
||||||
);
|
);
|
||||||
|
ref.read(editingEnabledProvider.notifier).set(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setImageBytes(Uint8List bytes) {
|
void setImageBytes(Uint8List bytes) {
|
||||||
state = state.copyWith(imageBytes: bytes, asset: null);
|
final newAsset = SignatureAsset(id: 'drawn', bytes: bytes);
|
||||||
if (state.rect == null) {
|
state = state.copyWith(asset: newAsset);
|
||||||
|
if (ref.read(currentRectProvider) == null) {
|
||||||
placeDefaultRect();
|
placeDefaultRect();
|
||||||
}
|
}
|
||||||
// Mark as draft/editable when user just loaded image
|
ref.read(editingEnabledProvider.notifier).set(true);
|
||||||
state = state.copyWith(editingEnabled: true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select image from the shared signature library
|
// Select image from the shared signature library
|
||||||
void setImageFromLibrary({required SignatureAsset asset}) {
|
void setImageFromLibrary({required SignatureAsset asset}) {
|
||||||
state = state.copyWith(asset: asset);
|
state = state.copyWith(asset: asset);
|
||||||
if (state.rect == null) {
|
if (ref.read(currentRectProvider) == null) {
|
||||||
placeDefaultRect();
|
placeDefaultRect();
|
||||||
}
|
}
|
||||||
state = state.copyWith(editingEnabled: true);
|
ref.read(editingEnabledProvider.notifier).set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearImage() {
|
void clearImage() {
|
||||||
state = state.copyWith(imageBytes: null, rect: null, editingEnabled: false);
|
state = SignatureCard.initial();
|
||||||
|
ref.read(currentRectProvider.notifier).setRect(null);
|
||||||
|
ref.read(editingEnabledProvider.notifier).set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void placeAtCenter(Offset center, {double width = 120, double height = 60}) {
|
void placeAtCenter(Offset center, {double width = 120, double height = 60}) {
|
||||||
Rect r = Rect.fromCenter(center: center, width: width, height: height);
|
Rect r = Rect.fromCenter(center: center, width: width, height: height);
|
||||||
r = _clampRectToPage(r);
|
r = _clampRectToPage(r);
|
||||||
state = state.copyWith(rect: r, editingEnabled: true);
|
ref.read(currentRectProvider.notifier).setRect(r);
|
||||||
|
ref.read(editingEnabledProvider.notifier).set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confirm current signature: freeze editing and place it on the PDF as an immutable overlay.
|
// Confirm current signature: freeze editing and place it on the PDF as an immutable overlay.
|
||||||
// Stores the placement rect in UI-space (SignatureController.pageSize units).
|
// Stores the placement rect in UI-space (SignatureController.pageSize units).
|
||||||
// Returns the Rect placed, or null if no rect to confirm.
|
// Returns the Rect placed, or null if no rect to confirm.
|
||||||
Rect? confirmCurrentSignature(WidgetRef ref) {
|
Rect? confirmCurrentSignature(WidgetRef ref) {
|
||||||
final r = state.rect;
|
final r = ref.read(currentRectProvider);
|
||||||
if (r == null) return null;
|
if (r == null) return null;
|
||||||
// Place onto the current page
|
// Place onto the current page
|
||||||
final pdf = ref.read(pdfProvider);
|
final pdf = ref.read(documentRepositoryProvider);
|
||||||
if (!pdf.loaded) return null;
|
if (!pdf.loaded) return null;
|
||||||
// Bind the processed image at placement time (so placed preview matches adjustments).
|
|
||||||
// If processed bytes exist, always create a new asset for this placement.
|
|
||||||
// Prefer reusing an existing library asset when the active overlay is
|
|
||||||
// based on a library item. If there is no library asset, do NOT create
|
|
||||||
// a new library card here — keep the placement's asset empty so the
|
|
||||||
// UI and exporter will fall back to using the processed/current bytes.
|
|
||||||
// Store as UI-space rect (consistent with export and rendering paths)
|
|
||||||
ref
|
ref
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: pdf.currentPage,
|
page: pdf.currentPage,
|
||||||
rect: r,
|
rect: r,
|
||||||
asset: state.asset,
|
asset: state.asset,
|
||||||
rotationDeg: state.rotation,
|
rotationDeg: state.rotationDeg,
|
||||||
);
|
);
|
||||||
// Newly placed index is the last one on the page
|
// Newly placed index is the last one on the page
|
||||||
final idx =
|
final idx =
|
||||||
(ref.read(pdfProvider).placementsByPage[pdf.currentPage]?.length ?? 1) -
|
(ref
|
||||||
|
.read(documentRepositoryProvider)
|
||||||
|
.placementsByPage[pdf.currentPage]
|
||||||
|
?.length ??
|
||||||
|
1) -
|
||||||
1;
|
1;
|
||||||
// Auto-select the newly placed item so the red box appears
|
// Auto-select the newly placed item so the red box appears
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
ref.read(pdfProvider.notifier).selectPlacement(idx);
|
ref.read(documentRepositoryProvider.notifier).selectPlacement(idx);
|
||||||
}
|
}
|
||||||
// Freeze editing: keep rect for preview but disable interaction
|
// Freeze editing: keep rect for preview but disable interaction
|
||||||
state = state.copyWith(editingEnabled: false);
|
ref.read(editingEnabledProvider.notifier).set(false);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,76 +223,89 @@ class SignatureController extends StateNotifier<SignatureState> {
|
||||||
// Useful in widget tests where obtaining a WidgetRef is not straightforward.
|
// Useful in widget tests where obtaining a WidgetRef is not straightforward.
|
||||||
@visibleForTesting
|
@visibleForTesting
|
||||||
Rect? confirmCurrentSignatureWithContainer(ProviderContainer container) {
|
Rect? confirmCurrentSignatureWithContainer(ProviderContainer container) {
|
||||||
final r = state.rect;
|
final r = container.read(currentRectProvider);
|
||||||
if (r == null) return null;
|
if (r == null) return null;
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
if (!pdf.loaded) return null;
|
if (!pdf.loaded) return null;
|
||||||
// Reuse existing library asset if present; otherwise leave empty so the
|
|
||||||
// placement will reference the current bytes via fallback paths.
|
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: pdf.currentPage,
|
page: pdf.currentPage,
|
||||||
rect: r,
|
rect: r,
|
||||||
asset: state.asset,
|
asset: state.asset,
|
||||||
rotationDeg: state.rotation,
|
rotationDeg: state.rotationDeg,
|
||||||
);
|
);
|
||||||
final idx =
|
final idx =
|
||||||
(container
|
(container
|
||||||
.read(pdfProvider)
|
.read(documentRepositoryProvider)
|
||||||
.placementsByPage[pdf.currentPage]
|
.placementsByPage[pdf.currentPage]
|
||||||
?.length ??
|
?.length ??
|
||||||
1) -
|
1) -
|
||||||
1;
|
1;
|
||||||
// Auto-select the newly placed item so the red box appears
|
// Auto-select the newly placed item so the red box appears
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
container.read(pdfProvider.notifier).selectPlacement(idx);
|
container.read(documentRepositoryProvider.notifier).selectPlacement(idx);
|
||||||
}
|
}
|
||||||
// Freeze editing: keep rect for preview but disable interaction
|
// Freeze editing: keep rect for preview but disable interaction
|
||||||
state = state.copyWith(editingEnabled: false);
|
container.read(editingEnabledProvider.notifier).set(false);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the active overlay (draft or confirmed preview) but keep image settings intact
|
// Remove the active overlay (draft or confirmed preview) but keep image settings intact
|
||||||
void clearActiveOverlay() {
|
void clearActiveOverlay() {
|
||||||
state = state.copyWith(rect: null, editingEnabled: false);
|
ref.read(currentRectProvider.notifier).setRect(null);
|
||||||
|
ref.read(editingEnabledProvider.notifier).set(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final signatureProvider =
|
final signatureCardProvider =
|
||||||
StateNotifierProvider<SignatureController, SignatureState>(
|
StateNotifierProvider<SignatureController, SignatureCard>(
|
||||||
(ref) => SignatureController(),
|
(ref) => SignatureController(ref),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final currentRectProvider = StateNotifierProvider<RectNotifier, Rect?>(
|
||||||
|
(ref) => RectNotifier(),
|
||||||
|
);
|
||||||
|
|
||||||
|
class RectNotifier extends StateNotifier<Rect?> {
|
||||||
|
RectNotifier() : super(null);
|
||||||
|
|
||||||
|
void setRect(Rect? r) => state = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
final editingEnabledProvider = StateNotifierProvider<BoolNotifier, bool>(
|
||||||
|
(ref) => BoolNotifier(false),
|
||||||
|
);
|
||||||
|
|
||||||
|
class BoolNotifier extends StateNotifier<bool> {
|
||||||
|
BoolNotifier(bool initial) : super(initial);
|
||||||
|
|
||||||
|
void set(bool v) => state = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
final aspectLockedProvider = StateNotifierProvider<BoolNotifier, bool>(
|
||||||
|
(ref) => BoolNotifier(false),
|
||||||
|
);
|
||||||
|
|
||||||
/// Derived provider that returns processed signature image bytes according to
|
/// Derived provider that returns processed signature image bytes according to
|
||||||
/// current adjustment settings (contrast/brightness) and background removal.
|
/// current adjustment settings (contrast/brightness) and background removal.
|
||||||
/// Returns null if no image is loaded. The output is a PNG to preserve alpha.
|
/// Returns null if no image is loaded. The output is a PNG to preserve alpha.
|
||||||
final processedSignatureImageProvider = Provider<Uint8List?>((ref) {
|
final processedSignatureImageProvider = Provider<Uint8List?>((ref) {
|
||||||
// Watch only the fields that affect pixel processing to avoid recompute on rotation.
|
final SignatureAsset asset = ref.watch(
|
||||||
final SignatureAsset? asset = ref.watch(
|
signatureCardProvider.select((s) => s.asset),
|
||||||
signatureProvider.select((s) => s.asset),
|
|
||||||
);
|
|
||||||
final Uint8List? directBytes = ref.watch(
|
|
||||||
signatureProvider.select((s) => s.imageBytes),
|
|
||||||
);
|
);
|
||||||
final double contrast = ref.watch(
|
final double contrast = ref.watch(
|
||||||
signatureProvider.select((s) => s.contrast),
|
signatureCardProvider.select((s) => s.graphicAdjust.contrast),
|
||||||
);
|
);
|
||||||
final double brightness = ref.watch(
|
final double brightness = ref.watch(
|
||||||
signatureProvider.select((s) => s.brightness),
|
signatureCardProvider.select((s) => s.graphicAdjust.brightness),
|
||||||
);
|
);
|
||||||
final bool bgRemoval = ref.watch(
|
final bool bgRemoval = ref.watch(
|
||||||
signatureProvider.select((s) => s.bgRemoval),
|
signatureCardProvider.select((s) => s.graphicAdjust.bgRemoval),
|
||||||
);
|
);
|
||||||
|
|
||||||
// If active overlay is based on a library asset, pull its bytes
|
Uint8List? bytes = asset.bytes;
|
||||||
Uint8List? bytes;
|
if (bytes.isEmpty) return null;
|
||||||
if (asset != null) {
|
|
||||||
bytes = asset.bytes;
|
|
||||||
} else {
|
|
||||||
bytes = directBytes;
|
|
||||||
}
|
|
||||||
if (bytes == null || bytes.isEmpty) return null;
|
|
||||||
|
|
||||||
// Decode (supports PNG/JPEG, etc.)
|
// Decode (supports PNG/JPEG, etc.)
|
||||||
final decoded = img.decodeImage(bytes);
|
final decoded = img.decodeImage(bytes);
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'package:pdf/widgets.dart' as pw;
|
||||||
import 'package:pdf/pdf.dart' as pdf;
|
import 'package:pdf/pdf.dart' as pdf;
|
||||||
import 'package:printing/printing.dart' as printing;
|
import 'package:printing/printing.dart' as printing;
|
||||||
import 'package:image/image.dart' as img;
|
import 'package:image/image.dart' as img;
|
||||||
import '../model/model.dart';
|
import '../../domain/models/model.dart';
|
||||||
|
|
||||||
// NOTE:
|
// NOTE:
|
||||||
// - This exporter uses a raster snapshot of the UI (RepaintBoundary) and embeds it into a new PDF.
|
// - This exporter uses a raster snapshot of the UI (RepaintBoundary) and embeds it into a new PDF.
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import 'dart:typed_data';
|
||||||
|
import 'signature_placement.dart';
|
||||||
|
|
||||||
|
/// PDF document to be signed
|
||||||
|
class Document {
|
||||||
|
final bool loaded;
|
||||||
|
final int pageCount;
|
||||||
|
final int currentPage;
|
||||||
|
final Uint8List? pickedPdfBytes;
|
||||||
|
// Multiple signature placements per page, each combines geometry and asset.
|
||||||
|
final Map<int, List<SignaturePlacement>> placementsByPage;
|
||||||
|
const Document({
|
||||||
|
required this.loaded,
|
||||||
|
required this.pageCount,
|
||||||
|
required this.currentPage,
|
||||||
|
this.pickedPdfBytes,
|
||||||
|
this.placementsByPage = const {},
|
||||||
|
});
|
||||||
|
factory Document.initial() => const Document(
|
||||||
|
loaded: false,
|
||||||
|
pageCount: 0,
|
||||||
|
currentPage: 1,
|
||||||
|
pickedPdfBytes: null,
|
||||||
|
placementsByPage: {},
|
||||||
|
);
|
||||||
|
Document copyWith({
|
||||||
|
bool? loaded,
|
||||||
|
int? pageCount,
|
||||||
|
int? currentPage,
|
||||||
|
Uint8List? pickedPdfBytes,
|
||||||
|
Map<int, List<SignaturePlacement>>? placementsByPage,
|
||||||
|
}) => Document(
|
||||||
|
loaded: loaded ?? this.loaded,
|
||||||
|
pageCount: pageCount ?? this.pageCount,
|
||||||
|
currentPage: currentPage ?? this.currentPage,
|
||||||
|
pickedPdfBytes: pickedPdfBytes ?? this.pickedPdfBytes,
|
||||||
|
placementsByPage: placementsByPage ?? this.placementsByPage,
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
export 'signature_asset.dart';
|
||||||
|
export 'graphic_adjust.dart';
|
||||||
|
export 'signature_card.dart';
|
||||||
|
export 'signature_placement.dart';
|
||||||
|
export 'document.dart';
|
|
@ -0,0 +1,10 @@
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
/// SignatureAsset store image file of a signature, stored in the device or cloud storage
|
||||||
|
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});
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
import 'dart:typed_data';
|
||||||
|
import 'signature_asset.dart';
|
||||||
|
import 'graphic_adjust.dart';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* signature card is template of signature placement
|
||||||
|
* Use the [SignatureCardRepository] to obtain a full [SignatureCard]
|
||||||
|
*/
|
||||||
|
class SignatureCard {
|
||||||
|
final double rotationDeg;
|
||||||
|
final SignatureAsset asset;
|
||||||
|
final GraphicAdjust graphicAdjust;
|
||||||
|
|
||||||
|
const SignatureCard({
|
||||||
|
required this.rotationDeg,
|
||||||
|
required this.asset,
|
||||||
|
this.graphicAdjust = const GraphicAdjust(),
|
||||||
|
});
|
||||||
|
|
||||||
|
SignatureCard copyWith({
|
||||||
|
double? rotationDeg,
|
||||||
|
SignatureAsset? asset,
|
||||||
|
GraphicAdjust? graphicAdjust,
|
||||||
|
}) => SignatureCard(
|
||||||
|
rotationDeg: rotationDeg ?? this.rotationDeg,
|
||||||
|
asset: asset ?? this.asset,
|
||||||
|
graphicAdjust: graphicAdjust ?? this.graphicAdjust,
|
||||||
|
);
|
||||||
|
|
||||||
|
factory SignatureCard.initial() => SignatureCard(
|
||||||
|
rotationDeg: 0.0,
|
||||||
|
asset: SignatureAsset(id: '', bytes: Uint8List(0)),
|
||||||
|
graphicAdjust: const GraphicAdjust(),
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
import 'dart:ui';
|
||||||
|
import 'signature_asset.dart';
|
||||||
|
import 'graphic_adjust.dart';
|
||||||
|
|
||||||
|
/// Represents a single signature placement on a page combining both the
|
||||||
|
/// geometric rectangle (UI coordinate space) and the 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;
|
||||||
|
|
||||||
|
/// Rotation in degrees to apply when rendering/exporting this placement.
|
||||||
|
final double rotationDeg;
|
||||||
|
final GraphicAdjust graphicAdjust;
|
||||||
|
final SignatureAsset asset;
|
||||||
|
|
||||||
|
const SignaturePlacement({
|
||||||
|
required this.rect,
|
||||||
|
required this.asset,
|
||||||
|
this.rotationDeg = 0.0,
|
||||||
|
this.graphicAdjust = const GraphicAdjust(),
|
||||||
|
});
|
||||||
|
|
||||||
|
SignaturePlacement copyWith({
|
||||||
|
Rect? rect,
|
||||||
|
SignatureAsset? asset,
|
||||||
|
double? rotationDeg,
|
||||||
|
GraphicAdjust? graphicAdjust,
|
||||||
|
}) => SignaturePlacement(
|
||||||
|
rect: rect ?? this.rect,
|
||||||
|
asset: asset ?? this.asset,
|
||||||
|
rotationDeg: rotationDeg ?? this.rotationDeg,
|
||||||
|
graphicAdjust: graphicAdjust ?? this.graphicAdjust,
|
||||||
|
);
|
||||||
|
}
|
|
@ -2,13 +2,13 @@ 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';
|
||||||
|
|
||||||
import '../../../../data/model/model.dart';
|
import '../../../../domain/models/model.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
||||||
|
|
||||||
class AdjustmentsPanel extends ConsumerWidget {
|
class AdjustmentsPanel extends ConsumerWidget {
|
||||||
const AdjustmentsPanel({super.key, required this.sig});
|
const AdjustmentsPanel({super.key, required this.sig});
|
||||||
|
|
||||||
final SignatureState sig;
|
final SignatureCard sig;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
@ -22,19 +22,20 @@ class AdjustmentsPanel extends ConsumerWidget {
|
||||||
children: [
|
children: [
|
||||||
Checkbox(
|
Checkbox(
|
||||||
key: const Key('chk_aspect_lock'),
|
key: const Key('chk_aspect_lock'),
|
||||||
value: sig.aspectLocked,
|
value: ref.watch(aspectLockedProvider),
|
||||||
onChanged:
|
onChanged:
|
||||||
(v) => ref
|
(v) => ref
|
||||||
.read(signatureProvider.notifier)
|
.read(signatureCardProvider.notifier)
|
||||||
.toggleAspect(v ?? false),
|
.toggleAspect(v ?? false),
|
||||||
),
|
),
|
||||||
Text(AppLocalizations.of(context).lockAspectRatio),
|
Text(AppLocalizations.of(context).lockAspectRatio),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
Switch(
|
Switch(
|
||||||
key: const Key('swt_bg_removal'),
|
key: const Key('swt_bg_removal'),
|
||||||
value: sig.bgRemoval,
|
value: sig.graphicAdjust.bgRemoval,
|
||||||
onChanged:
|
onChanged:
|
||||||
(v) => ref.read(signatureProvider.notifier).setBgRemoval(v),
|
(v) =>
|
||||||
|
ref.read(signatureCardProvider.notifier).setBgRemoval(v),
|
||||||
),
|
),
|
||||||
Text(AppLocalizations.of(context).backgroundRemoval),
|
Text(AppLocalizations.of(context).backgroundRemoval),
|
||||||
],
|
],
|
||||||
|
@ -47,15 +48,16 @@ class AdjustmentsPanel extends ConsumerWidget {
|
||||||
Text(AppLocalizations.of(context).contrast),
|
Text(AppLocalizations.of(context).contrast),
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: Text(sig.contrast.toStringAsFixed(2)),
|
child: Text(sig.graphicAdjust.contrast.toStringAsFixed(2)),
|
||||||
),
|
),
|
||||||
Slider(
|
Slider(
|
||||||
key: const Key('sld_contrast'),
|
key: const Key('sld_contrast'),
|
||||||
min: 0.0,
|
min: 0.0,
|
||||||
max: 2.0,
|
max: 2.0,
|
||||||
value: sig.contrast,
|
value: sig.graphicAdjust.contrast,
|
||||||
onChanged:
|
onChanged:
|
||||||
(v) => ref.read(signatureProvider.notifier).setContrast(v),
|
(v) =>
|
||||||
|
ref.read(signatureCardProvider.notifier).setContrast(v),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -66,15 +68,16 @@ class AdjustmentsPanel extends ConsumerWidget {
|
||||||
Text(AppLocalizations.of(context).brightness),
|
Text(AppLocalizations.of(context).brightness),
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: Text(sig.brightness.toStringAsFixed(2)),
|
child: Text(sig.graphicAdjust.brightness.toStringAsFixed(2)),
|
||||||
),
|
),
|
||||||
Slider(
|
Slider(
|
||||||
key: const Key('sld_brightness'),
|
key: const Key('sld_brightness'),
|
||||||
min: -1.0,
|
min: -1.0,
|
||||||
max: 1.0,
|
max: 1.0,
|
||||||
value: sig.brightness,
|
value: sig.graphicAdjust.brightness,
|
||||||
onChanged:
|
onChanged:
|
||||||
(v) => ref.read(signatureProvider.notifier).setBrightness(v),
|
(v) =>
|
||||||
|
ref.read(signatureCardProvider.notifier).setBrightness(v),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -51,7 +51,7 @@ class _PdfPageAreaState extends ConsumerState<PdfPageArea> {
|
||||||
// is instructed to align to the provider's current page once ready.
|
// is instructed to align to the provider's current page once ready.
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
final pdf = ref.read(pdfProvider);
|
final pdf = ref.read(documentRepositoryProvider);
|
||||||
if (pdf.pickedPdfPath != null && pdf.loaded) {
|
if (pdf.pickedPdfPath != null && pdf.loaded) {
|
||||||
_scrollToPage(pdf.currentPage);
|
_scrollToPage(pdf.currentPage);
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ class _PdfPageAreaState extends ConsumerState<PdfPageArea> {
|
||||||
void _scrollToPage(int page) {
|
void _scrollToPage(int page) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
final pdf = ref.read(pdfProvider);
|
final pdf = ref.read(documentRepositoryProvider);
|
||||||
const isContinuous = true;
|
const isContinuous = true;
|
||||||
|
|
||||||
// Real continuous: drive via PdfViewerController
|
// Real continuous: drive via PdfViewerController
|
||||||
|
@ -156,11 +156,11 @@ class _PdfPageAreaState extends ConsumerState<PdfPageArea> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final pdf = ref.watch(pdfProvider);
|
final pdf = ref.watch(documentRepositoryProvider);
|
||||||
const pageViewMode = 'continuous';
|
const pageViewMode = 'continuous';
|
||||||
|
|
||||||
// React to provider currentPage changes (e.g., user tapped overview)
|
// React to provider currentPage changes (e.g., user tapped overview)
|
||||||
ref.listen(pdfProvider, (prev, next) {
|
ref.listen(documentRepositoryProvider, (prev, next) {
|
||||||
if (_suppressProviderListen) return;
|
if (_suppressProviderListen) return;
|
||||||
if ((prev?.currentPage != next.currentPage)) {
|
if ((prev?.currentPage != next.currentPage)) {
|
||||||
final target = next.currentPage;
|
final target = next.currentPage;
|
||||||
|
@ -288,7 +288,9 @@ class _PdfPageAreaState extends ConsumerState<PdfPageArea> {
|
||||||
],
|
],
|
||||||
onViewerReady: (doc, controller) {
|
onViewerReady: (doc, controller) {
|
||||||
if (pdf.pageCount != doc.pages.length) {
|
if (pdf.pageCount != doc.pages.length) {
|
||||||
ref.read(pdfProvider.notifier).setPageCount(doc.pages.length);
|
ref
|
||||||
|
.read(documentRepositoryProvider.notifier)
|
||||||
|
.setPageCount(doc.pages.length);
|
||||||
}
|
}
|
||||||
final target = _pendingPage ?? pdf.currentPage;
|
final target = _pendingPage ?? pdf.currentPage;
|
||||||
_pendingPage = null;
|
_pendingPage = null;
|
||||||
|
@ -305,9 +307,9 @@ class _PdfPageAreaState extends ConsumerState<PdfPageArea> {
|
||||||
// Programmatic navigation: wait until target reached
|
// Programmatic navigation: wait until target reached
|
||||||
if (_programmaticTargetPage != null) {
|
if (_programmaticTargetPage != null) {
|
||||||
if (n == _programmaticTargetPage) {
|
if (n == _programmaticTargetPage) {
|
||||||
if (n != ref.read(pdfProvider).currentPage) {
|
if (n != ref.read(documentRepositoryProvider).currentPage) {
|
||||||
_suppressProviderListen = true;
|
_suppressProviderListen = true;
|
||||||
ref.read(pdfProvider.notifier).jumpTo(n);
|
ref.read(documentRepositoryProvider.notifier).jumpTo(n);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
_suppressProviderListen = false;
|
_suppressProviderListen = false;
|
||||||
});
|
});
|
||||||
|
@ -317,9 +319,9 @@ class _PdfPageAreaState extends ConsumerState<PdfPageArea> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// User scroll -> reflect page to provider without re-triggering scroll
|
// User scroll -> reflect page to provider without re-triggering scroll
|
||||||
if (n != ref.read(pdfProvider).currentPage) {
|
if (n != ref.read(documentRepositoryProvider).currentPage) {
|
||||||
_suppressProviderListen = true;
|
_suppressProviderListen = true;
|
||||||
ref.read(pdfProvider.notifier).jumpTo(n);
|
ref.read(documentRepositoryProvider.notifier).jumpTo(n);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
_suppressProviderListen = false;
|
_suppressProviderListen = false;
|
||||||
});
|
});
|
||||||
|
@ -348,8 +350,8 @@ class _PdfPageAreaState extends ConsumerState<PdfPageArea> {
|
||||||
}
|
}
|
||||||
ref.read(signatureProvider.notifier).placeAtCenter(Offset(cx, cy));
|
ref.read(signatureProvider.notifier).placeAtCenter(Offset(cx, cy));
|
||||||
ref
|
ref
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.setSignedPage(ref.read(pdfProvider).currentPage);
|
.setSignedPage(ref.read(documentRepositoryProvider).currentPage);
|
||||||
},
|
},
|
||||||
builder:
|
builder:
|
||||||
(context, candidateData, rejected) => Stack(
|
(context, candidateData, rejected) => Stack(
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
||||||
import '../../../../data/model/model.dart';
|
import '../../../../domain/models/model.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'signature_overlay.dart';
|
import 'signature_overlay.dart';
|
||||||
|
|
||||||
|
@ -29,8 +29,8 @@ class PdfPageOverlays extends ConsumerWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final pdf = ref.watch(pdfProvider);
|
final pdf = ref.watch(documentRepositoryProvider);
|
||||||
final sig = ref.watch(signatureProvider);
|
final sig = ref.watch(signatureCardProvider);
|
||||||
final placed =
|
final placed =
|
||||||
pdf.placementsByPage[pageNumber] ?? const <SignaturePlacement>[];
|
pdf.placementsByPage[pageNumber] ?? const <SignaturePlacement>[];
|
||||||
final widgets = <Widget>[];
|
final widgets = <Widget>[];
|
||||||
|
@ -44,16 +44,17 @@ class PdfPageOverlays extends ConsumerWidget {
|
||||||
rect: uiRect,
|
rect: uiRect,
|
||||||
sig: sig,
|
sig: sig,
|
||||||
pageNumber: pageNumber,
|
pageNumber: pageNumber,
|
||||||
interactive: false,
|
|
||||||
placedIndex: i,
|
placedIndex: i,
|
||||||
onSelectPlaced: onSelectPlaced,
|
onSelectPlaced: onSelectPlaced,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final currentRect = ref.watch(currentRectProvider);
|
||||||
|
final editingEnabled = ref.watch(editingEnabledProvider);
|
||||||
final showActive =
|
final showActive =
|
||||||
sig.rect != null &&
|
currentRect != null &&
|
||||||
sig.editingEnabled &&
|
editingEnabled &&
|
||||||
(pdf.signedPage == null || pdf.signedPage == pageNumber) &&
|
(pdf.signedPage == null || pdf.signedPage == pageNumber) &&
|
||||||
pdf.currentPage == pageNumber;
|
pdf.currentPage == pageNumber;
|
||||||
|
|
||||||
|
@ -61,10 +62,9 @@ class PdfPageOverlays extends ConsumerWidget {
|
||||||
widgets.add(
|
widgets.add(
|
||||||
SignatureOverlay(
|
SignatureOverlay(
|
||||||
pageSize: pageSize,
|
pageSize: pageSize,
|
||||||
rect: sig.rect!,
|
rect: currentRect,
|
||||||
sig: sig,
|
sig: sig,
|
||||||
pageNumber: pageNumber,
|
pageNumber: pageNumber,
|
||||||
interactive: true,
|
|
||||||
onDragSignature: onDragSignature,
|
onDragSignature: onDragSignature,
|
||||||
onResizeSignature: onResizeSignature,
|
onResizeSignature: onResizeSignature,
|
||||||
onConfirmSignature: onConfirmSignature,
|
onConfirmSignature: onConfirmSignature,
|
||||||
|
|
|
@ -10,7 +10,7 @@ class PdfPagesOverview extends ConsumerWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final pdf = ref.watch(pdfProvider);
|
final pdf = ref.watch(documentRepositoryProvider);
|
||||||
final useMock = ref.watch(useMockViewerProvider);
|
final useMock = ref.watch(useMockViewerProvider);
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
|
@ -25,7 +25,10 @@ class PdfPagesOverview extends ConsumerWidget {
|
||||||
final pageNumber = index + 1;
|
final pageNumber = index + 1;
|
||||||
final isSelected = pdf.currentPage == pageNumber;
|
final isSelected = pdf.currentPage == pageNumber;
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () => ref.read(pdfProvider.notifier).jumpTo(pageNumber),
|
onTap:
|
||||||
|
() => ref
|
||||||
|
.read(documentRepositoryProvider.notifier)
|
||||||
|
.jumpTo(pageNumber),
|
||||||
child: DecoratedBox(
|
child: DecoratedBox(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color:
|
color:
|
||||||
|
@ -74,7 +77,9 @@ class PdfPagesOverview extends ConsumerWidget {
|
||||||
final pages = document.pages;
|
final pages = document.pages;
|
||||||
if (pdf.pageCount != pages.length) {
|
if (pdf.pageCount != pages.length) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
ref.read(pdfProvider.notifier).setPageCount(pages.length);
|
ref
|
||||||
|
.read(documentRepositoryProvider.notifier)
|
||||||
|
.setPageCount(pages.length);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return buildList(
|
return buildList(
|
||||||
|
|
|
@ -12,7 +12,7 @@ import '../../../../data/services/export_providers.dart';
|
||||||
import 'package:image/image.dart' as img;
|
import 'package:image/image.dart' as img;
|
||||||
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import 'draw_canvas.dart';
|
import 'draw_canvas.dart';
|
||||||
import 'pdf_toolbar.dart';
|
import 'pdf_toolbar.dart';
|
||||||
import 'pdf_page_area.dart';
|
import 'pdf_page_area.dart';
|
||||||
|
@ -61,13 +61,15 @@ class _PdfSignatureHomePageState extends ConsumerState<PdfSignatureHomePage> {
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
bytes = null;
|
bytes = null;
|
||||||
}
|
}
|
||||||
ref.read(pdfProvider.notifier).openPicked(path: file.path, bytes: bytes);
|
ref
|
||||||
|
.read(documentRepositoryProvider.notifier)
|
||||||
|
.openPicked(path: file.path, bytes: bytes);
|
||||||
ref.read(signatureProvider.notifier).resetForNewPage();
|
ref.read(signatureProvider.notifier).resetForNewPage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _jumpToPage(int page) {
|
void _jumpToPage(int page) {
|
||||||
ref.read(pdfProvider.notifier).jumpTo(page);
|
ref.read(documentRepositoryProvider.notifier).jumpTo(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Uint8List?> _loadSignatureFromFile() async {
|
Future<Uint8List?> _loadSignatureFromFile() async {
|
||||||
|
@ -81,9 +83,11 @@ class _PdfSignatureHomePageState extends ConsumerState<PdfSignatureHomePage> {
|
||||||
final bytes = await file.readAsBytes();
|
final bytes = await file.readAsBytes();
|
||||||
final sig = ref.read(signatureProvider.notifier);
|
final sig = ref.read(signatureProvider.notifier);
|
||||||
sig.setImageBytes(bytes);
|
sig.setImageBytes(bytes);
|
||||||
final p = ref.read(pdfProvider);
|
final p = ref.read(documentRepositoryProvider);
|
||||||
if (p.loaded) {
|
if (p.loaded) {
|
||||||
ref.read(pdfProvider.notifier).setSignedPage(p.currentPage);
|
ref
|
||||||
|
.read(documentRepositoryProvider.notifier)
|
||||||
|
.setSignedPage(p.currentPage);
|
||||||
}
|
}
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
@ -101,7 +105,7 @@ class _PdfSignatureHomePageState extends ConsumerState<PdfSignatureHomePage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onSelectPlaced(int? index) {
|
void _onSelectPlaced(int? index) {
|
||||||
ref.read(pdfProvider.notifier).selectPlacement(index);
|
ref.read(documentRepositoryProvider.notifier).selectPlacement(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Uint8List?> _openDrawCanvas() async {
|
Future<Uint8List?> _openDrawCanvas() async {
|
||||||
|
@ -113,9 +117,11 @@ class _PdfSignatureHomePageState extends ConsumerState<PdfSignatureHomePage> {
|
||||||
);
|
);
|
||||||
if (result != null && result.isNotEmpty) {
|
if (result != null && result.isNotEmpty) {
|
||||||
ref.read(signatureProvider.notifier).setImageBytes(result);
|
ref.read(signatureProvider.notifier).setImageBytes(result);
|
||||||
final p = ref.read(pdfProvider);
|
final p = ref.read(documentRepositoryProvider);
|
||||||
if (p.loaded) {
|
if (p.loaded) {
|
||||||
ref.read(pdfProvider.notifier).setSignedPage(p.currentPage);
|
ref
|
||||||
|
.read(documentRepositoryProvider.notifier)
|
||||||
|
.setSignedPage(p.currentPage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -124,7 +130,7 @@ class _PdfSignatureHomePageState extends ConsumerState<PdfSignatureHomePage> {
|
||||||
Future<void> _saveSignedPdf() async {
|
Future<void> _saveSignedPdf() async {
|
||||||
ref.read(exportingProvider.notifier).state = true;
|
ref.read(exportingProvider.notifier).state = true;
|
||||||
try {
|
try {
|
||||||
final pdf = ref.read(pdfProvider);
|
final pdf = ref.read(documentRepositoryProvider);
|
||||||
final sig = ref.read(signatureProvider);
|
final sig = ref.read(signatureProvider);
|
||||||
final messenger = ScaffoldMessenger.of(context);
|
final messenger = ScaffoldMessenger.of(context);
|
||||||
if (!pdf.loaded || sig.rect == null) {
|
if (!pdf.loaded || sig.rect == null) {
|
||||||
|
@ -175,7 +181,8 @@ class _PdfSignatureHomePageState extends ConsumerState<PdfSignatureHomePage> {
|
||||||
signatureImageBytes: rotated,
|
signatureImageBytes: rotated,
|
||||||
placementsByPage: pdf.placementsByPage,
|
placementsByPage: pdf.placementsByPage,
|
||||||
libraryBytes: {
|
libraryBytes: {
|
||||||
for (final a in ref.read(signatureLibraryProvider)) a.id: a.bytes,
|
for (final a in ref.read(signatureAssetRepositoryProvider))
|
||||||
|
a.id: a.bytes,
|
||||||
},
|
},
|
||||||
targetDpi: targetDpi,
|
targetDpi: targetDpi,
|
||||||
);
|
);
|
||||||
|
@ -211,7 +218,8 @@ class _PdfSignatureHomePageState extends ConsumerState<PdfSignatureHomePage> {
|
||||||
signatureImageBytes: rotated,
|
signatureImageBytes: rotated,
|
||||||
placementsByPage: pdf.placementsByPage,
|
placementsByPage: pdf.placementsByPage,
|
||||||
libraryBytes: {
|
libraryBytes: {
|
||||||
for (final a in ref.read(signatureLibraryProvider)) a.id: a.bytes,
|
for (final a in ref.read(signatureAssetRepositoryProvider))
|
||||||
|
a.id: a.bytes,
|
||||||
},
|
},
|
||||||
targetDpi: targetDpi,
|
targetDpi: targetDpi,
|
||||||
);
|
);
|
||||||
|
@ -241,7 +249,7 @@ class _PdfSignatureHomePageState extends ConsumerState<PdfSignatureHomePage> {
|
||||||
signatureImageBytes: rotated,
|
signatureImageBytes: rotated,
|
||||||
placementsByPage: pdf.placementsByPage,
|
placementsByPage: pdf.placementsByPage,
|
||||||
libraryBytes: {
|
libraryBytes: {
|
||||||
for (final a in ref.read(signatureLibraryProvider))
|
for (final a in ref.read(signatureAssetRepositoryProvider))
|
||||||
a.id: a.bytes,
|
a.id: a.bytes,
|
||||||
},
|
},
|
||||||
targetDpi: targetDpi,
|
targetDpi: targetDpi,
|
||||||
|
@ -411,7 +419,7 @@ class _PdfSignatureHomePageState extends ConsumerState<PdfSignatureHomePage> {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
zoomLevel: _zoomLevel,
|
zoomLevel: _zoomLevel,
|
||||||
fileName: ref.watch(pdfProvider).pickedPdfPath,
|
fileName: ref.watch(documentRepositoryProvider).pickedPdfPath,
|
||||||
showPagesSidebar: _showPagesSidebar,
|
showPagesSidebar: _showPagesSidebar,
|
||||||
showSignaturesSidebar: _showSignaturesSidebar,
|
showSignaturesSidebar: _showSignaturesSidebar,
|
||||||
onTogglePagesSidebar:
|
onTogglePagesSidebar:
|
||||||
|
|
|
@ -55,7 +55,7 @@ class _PdfToolbarState extends ConsumerState<PdfToolbar> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final pdf = ref.watch(pdfProvider);
|
final pdf = ref.watch(documentRepositoryProvider);
|
||||||
final l = AppLocalizations.of(context);
|
final l = AppLocalizations.of(context);
|
||||||
final pageInfo = l.pageInfo(pdf.currentPage, pdf.pageCount);
|
final pageInfo = l.pageInfo(pdf.currentPage, pdf.pageCount);
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@ 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';
|
||||||
import 'package:pdf_signature/data/model/model.dart' as model;
|
import 'package:pdf_signature/domain/models/model.dart' as model;
|
||||||
|
|
||||||
import '../../../../data/services/export_providers.dart';
|
import '../../../../data/services/export_providers.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import 'image_editor_dialog.dart';
|
import 'image_editor_dialog.dart';
|
||||||
import '../../signature/widgets/signature_card.dart';
|
import '../../signature/widgets/signature_card.dart';
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ class _SignatureDrawerState extends ConsumerState<SignatureDrawer> {
|
||||||
final sig = ref.watch(signatureProvider);
|
final sig = ref.watch(signatureProvider);
|
||||||
final processed = ref.watch(processedSignatureImageProvider);
|
final processed = ref.watch(processedSignatureImageProvider);
|
||||||
final bytes = processed ?? sig.imageBytes;
|
final bytes = processed ?? sig.imageBytes;
|
||||||
final library = ref.watch(signatureLibraryProvider);
|
final library = ref.watch(signatureAssetRepositoryProvider);
|
||||||
final isExporting = ref.watch(exportingProvider);
|
final isExporting = ref.watch(exportingProvider);
|
||||||
final disabled = widget.disabled || isExporting;
|
final disabled = widget.disabled || isExporting;
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ class _SignatureDrawerState extends ConsumerState<SignatureDrawer> {
|
||||||
disabled: disabled,
|
disabled: disabled,
|
||||||
onDelete:
|
onDelete:
|
||||||
() => ref
|
() => ref
|
||||||
.read(signatureLibraryProvider.notifier)
|
.read(signatureAssetRepositoryProvider.notifier)
|
||||||
.remove(a.id),
|
.remove(a.id),
|
||||||
onAdjust: () async {
|
onAdjust: () async {
|
||||||
ref
|
ref
|
||||||
|
@ -151,10 +151,16 @@ class _SignatureDrawerState extends ConsumerState<SignatureDrawer> {
|
||||||
ref.read(signatureProvider).imageBytes;
|
ref.read(signatureProvider).imageBytes;
|
||||||
if (b != null) {
|
if (b != null) {
|
||||||
final id = ref
|
final id = ref
|
||||||
.read(signatureLibraryProvider.notifier)
|
.read(
|
||||||
|
signatureAssetRepositoryProvider
|
||||||
|
.notifier,
|
||||||
|
)
|
||||||
.add(b, name: 'image');
|
.add(b, name: 'image');
|
||||||
final asset = ref
|
final asset = ref
|
||||||
.read(signatureLibraryProvider.notifier)
|
.read(
|
||||||
|
signatureAssetRepositoryProvider
|
||||||
|
.notifier,
|
||||||
|
)
|
||||||
.byId(id);
|
.byId(id);
|
||||||
if (asset != null) {
|
if (asset != null) {
|
||||||
ref
|
ref
|
||||||
|
@ -179,10 +185,16 @@ class _SignatureDrawerState extends ConsumerState<SignatureDrawer> {
|
||||||
ref.read(signatureProvider).imageBytes;
|
ref.read(signatureProvider).imageBytes;
|
||||||
if (b != null) {
|
if (b != null) {
|
||||||
final id = ref
|
final id = ref
|
||||||
.read(signatureLibraryProvider.notifier)
|
.read(
|
||||||
|
signatureAssetRepositoryProvider
|
||||||
|
.notifier,
|
||||||
|
)
|
||||||
.add(b, name: 'drawing');
|
.add(b, name: 'drawing');
|
||||||
final asset = ref
|
final asset = ref
|
||||||
.read(signatureLibraryProvider.notifier)
|
.read(
|
||||||
|
signatureAssetRepositoryProvider
|
||||||
|
.notifier,
|
||||||
|
)
|
||||||
.byId(id);
|
.byId(id);
|
||||||
if (asset != null) {
|
if (asset != null) {
|
||||||
ref
|
ref
|
||||||
|
|
|
@ -4,10 +4,10 @@ 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';
|
||||||
|
|
||||||
import '../../../../data/model/model.dart';
|
import '../../../../domain/models/model.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import 'image_editor_dialog.dart';
|
import 'image_editor_dialog.dart';
|
||||||
import '../../signature/widgets/rotated_signature_image.dart';
|
import '../../signature/widgets/rotated_signature_image.dart';
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ class SignatureOverlay extends ConsumerWidget {
|
||||||
required this.rect,
|
required this.rect,
|
||||||
required this.sig,
|
required this.sig,
|
||||||
required this.pageNumber,
|
required this.pageNumber,
|
||||||
this.interactive = true,
|
|
||||||
this.placedIndex,
|
this.placedIndex,
|
||||||
this.onDragSignature,
|
this.onDragSignature,
|
||||||
this.onResizeSignature,
|
this.onResizeSignature,
|
||||||
|
@ -30,9 +29,8 @@ class SignatureOverlay extends ConsumerWidget {
|
||||||
|
|
||||||
final Size pageSize;
|
final Size pageSize;
|
||||||
final Rect rect;
|
final Rect rect;
|
||||||
final SignatureState sig;
|
final SignatureCard sig;
|
||||||
final int pageNumber;
|
final int pageNumber;
|
||||||
final bool interactive;
|
|
||||||
final int? placedIndex;
|
final int? placedIndex;
|
||||||
|
|
||||||
// Callbacks used by interactive overlay
|
// Callbacks used by interactive overlay
|
||||||
|
@ -75,7 +73,8 @@ class SignatureOverlay extends ConsumerWidget {
|
||||||
double scaleX,
|
double scaleX,
|
||||||
double scaleY,
|
double scaleY,
|
||||||
) {
|
) {
|
||||||
final selectedIdx = ref.read(pdfProvider).selectedPlacementIndex;
|
final selectedIdx =
|
||||||
|
ref.read(documentRepositoryProvider).selectedPlacementIndex;
|
||||||
final bool isPlaced = placedIndex != null;
|
final bool isPlaced = placedIndex != null;
|
||||||
final bool isSelected = isPlaced && selectedIdx == placedIndex;
|
final bool isSelected = isPlaced && selectedIdx == placedIndex;
|
||||||
final Color borderColor = isPlaced ? Colors.red : Colors.indigo;
|
final Color borderColor = isPlaced ? Colors.red : Colors.indigo;
|
||||||
|
@ -92,7 +91,7 @@ class SignatureOverlay extends ConsumerWidget {
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0.05 + math.min(0.25, (sig.contrast - 1.0).abs()),
|
0.05 + math.min(0.25, (sig.graphicAdjust.contrast - 1.0).abs()),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -210,7 +209,7 @@ class SignatureOverlay extends ConsumerWidget {
|
||||||
onClearActiveOverlay?.call();
|
onClearActiveOverlay?.call();
|
||||||
} else {
|
} else {
|
||||||
ref
|
ref
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.removePlacement(page: pageNumber, index: placedIndex);
|
.removePlacement(page: pageNumber, index: placedIndex);
|
||||||
}
|
}
|
||||||
} else if (choice == 'adjust') {
|
} else if (choice == 'adjust') {
|
||||||
|
@ -231,23 +230,24 @@ class _SignatureImage extends ConsumerWidget {
|
||||||
final bool interactive;
|
final bool interactive;
|
||||||
final int? placedIndex;
|
final int? placedIndex;
|
||||||
final int pageNumber;
|
final int pageNumber;
|
||||||
final SignatureState sig;
|
final SignatureCard sig;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
Uint8List? bytes;
|
Uint8List? bytes;
|
||||||
if (interactive) {
|
if (interactive) {
|
||||||
final processed = ref.watch(processedSignatureImageProvider);
|
final processed = ref.watch(processedSignatureImageProvider);
|
||||||
bytes = processed ?? sig.imageBytes;
|
bytes = processed ?? sig.asset.bytes;
|
||||||
} else if (placedIndex != null) {
|
} else if (placedIndex != null) {
|
||||||
final placementList = ref.read(pdfProvider).placementsByPage[pageNumber];
|
final placementList =
|
||||||
|
ref.read(documentRepositoryProvider).placementsByPage[pageNumber];
|
||||||
final placement =
|
final placement =
|
||||||
(placementList != null && placedIndex! < placementList.length)
|
(placementList != null && placedIndex! < placementList.length)
|
||||||
? placementList[placedIndex!]
|
? placementList[placedIndex!]
|
||||||
: null;
|
: null;
|
||||||
final imgId = (placement?.asset)?.id;
|
final imgId = (placement?.asset)?.id;
|
||||||
if (imgId != null && imgId.isNotEmpty) {
|
if (imgId != null && imgId.isNotEmpty) {
|
||||||
final lib = ref.watch(signatureLibraryProvider);
|
final lib = ref.watch(signatureAssetRepositoryProvider);
|
||||||
for (final a in lib) {
|
for (final a in lib) {
|
||||||
if (a.id == imgId) {
|
if (a.id == imgId) {
|
||||||
bytes = a.bytes;
|
bytes = a.bytes;
|
||||||
|
@ -255,7 +255,7 @@ class _SignatureImage extends ConsumerWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bytes ??= ref.read(processedSignatureImageProvider) ?? sig.imageBytes;
|
bytes ??= ref.read(processedSignatureImageProvider) ?? sig.asset.bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes == null) {
|
if (bytes == null) {
|
||||||
|
@ -271,9 +271,10 @@ class _SignatureImage extends ConsumerWidget {
|
||||||
// Use live rotation for interactive overlay; stored rotation for placed
|
// Use live rotation for interactive overlay; stored rotation for placed
|
||||||
double rotationDeg = 0.0;
|
double rotationDeg = 0.0;
|
||||||
if (interactive) {
|
if (interactive) {
|
||||||
rotationDeg = sig.rotation;
|
rotationDeg = sig.rotationDeg;
|
||||||
} else if (placedIndex != null) {
|
} else if (placedIndex != null) {
|
||||||
final placementList = ref.read(pdfProvider).placementsByPage[pageNumber];
|
final placementList =
|
||||||
|
ref.read(documentRepositoryProvider).placementsByPage[pageNumber];
|
||||||
if (placementList != null && placedIndex! < placementList.length) {
|
if (placementList != null && placedIndex! < placementList.length) {
|
||||||
rotationDeg = placementList[placedIndex!].rotationDeg;
|
rotationDeg = placementList[placedIndex!].rotationDeg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import 'signature_drag_data.dart';
|
import 'signature_drag_data.dart';
|
||||||
import 'rotated_signature_image.dart';
|
import 'rotated_signature_image.dart';
|
||||||
import 'package:pdf_signature/l10n/app_localizations.dart';
|
import 'package:pdf_signature/l10n/app_localizations.dart';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
|
|
||||||
class SignatureDragData {
|
class SignatureDragData {
|
||||||
final SignatureAsset? asset; // null means use current processed signature
|
final SignatureAsset? asset; // null means use current processed signature
|
||||||
|
|
|
@ -50,7 +50,9 @@ Future<void> handleDroppedFiles(
|
||||||
bytes = null;
|
bytes = null;
|
||||||
}
|
}
|
||||||
final String path = pdf.path ?? pdf.name;
|
final String path = pdf.path ?? pdf.name;
|
||||||
read(pdfProvider.notifier).openPicked(path: path, bytes: bytes);
|
read(
|
||||||
|
documentRepositoryProvider.notifier,
|
||||||
|
).openPicked(path: path, bytes: bytes);
|
||||||
read(signatureProvider.notifier).resetForNewPage();
|
read(signatureProvider.notifier).resetForNewPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +76,9 @@ class _WelcomeScreenState extends ConsumerState<WelcomeScreen> {
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
bytes = null;
|
bytes = null;
|
||||||
}
|
}
|
||||||
ref.read(pdfProvider.notifier).openPicked(path: file.path, bytes: bytes);
|
ref
|
||||||
|
.read(documentRepositoryProvider.notifier)
|
||||||
|
.openPicked(path: file.path, bytes: bytes);
|
||||||
ref.read(signatureProvider.notifier).resetForNewPage();
|
ref.read(signatureProvider.notifier).resetForNewPage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,11 @@ dependencies:
|
||||||
flutter_localized_locales: ^2.0.5
|
flutter_localized_locales: ^2.0.5
|
||||||
desktop_drop: ^0.5.0
|
desktop_drop: ^0.5.0
|
||||||
multi_split_view: ^3.6.1
|
multi_split_view: ^3.6.1
|
||||||
|
freezed_annotation: ^3.1.0
|
||||||
|
json_annotation: ^4.9.0
|
||||||
|
share_plus: ^11.1.0
|
||||||
|
logging: ^1.3.0
|
||||||
|
riverpod_annotation: ^2.6.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -61,6 +66,8 @@ dev_dependencies:
|
||||||
build_runner: ^2.4.12
|
build_runner: ^2.4.12
|
||||||
build: ^3.0.2
|
build: ^3.0.2
|
||||||
bdd_widget_test: ^2.0.1
|
bdd_widget_test: ^2.0.1
|
||||||
|
mocktail: ^1.0.4
|
||||||
|
freezed: ^3.0.0
|
||||||
custom_lint: ^0.7.6
|
custom_lint: ^0.7.6
|
||||||
riverpod_lint: ^2.6.5
|
riverpod_lint: ^2.6.5
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: a created signature card
|
/// Usage: a created signature card
|
||||||
|
@ -15,5 +15,5 @@ Future<void> aCreatedSignatureCard(WidgetTester tester) async {
|
||||||
bytes: Uint8List(100),
|
bytes: Uint8List(100),
|
||||||
name: 'Test Card',
|
name: 'Test Card',
|
||||||
);
|
);
|
||||||
container.read(signatureLibraryProvider.notifier).state = [asset];
|
container.read(signatureAssetRepositoryProvider.notifier).state = [asset];
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: a document is open and contains at least one signature placement
|
/// Usage: a document is open and contains at least one signature placement
|
||||||
|
@ -13,10 +13,10 @@ Future<void> aDocumentIsOpenAndContainsAtLeastOneSignaturePlacement(
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.openPicked(path: 'test.pdf', pageCount: 5);
|
.openPicked(path: 'test.pdf', pageCount: 5);
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: 1,
|
page: 1,
|
||||||
rect: Rect.fromLTWH(10, 10, 100, 50),
|
rect: Rect.fromLTWH(10, 10, 100, 50),
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: a document is open and contains multiple placed signature placements across pages
|
/// Usage: a document is open and contains multiple placed signature placements across pages
|
||||||
|
@ -14,24 +14,24 @@ aDocumentIsOpenAndContainsMultiplePlacedSignaturePlacementsAcrossPages(
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.openPicked(path: 'multi.pdf', pageCount: 5);
|
.openPicked(path: 'multi.pdf', pageCount: 5);
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: 1,
|
page: 1,
|
||||||
rect: Rect.fromLTWH(10, 10, 100, 50),
|
rect: Rect.fromLTWH(10, 10, 100, 50),
|
||||||
asset: SignatureAsset(id: 'sig1.png', bytes: Uint8List(0)),
|
asset: SignatureAsset(id: 'sig1.png', bytes: Uint8List(0)),
|
||||||
);
|
);
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: 2,
|
page: 2,
|
||||||
rect: Rect.fromLTWH(20, 20, 100, 50),
|
rect: Rect.fromLTWH(20, 20, 100, 50),
|
||||||
asset: SignatureAsset(id: 'sig2.png', bytes: Uint8List(0)),
|
asset: SignatureAsset(id: 'sig2.png', bytes: Uint8List(0)),
|
||||||
);
|
);
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: 3,
|
page: 3,
|
||||||
rect: Rect.fromLTWH(30, 30, 100, 50),
|
rect: Rect.fromLTWH(30, 30, 100, 50),
|
||||||
|
|
|
@ -10,7 +10,7 @@ Future<void> aDocumentIsOpenWithNoSignaturePlacementsPlaced(
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.openPicked(path: 'empty.pdf', pageCount: 5);
|
.openPicked(path: 'empty.pdf', pageCount: 5);
|
||||||
// No placements added
|
// No placements added
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,6 @@ import '_world.dart';
|
||||||
Future<void> aDocumentPageIsSelectedForSigning(WidgetTester tester) async {
|
Future<void> aDocumentPageIsSelectedForSigning(WidgetTester tester) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
container.read(pdfProvider.notifier).setSignedPage(1);
|
container.read(documentRepositoryProvider.notifier).setSignedPage(1);
|
||||||
container.read(pdfProvider.notifier).jumpTo(1);
|
container.read(documentRepositoryProvider.notifier).jumpTo(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,18 +2,23 @@ import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: a multi-page document is open
|
/// Usage: a multi-page document is open
|
||||||
Future<void> aMultipageDocumentIsOpen(WidgetTester tester) async {
|
Future<void> aMultipageDocumentIsOpen(WidgetTester tester) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
container.read(signatureLibraryProvider.notifier).state = [];
|
container.read(signatureAssetRepositoryProvider.notifier).state = [];
|
||||||
container.read(pdfProvider.notifier).state = PdfState.initial();
|
container.read(documentRepositoryProvider.notifier).state =
|
||||||
container.read(signatureProvider.notifier).state = SignatureState.initial();
|
Document.initial();
|
||||||
|
container.read(signatureCardProvider.notifier).state =
|
||||||
|
SignatureCard.initial();
|
||||||
|
container.read(currentRectProvider.notifier).state = null;
|
||||||
|
container.read(editingEnabledProvider.notifier).state = false;
|
||||||
|
container.read(aspectLockedProvider.notifier).state = false;
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.openPicked(path: 'mock.pdf', pageCount: 5);
|
.openPicked(path: 'mock.pdf', pageCount: 5);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,6 @@ Future<void> aSampleMultipageDocument5PagesIsAvailable(
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.openPicked(path: 'sample.pdf', pageCount: 5);
|
.openPicked(path: 'sample.pdf', pageCount: 5);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: a signature asset is created
|
/// Usage: a signature asset is created
|
||||||
|
@ -13,9 +13,9 @@ Future<void> aSignatureAssetIsCreated(WidgetTester tester) async {
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
|
|
||||||
// Ensure PDF is open
|
// Ensure PDF is open
|
||||||
if (!container.read(pdfProvider).loaded) {
|
if (!container.read(documentRepositoryProvider).loaded) {
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.openPicked(path: 'mock.pdf', pageCount: 5);
|
.openPicked(path: 'mock.pdf', pageCount: 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,12 +25,12 @@ Future<void> aSignatureAssetIsCreated(WidgetTester tester) async {
|
||||||
bytes: Uint8List(100),
|
bytes: Uint8List(100),
|
||||||
name: 'Test Asset',
|
name: 'Test Asset',
|
||||||
);
|
);
|
||||||
container.read(signatureLibraryProvider.notifier).state = [asset];
|
container.read(signatureAssetRepositoryProvider.notifier).state = [asset];
|
||||||
|
|
||||||
// Place it on the current page
|
// Place it on the current page
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: pdf.currentPage,
|
page: pdf.currentPage,
|
||||||
rect: Rect.fromLTWH(50, 50, 100, 50),
|
rect: Rect.fromLTWH(50, 50, 100, 50),
|
||||||
|
|
|
@ -1,21 +1,26 @@
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: a signature asset is loaded or drawn
|
/// Usage: a signature asset is loaded or drawn
|
||||||
Future<void> aSignatureAssetIsLoadedOrDrawn(WidgetTester tester) async {
|
Future<void> aSignatureAssetIsLoadedOrDrawn(WidgetTester tester) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
container.read(signatureLibraryProvider.notifier).state = [];
|
container.read(signatureAssetRepositoryProvider.notifier).state = [];
|
||||||
container.read(pdfProvider.notifier).state = PdfState.initial();
|
container.read(documentRepositoryProvider.notifier).state =
|
||||||
container.read(signatureProvider.notifier).state = SignatureState.initial();
|
Document.initial();
|
||||||
|
container.read(signatureCardProvider.notifier).state =
|
||||||
|
SignatureCard.initial();
|
||||||
|
container.read(currentRectProvider.notifier).state = null;
|
||||||
|
container.read(editingEnabledProvider.notifier).state = false;
|
||||||
|
container.read(aspectLockedProvider.notifier).state = false;
|
||||||
final bytes = Uint8List.fromList([1, 2, 3, 4, 5]);
|
final bytes = Uint8List.fromList([1, 2, 3, 4, 5]);
|
||||||
container
|
container
|
||||||
.read(signatureLibraryProvider.notifier)
|
.read(signatureAssetRepositoryProvider.notifier)
|
||||||
.add(bytes, name: 'test.png');
|
.add(bytes, name: 'test.png');
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: a signature asset is placed on the page
|
/// Usage: a signature asset is placed on the page
|
||||||
|
@ -13,31 +13,31 @@ Future<void> aSignatureAssetIsPlacedOnThePage(WidgetTester tester) async {
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
|
|
||||||
// Ensure PDF is open
|
// Ensure PDF is open
|
||||||
if (!container.read(pdfProvider).loaded) {
|
if (!container.read(documentRepositoryProvider).loaded) {
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.openPicked(path: 'mock.pdf', pageCount: 5);
|
.openPicked(path: 'mock.pdf', pageCount: 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get or create an asset
|
// Get or create an asset
|
||||||
var library = container.read(signatureLibraryProvider);
|
var library = container.read(signatureAssetRepositoryProvider);
|
||||||
SignatureAsset asset;
|
SignatureAsset asset;
|
||||||
if (library.isNotEmpty) {
|
if (library.isNotEmpty) {
|
||||||
asset = library.first;
|
asset = library.first;
|
||||||
} else {
|
} else {
|
||||||
final bytes = Uint8List.fromList([1, 2, 3, 4, 5]);
|
final bytes = Uint8List.fromList([1, 2, 3, 4, 5]);
|
||||||
final id = container
|
final id = container
|
||||||
.read(signatureLibraryProvider.notifier)
|
.read(signatureAssetRepositoryProvider.notifier)
|
||||||
.add(bytes, name: 'test.png');
|
.add(bytes, name: 'test.png');
|
||||||
asset = container
|
asset = container
|
||||||
.read(signatureLibraryProvider)
|
.read(signatureAssetRepositoryProvider)
|
||||||
.firstWhere((a) => a.id == id);
|
.firstWhere((a) => a.id == id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place it on the current page
|
// Place it on the current page
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: pdf.currentPage,
|
page: pdf.currentPage,
|
||||||
rect: Rect.fromLTWH(50, 50, 100, 50),
|
rect: Rect.fromLTWH(50, 50, 100, 50),
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: a signature asset is selected
|
/// Usage: a signature asset is selected
|
||||||
Future<void> aSignatureAssetIsSelected(WidgetTester tester) async {
|
Future<void> aSignatureAssetIsSelected(WidgetTester tester) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
var library = container.read(signatureLibraryProvider);
|
var library = container.read(signatureAssetRepositoryProvider);
|
||||||
|
|
||||||
// If library is empty, add a dummy asset
|
// If library is empty, add a dummy asset
|
||||||
if (library.isEmpty) {
|
if (library.isEmpty) {
|
||||||
|
@ -18,9 +18,9 @@ Future<void> aSignatureAssetIsSelected(WidgetTester tester) async {
|
||||||
bytes: Uint8List(100),
|
bytes: Uint8List(100),
|
||||||
name: 'Selected Asset',
|
name: 'Selected Asset',
|
||||||
);
|
);
|
||||||
container.read(signatureLibraryProvider.notifier).state = [asset];
|
container.read(signatureAssetRepositoryProvider.notifier).state = [asset];
|
||||||
// Re-read the library
|
// Re-read the library
|
||||||
library = container.read(signatureLibraryProvider);
|
library = container.read(signatureAssetRepositoryProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: a signature asset loaded or drawn is wrapped in a signature card
|
/// Usage: a signature asset loaded or drawn is wrapped in a signature card
|
||||||
|
@ -13,11 +13,16 @@ Future<void> aSignatureAssetLoadedOrDrawnIsWrappedInASignatureCard(
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
container.read(signatureLibraryProvider.notifier).state = [];
|
container.read(signatureAssetRepositoryProvider.notifier).state = [];
|
||||||
container.read(pdfProvider.notifier).state = PdfState.initial();
|
container.read(documentRepositoryProvider.notifier).state =
|
||||||
container.read(signatureProvider.notifier).state = SignatureState.initial();
|
Document.initial();
|
||||||
|
container.read(signatureCardProvider.notifier).state =
|
||||||
|
SignatureCard.initial();
|
||||||
|
container.read(currentRectProvider.notifier).state = null;
|
||||||
|
container.read(editingEnabledProvider.notifier).state = false;
|
||||||
|
container.read(aspectLockedProvider.notifier).state = false;
|
||||||
final bytes = Uint8List.fromList([1, 2, 3, 4, 5]);
|
final bytes = Uint8List.fromList([1, 2, 3, 4, 5]);
|
||||||
container
|
container
|
||||||
.read(signatureLibraryProvider.notifier)
|
.read(signatureAssetRepositoryProvider.notifier)
|
||||||
.add(bytes, name: 'test.png');
|
.add(bytes, name: 'test.png');
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ Future<void> aSignaturePlacementAppearsOnThePageBasedOnTheSignatureCard(
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container!;
|
final container = TestWorld.container!;
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
||||||
expect(
|
expect(
|
||||||
placements.isNotEmpty,
|
placements.isNotEmpty,
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: a signature placement is placed on page {2}
|
/// Usage: a signature placement is placed on page {2}
|
||||||
|
@ -15,7 +15,7 @@ Future<void> aSignaturePlacementIsPlacedOnPage(
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
final page = param1.toInt();
|
final page = param1.toInt();
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: page,
|
page: page,
|
||||||
rect: Rect.fromLTWH(20, 20, 100, 50),
|
rect: Rect.fromLTWH(20, 20, 100, 50),
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: a signature placement is placed with a position and size relative to the page
|
/// Usage: a signature placement is placed with a position and size relative to the page
|
||||||
|
@ -12,9 +12,9 @@ Future<void> aSignaturePlacementIsPlacedWithAPositionAndSizeRelativeToThePage(
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: pdf.currentPage,
|
page: pdf.currentPage,
|
||||||
rect: Rect.fromLTWH(50, 50, 200, 100),
|
rect: Rect.fromLTWH(50, 50, 200, 100),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: adjusting one instance does not affect the others
|
/// Usage: adjusting one instance does not affect the others
|
||||||
|
@ -9,13 +9,19 @@ Future<void> adjustingOneInstanceDoesNotAffectTheOthers(
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
final before = container.read(pdfProvider.notifier).placementsOn(2);
|
final before = container
|
||||||
|
.read(documentRepositoryProvider.notifier)
|
||||||
|
.placementsOn(2);
|
||||||
expect(before.length, greaterThanOrEqualTo(2));
|
expect(before.length, greaterThanOrEqualTo(2));
|
||||||
final modified = before[0].rect.translate(5, 0).inflate(3);
|
final modified = before[0].rect.translate(5, 0).inflate(3);
|
||||||
container.read(pdfProvider.notifier).removePlacement(page: 2, index: 0);
|
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
|
.removePlacement(page: 2, index: 0);
|
||||||
|
container
|
||||||
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(page: 2, rect: modified, asset: before[0].asset);
|
.addPlacement(page: 2, rect: modified, asset: before[0].asset);
|
||||||
final after = container.read(pdfProvider.notifier).placementsOn(2);
|
final after = container
|
||||||
|
.read(documentRepositoryProvider.notifier)
|
||||||
|
.placementsOn(2);
|
||||||
expect(after.any((p) => p.rect == before[1].rect), isTrue);
|
expect(after.any((p) => p.rect == before[1].rect), isTrue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ Future<void> adjustingOneOfTheSignaturePlacementsDoesNotAffectTheOthers(
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container!;
|
final container = TestWorld.container!;
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
final placements =
|
final placements =
|
||||||
pdf.placementsByPage.values.expand((list) => list).toList();
|
pdf.placementsByPage.values.expand((list) => list).toList();
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ allPlacedSignaturePlacementsAppearOnTheirCorrespondingPagesInTheOutput(
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
final totalPlacements = pdf.placementsByPage.values.fold(
|
final totalPlacements = pdf.placementsByPage.values.fold(
|
||||||
0,
|
0,
|
||||||
(sum, list) => sum + list.length,
|
(sum, list) => sum + list.length,
|
||||||
|
|
|
@ -8,7 +8,7 @@ Future<void> bothSignaturePlacementsAreShownOnTheirRespectivePages(
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
expect(pdf.placementsByPage[1], isNotEmpty);
|
expect(pdf.placementsByPage[1], isNotEmpty);
|
||||||
expect(pdf.placementsByPage[3], isNotEmpty);
|
expect(pdf.placementsByPage[3], isNotEmpty);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'dart:ui';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: dragging or resizing one does not change the other
|
/// Usage: dragging or resizing one does not change the other
|
||||||
|
@ -10,20 +10,26 @@ Future<void> draggingOrResizingOneDoesNotChangeTheOther(
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
final list = container.read(pdfProvider.notifier).placementsOn(1);
|
final list = container
|
||||||
|
.read(documentRepositoryProvider.notifier)
|
||||||
|
.placementsOn(1);
|
||||||
expect(list.length, greaterThanOrEqualTo(2));
|
expect(list.length, greaterThanOrEqualTo(2));
|
||||||
final before = List<Rect>.from(list.take(2).map((p) => p.rect));
|
final before = List<Rect>.from(list.take(2).map((p) => p.rect));
|
||||||
// Simulate changing the first only
|
// Simulate changing the first only
|
||||||
final changed = before[0].inflate(5);
|
final changed = before[0].inflate(5);
|
||||||
container.read(pdfProvider.notifier).removePlacement(page: 1, index: 0);
|
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
|
.removePlacement(page: 1, index: 0);
|
||||||
|
container
|
||||||
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: 1,
|
page: 1,
|
||||||
rect: changed,
|
rect: changed,
|
||||||
asset: list[1].asset,
|
asset: list[1].asset,
|
||||||
rotationDeg: list[1].rotationDeg,
|
rotationDeg: list[1].rotationDeg,
|
||||||
);
|
);
|
||||||
final after = container.read(pdfProvider.notifier).placementsOn(1);
|
final after = container
|
||||||
|
.read(documentRepositoryProvider.notifier)
|
||||||
|
.placementsOn(1);
|
||||||
expect(after.any((p) => p.rect == before[1]), isTrue);
|
expect(after.any((p) => p.rect == before[1]), isTrue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ Future<void> eachSignaturePlacementCanBeDraggedAndResizedIndependently(
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
||||||
expect(placements.length, greaterThan(1));
|
expect(placements.length, greaterThan(1));
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ Future<void> identicalSignatureInstancesAppearInEachLocation(
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
final state = container.read(pdfProvider);
|
final state = container.read(documentRepositoryProvider);
|
||||||
final p2 = state.placementsByPage[2] ?? const [];
|
final p2 = state.placementsByPage[2] ?? const [];
|
||||||
final p4 = state.placementsByPage[4] ?? const [];
|
final p4 = state.placementsByPage[4] ?? const [];
|
||||||
expect(p2.length, greaterThanOrEqualTo(2));
|
expect(p2.length, greaterThanOrEqualTo(2));
|
||||||
|
|
|
@ -8,7 +8,7 @@ Future<void> identicalSignaturePlacementsAppearInEachLocation(
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container!;
|
final container = TestWorld.container!;
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
final allPlacements =
|
final allPlacements =
|
||||||
pdf.placementsByPage.values.expand((list) => list).toList();
|
pdf.placementsByPage.values.expand((list) => list).toList();
|
||||||
final assetIds = allPlacements.map((p) => p.asset.id).toSet();
|
final assetIds = allPlacements.map((p) => p.asset.id).toSet();
|
||||||
|
|
|
@ -8,7 +8,7 @@ Future<void> onlyTheSelectedSignaturePlacementIsRemoved(
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
||||||
expect(placements.length, 2); // Started with 3, removed 1, should have 2
|
expect(placements.length, 2); // Started with 3, removed 1, should have 2
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,5 +10,5 @@ Future<void> pageBecomesVisibleInTheScrollArea(
|
||||||
) async {
|
) async {
|
||||||
final page = param1.toInt();
|
final page = param1.toInt();
|
||||||
final c = TestWorld.container ?? ProviderContainer();
|
final c = TestWorld.container ?? ProviderContainer();
|
||||||
expect(c.read(pdfProvider).currentPage, page);
|
expect(c.read(documentRepositoryProvider).currentPage, page);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,5 +7,5 @@ import '_world.dart';
|
||||||
Future<void> pageIsDisplayed(WidgetTester tester, num param1) async {
|
Future<void> pageIsDisplayed(WidgetTester tester, num param1) async {
|
||||||
final expected = param1.toInt();
|
final expected = param1.toInt();
|
||||||
final c = TestWorld.container ?? ProviderContainer();
|
final c = TestWorld.container ?? ProviderContainer();
|
||||||
expect(c.read(pdfProvider).currentPage, expected);
|
expect(c.read(documentRepositoryProvider).currentPage, expected);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import '_world.dart';
|
||||||
/// Usage: resize to fit within bounding box
|
/// Usage: resize to fit within bounding box
|
||||||
Future<void> resizeToFitWithinBoundingBox(WidgetTester tester) async {
|
Future<void> resizeToFitWithinBoundingBox(WidgetTester tester) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
|
|
||||||
if (pdf.selectedPlacementIndex != null) {
|
if (pdf.selectedPlacementIndex != null) {
|
||||||
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
||||||
|
|
|
@ -9,7 +9,7 @@ Future<void> signaturePlacementOccursOnTheSelectedPage(
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
|
|
||||||
// Check that there's at least one placement on the current page
|
// Check that there's at least one placement on the current page
|
||||||
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: the app attempts to load the asset
|
/// Usage: the app attempts to load the asset
|
||||||
|
@ -8,6 +8,6 @@ Future<void> theAppAttemptsToLoadTheAsset(WidgetTester tester) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
// Simulate attempting to load an asset - for now just ensure library is accessible
|
// Simulate attempting to load an asset - for now just ensure library is accessible
|
||||||
final library = container.read(signatureLibraryProvider);
|
final library = container.read(signatureAssetRepositoryProvider);
|
||||||
expect(library, isNotNull);
|
expect(library, isNotNull);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: the asset is loaded and shown as a signature asset
|
/// Usage: the asset is loaded and shown as a signature asset
|
||||||
|
@ -7,7 +7,7 @@ Future<void> theAssetIsLoadedAndShownAsASignatureAsset(
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container!;
|
final container = TestWorld.container!;
|
||||||
final library = container.read(signatureLibraryProvider);
|
final library = container.read(signatureAssetRepositoryProvider);
|
||||||
expect(
|
expect(
|
||||||
library.isNotEmpty,
|
library.isNotEmpty,
|
||||||
true,
|
true,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: the asset is loaded and shown as a signature card
|
/// Usage: the asset is loaded and shown as a signature card
|
||||||
|
@ -7,7 +7,7 @@ Future<void> theAssetIsLoadedAndShownAsASignatureCard(
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container!;
|
final container = TestWorld.container!;
|
||||||
final library = container.read(signatureLibraryProvider);
|
final library = container.read(signatureAssetRepositoryProvider);
|
||||||
expect(
|
expect(
|
||||||
library.isNotEmpty,
|
library.isNotEmpty,
|
||||||
true,
|
true,
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: the asset is not added to the document
|
/// Usage: the asset is not added to the document
|
||||||
Future<void> theAssetIsNotAddedToTheDocument(WidgetTester tester) async {
|
Future<void> theAssetIsNotAddedToTheDocument(WidgetTester tester) async {
|
||||||
final container = TestWorld.container!;
|
final container = TestWorld.container!;
|
||||||
final library = container.read(signatureLibraryProvider);
|
final library = container.read(signatureAssetRepositoryProvider);
|
||||||
expect(
|
expect(
|
||||||
library.isEmpty,
|
library.isEmpty,
|
||||||
true,
|
true,
|
||||||
|
|
|
@ -7,7 +7,7 @@ import '_world.dart';
|
||||||
Future<void> theDocumentIsOpen(WidgetTester tester) async {
|
Future<void> theDocumentIsOpen(WidgetTester tester) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
expect(pdf.loaded, isTrue);
|
expect(pdf.loaded, isTrue);
|
||||||
expect(pdf.pageCount, greaterThan(0));
|
expect(pdf.pageCount, greaterThan(0));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,6 @@ import '_world.dart';
|
||||||
/// Usage: the first page is displayed
|
/// Usage: the first page is displayed
|
||||||
Future<void> theFirstPageIsDisplayed(WidgetTester tester) async {
|
Future<void> theFirstPageIsDisplayed(WidgetTester tester) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
expect(pdf.currentPage, 1);
|
expect(pdf.currentPage, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ import '_world.dart';
|
||||||
Future<void> theGoToInputCannotBeUsed(WidgetTester tester) async {
|
Future<void> theGoToInputCannotBeUsed(WidgetTester tester) async {
|
||||||
final c = TestWorld.container ?? ProviderContainer();
|
final c = TestWorld.container ?? ProviderContainer();
|
||||||
// Not loaded, currentPage should remain 1 even after jump attempt
|
// Not loaded, currentPage should remain 1 even after jump attempt
|
||||||
expect(c.read(pdfProvider).loaded, isFalse);
|
expect(c.read(documentRepositoryProvider).loaded, isFalse);
|
||||||
final before = c.read(pdfProvider).currentPage;
|
final before = c.read(documentRepositoryProvider).currentPage;
|
||||||
c.read(pdfProvider.notifier).jumpTo(3);
|
c.read(documentRepositoryProvider.notifier).jumpTo(3);
|
||||||
final after = c.read(pdfProvider).currentPage;
|
final after = c.read(documentRepositoryProvider).currentPage;
|
||||||
expect(before, equals(after));
|
expect(before, equals(after));
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import '_world.dart';
|
||||||
Future<void> theLastPageIsDisplayedPage(WidgetTester tester, num param1) async {
|
Future<void> theLastPageIsDisplayedPage(WidgetTester tester, num param1) async {
|
||||||
final last = param1.toInt();
|
final last = param1.toInt();
|
||||||
final c = TestWorld.container ?? ProviderContainer();
|
final c = TestWorld.container ?? ProviderContainer();
|
||||||
final pdf = c.read(pdfProvider);
|
final pdf = c.read(documentRepositoryProvider);
|
||||||
expect(pdf.pageCount, last);
|
expect(pdf.pageCount, last);
|
||||||
expect(pdf.currentPage, last);
|
expect(pdf.currentPage, last);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,5 +10,5 @@ Future<void> theLeftPagesOverviewHighlightsPage(
|
||||||
) async {
|
) async {
|
||||||
final n = param1.toInt();
|
final n = param1.toInt();
|
||||||
final c = TestWorld.container ?? ProviderContainer();
|
final c = TestWorld.container ?? ProviderContainer();
|
||||||
expect(c.read(pdfProvider).currentPage, n);
|
expect(c.read(documentRepositoryProvider).currentPage, n);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ Future<void> theOtherSignaturePlacementsRemainUnchanged(
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container!;
|
final container = TestWorld.container!;
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
||||||
expect(placements.length, 2); // Should have 2 remaining after deleting 1
|
expect(placements.length, 2); // Should have 2 remaining after deleting 1
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ Future<void> thePageLabelShowsPageOf(
|
||||||
final current = param1.toInt();
|
final current = param1.toInt();
|
||||||
final total = param2.toInt();
|
final total = param2.toInt();
|
||||||
final c = TestWorld.container ?? ProviderContainer();
|
final c = TestWorld.container ?? ProviderContainer();
|
||||||
final pdf = c.read(pdfProvider);
|
final pdf = c.read(documentRepositoryProvider);
|
||||||
expect(pdf.currentPage, current);
|
expect(pdf.currentPage, current);
|
||||||
expect(pdf.pageCount, total);
|
expect(pdf.pageCount, total);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ Future<void> theSignaturePlacementIsStampedAtTheExactPdfPageCoordinatesAndSize(
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
|
|
||||||
final pdfState = container.read(pdfProvider);
|
final pdfState = container.read(documentRepositoryProvider);
|
||||||
|
|
||||||
// Verify PDF is loaded
|
// Verify PDF is loaded
|
||||||
expect(pdfState.loaded, isTrue, reason: 'PDF should be loaded');
|
expect(pdfState.loaded, isTrue, reason: 'PDF should be loaded');
|
||||||
|
|
|
@ -10,7 +10,7 @@ Future<void> theSignaturePlacementOnPageIsShownOnPage(
|
||||||
num param2,
|
num param2,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
final page = param1.toInt();
|
final page = param1.toInt();
|
||||||
expect(pdf.placementsByPage[page], isNotEmpty);
|
expect(pdf.placementsByPage[page], isNotEmpty);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ Future<void> theSignaturePlacementOnPageRemains(
|
||||||
num param1,
|
num param1,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
final page = param1.toInt();
|
final page = param1.toInt();
|
||||||
expect(pdf.placementsByPage[page], isNotEmpty);
|
expect(pdf.placementsByPage[page], isNotEmpty);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ Future<void> theSignaturePlacementRemainsWithinThePageArea(
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
|
|
||||||
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
||||||
for (final placement in placements) {
|
for (final placement in placements) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ Future<void> theSignaturePlacementRotatesAroundItsCenterInRealTime(
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
|
|
||||||
if (pdf.selectedPlacementIndex != null) {
|
if (pdf.selectedPlacementIndex != null) {
|
||||||
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
||||||
|
|
|
@ -10,7 +10,7 @@ Future<void> theSignaturePlacementsAppearOnTheCorrespondingPageInTheOutput(
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
|
|
||||||
final pdfState = container.read(pdfProvider);
|
final pdfState = container.read(documentRepositoryProvider);
|
||||||
|
|
||||||
// Verify that export was successful
|
// Verify that export was successful
|
||||||
expect(
|
expect(
|
||||||
|
|
|
@ -6,7 +6,7 @@ import '_world.dart';
|
||||||
/// Usage: the size and position update in real time
|
/// Usage: the size and position update in real time
|
||||||
Future<void> theSizeAndPositionUpdateInRealTime(WidgetTester tester) async {
|
Future<void> theSizeAndPositionUpdateInRealTime(WidgetTester tester) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
|
|
||||||
if (pdf.selectedPlacementIndex != null) {
|
if (pdf.selectedPlacementIndex != null) {
|
||||||
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
||||||
|
|
|
@ -8,7 +8,7 @@ import '_world.dart';
|
||||||
Future<void> theUserAttemptsToSave(WidgetTester tester) async {
|
Future<void> theUserAttemptsToSave(WidgetTester tester) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
final sig = container.read(signatureProvider);
|
final sig = container.read(signatureProvider);
|
||||||
// Simulate save attempt: since rect is null, mark flag
|
// Simulate save attempt: since rect is null, mark flag
|
||||||
if (!pdf.loaded || sig.rect == null) {
|
if (!pdf.loaded || sig.rect == null) {
|
||||||
|
|
|
@ -6,11 +6,11 @@ import '_world.dart';
|
||||||
/// Usage: the user can move to the next or previous page
|
/// Usage: the user can move to the next or previous page
|
||||||
Future<void> theUserCanMoveToTheNextOrPreviousPage(WidgetTester tester) async {
|
Future<void> theUserCanMoveToTheNextOrPreviousPage(WidgetTester tester) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
final pdfN = container.read(pdfProvider.notifier);
|
final pdfN = container.read(documentRepositoryProvider.notifier);
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
expect(pdf.currentPage, 1);
|
expect(pdf.currentPage, 1);
|
||||||
pdfN.jumpTo(2);
|
pdfN.jumpTo(2);
|
||||||
expect(container.read(pdfProvider).currentPage, 2);
|
expect(container.read(documentRepositoryProvider).currentPage, 2);
|
||||||
pdfN.jumpTo(1);
|
pdfN.jumpTo(1);
|
||||||
expect(container.read(pdfProvider).currentPage, 1);
|
expect(container.read(documentRepositoryProvider).currentPage, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: the user chooses a image file as a signature asset
|
/// Usage: the user chooses a image file as a signature asset
|
||||||
|
@ -12,6 +12,6 @@ Future<void> theUserChoosesAImageFileAsASignatureAsset(
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
final bytes = Uint8List.fromList([1, 2, 3, 4, 5]);
|
final bytes = Uint8List.fromList([1, 2, 3, 4, 5]);
|
||||||
container
|
container
|
||||||
.read(signatureLibraryProvider.notifier)
|
.read(signatureAssetRepositoryProvider.notifier)
|
||||||
.add(bytes, name: 'chosen.png');
|
.add(bytes, name: 'chosen.png');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: the user chooses a signature asset to created a signature card
|
/// Usage: the user chooses a signature asset to created a signature card
|
||||||
|
@ -12,6 +12,6 @@ Future<void> theUserChoosesASignatureAssetToCreatedASignatureCard(
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
final bytes = Uint8List.fromList([1, 2, 3, 4, 5]);
|
final bytes = Uint8List.fromList([1, 2, 3, 4, 5]);
|
||||||
container
|
container
|
||||||
.read(signatureLibraryProvider.notifier)
|
.read(signatureAssetRepositoryProvider.notifier)
|
||||||
.add(bytes, name: 'card.png');
|
.add(bytes, name: 'card.png');
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ Future<void> theUserClicksTheGoToApplyButton(WidgetTester tester) async {
|
||||||
final c = TestWorld.container ?? ProviderContainer();
|
final c = TestWorld.container ?? ProviderContainer();
|
||||||
final pending = TestWorld.pendingGoTo;
|
final pending = TestWorld.pendingGoTo;
|
||||||
if (pending != null) {
|
if (pending != null) {
|
||||||
c.read(pdfProvider.notifier).jumpTo(pending);
|
c.read(documentRepositoryProvider.notifier).jumpTo(pending);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,6 @@ Future<void> theUserClicksTheThumbnailForPage(
|
||||||
) async {
|
) async {
|
||||||
final page = param1.toInt();
|
final page = param1.toInt();
|
||||||
final c = TestWorld.container ?? ProviderContainer();
|
final c = TestWorld.container ?? ProviderContainer();
|
||||||
c.read(pdfProvider.notifier).jumpTo(page);
|
c.read(documentRepositoryProvider.notifier).jumpTo(page);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,9 @@ Future<void> theUserDeletesOneSelectedSignaturePlacement(
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
if (pdf.selectedPlacementIndex == null) {
|
if (pdf.selectedPlacementIndex == null) {
|
||||||
container.read(pdfProvider.notifier).selectPlacement(0);
|
container.read(documentRepositoryProvider.notifier).selectPlacement(0);
|
||||||
}
|
}
|
||||||
container.read(pdfProvider.notifier).deleteSelectedPlacement();
|
container.read(documentRepositoryProvider.notifier).deleteSelectedPlacement();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,8 @@ Future<void> theUserDragsHandlesToResizeAndDragsToReposition(
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
final pdfN = container.read(pdfProvider.notifier);
|
final pdfN = container.read(documentRepositoryProvider.notifier);
|
||||||
|
|
||||||
if (pdf.selectedPlacementIndex != null) {
|
if (pdf.selectedPlacementIndex != null) {
|
||||||
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
final placements = pdf.placementsByPage[pdf.currentPage] ?? [];
|
||||||
|
|
|
@ -3,8 +3,8 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: the user drags it on the page of the document to place signature placements in multiple locations in the document
|
/// Usage: the user drags it on the page of the document to place signature placements in multiple locations in the document
|
||||||
|
@ -13,7 +13,7 @@ theUserDragsItOnThePageOfTheDocumentToPlaceSignaturePlacementsInMultipleLocation
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container!;
|
final container = TestWorld.container!;
|
||||||
final lib = container.read(signatureLibraryProvider);
|
final lib = container.read(signatureAssetRepositoryProvider);
|
||||||
final asset =
|
final asset =
|
||||||
lib.isNotEmpty
|
lib.isNotEmpty
|
||||||
? lib.first
|
? lib.first
|
||||||
|
@ -24,28 +24,28 @@ theUserDragsItOnThePageOfTheDocumentToPlaceSignaturePlacementsInMultipleLocation
|
||||||
);
|
);
|
||||||
|
|
||||||
// Ensure PDF is open
|
// Ensure PDF is open
|
||||||
if (!container.read(pdfProvider).loaded) {
|
if (!container.read(documentRepositoryProvider).loaded) {
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.openPicked(path: 'mock.pdf', pageCount: 5);
|
.openPicked(path: 'mock.pdf', pageCount: 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: 1,
|
page: 1,
|
||||||
rect: Rect.fromLTWH(10, 10, 100, 50),
|
rect: Rect.fromLTWH(10, 10, 100, 50),
|
||||||
asset: asset,
|
asset: asset,
|
||||||
);
|
);
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: 2,
|
page: 2,
|
||||||
rect: Rect.fromLTWH(20, 20, 100, 50),
|
rect: Rect.fromLTWH(20, 20, 100, 50),
|
||||||
asset: asset,
|
asset: asset,
|
||||||
);
|
);
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: 3,
|
page: 3,
|
||||||
rect: Rect.fromLTWH(30, 30, 100, 50),
|
rect: Rect.fromLTWH(30, 30, 100, 50),
|
||||||
|
|
|
@ -3,8 +3,8 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: the user drags this signature card on the page of the document to place a signature placement
|
/// Usage: the user drags this signature card on the page of the document to place a signature placement
|
||||||
|
@ -16,31 +16,31 @@ theUserDragsThisSignatureCardOnThePageOfTheDocumentToPlaceASignaturePlacement(
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
|
|
||||||
// Ensure PDF is open
|
// Ensure PDF is open
|
||||||
if (!container.read(pdfProvider).loaded) {
|
if (!container.read(documentRepositoryProvider).loaded) {
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.openPicked(path: 'mock.pdf', pageCount: 5);
|
.openPicked(path: 'mock.pdf', pageCount: 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get or create an asset
|
// Get or create an asset
|
||||||
var library = container.read(signatureLibraryProvider);
|
var library = container.read(signatureAssetRepositoryProvider);
|
||||||
SignatureAsset asset;
|
SignatureAsset asset;
|
||||||
if (library.isNotEmpty) {
|
if (library.isNotEmpty) {
|
||||||
asset = library.first;
|
asset = library.first;
|
||||||
} else {
|
} else {
|
||||||
final bytes = Uint8List.fromList([1, 2, 3, 4, 5]);
|
final bytes = Uint8List.fromList([1, 2, 3, 4, 5]);
|
||||||
final id = container
|
final id = container
|
||||||
.read(signatureLibraryProvider.notifier)
|
.read(signatureAssetRepositoryProvider.notifier)
|
||||||
.add(bytes, name: 'placement.png');
|
.add(bytes, name: 'placement.png');
|
||||||
asset = container
|
asset = container
|
||||||
.read(signatureLibraryProvider)
|
.read(signatureAssetRepositoryProvider)
|
||||||
.firstWhere((a) => a.id == id);
|
.firstWhere((a) => a.id == id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place it on the current page
|
// Place it on the current page
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: pdf.currentPage,
|
page: pdf.currentPage,
|
||||||
rect: Rect.fromLTWH(100, 100, 100, 50),
|
rect: Rect.fromLTWH(100, 100, 100, 50),
|
||||||
|
|
|
@ -10,6 +10,6 @@ Future<void> theUserEntersIntoTheGoToInputAndAppliesIt(
|
||||||
) async {
|
) async {
|
||||||
final value = param1.toInt();
|
final value = param1.toInt();
|
||||||
final c = TestWorld.container ?? ProviderContainer();
|
final c = TestWorld.container ?? ProviderContainer();
|
||||||
c.read(pdfProvider.notifier).jumpTo(value);
|
c.read(documentRepositoryProvider.notifier).jumpTo(value);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,6 @@ import '_world.dart';
|
||||||
Future<void> theUserJumpsToPage(WidgetTester tester, num param1) async {
|
Future<void> theUserJumpsToPage(WidgetTester tester, num param1) async {
|
||||||
final page = param1.toInt();
|
final page = param1.toInt();
|
||||||
final c = TestWorld.container ?? ProviderContainer();
|
final c = TestWorld.container ?? ProviderContainer();
|
||||||
c.read(pdfProvider.notifier).jumpTo(page);
|
c.read(documentRepositoryProvider.notifier).jumpTo(page);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: the user navigates to page {5} and places another signature placement
|
/// Usage: the user navigates to page {5} and places another signature placement
|
||||||
|
@ -14,9 +14,9 @@ Future<void> theUserNavigatesToPageAndPlacesAnotherSignaturePlacement(
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
final page = param1.toInt();
|
final page = param1.toInt();
|
||||||
container.read(pdfProvider.notifier).jumpTo(page);
|
container.read(documentRepositoryProvider.notifier).jumpTo(page);
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: page,
|
page: page,
|
||||||
rect: Rect.fromLTWH(40, 40, 100, 50),
|
rect: Rect.fromLTWH(40, 40, 100, 50),
|
||||||
|
|
|
@ -3,8 +3,8 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: the user places a signature placement from asset <second_asset> on page <second_page>
|
/// Usage: the user places a signature placement from asset <second_asset> on page <second_page>
|
||||||
|
@ -15,14 +15,14 @@ Future<void> theUserPlacesASignaturePlacementFromAssetOnPage(
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
final library = container.read(signatureLibraryProvider);
|
final library = container.read(signatureAssetRepositoryProvider);
|
||||||
var asset = library.where((a) => a.name == assetName).firstOrNull;
|
var asset = library.where((a) => a.name == assetName).firstOrNull;
|
||||||
if (asset == null) {
|
if (asset == null) {
|
||||||
// add dummy asset
|
// add dummy asset
|
||||||
final id = container
|
final id = container
|
||||||
.read(signatureLibraryProvider.notifier)
|
.read(signatureAssetRepositoryProvider.notifier)
|
||||||
.add(Uint8List(0), name: assetName);
|
.add(Uint8List(0), name: assetName);
|
||||||
final updatedLibrary = container.read(signatureLibraryProvider);
|
final updatedLibrary = container.read(signatureAssetRepositoryProvider);
|
||||||
asset = updatedLibrary.firstWhere(
|
asset = updatedLibrary.firstWhere(
|
||||||
(a) => a.id == id,
|
(a) => a.id == id,
|
||||||
orElse:
|
orElse:
|
||||||
|
@ -30,7 +30,7 @@ Future<void> theUserPlacesASignaturePlacementFromAssetOnPage(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: page,
|
page: page,
|
||||||
rect: Rect.fromLTWH(10, 10, 50, 50),
|
rect: Rect.fromLTWH(10, 10, 50, 50),
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: the user places a signature placement on page {1}
|
/// Usage: the user places a signature placement on page {1}
|
||||||
|
@ -15,7 +15,7 @@ Future<void> theUserPlacesASignaturePlacementOnPage(
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
final page = param1.toInt();
|
final page = param1.toInt();
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: page,
|
page: page,
|
||||||
rect: Rect.fromLTWH(20, 20, 100, 50),
|
rect: Rect.fromLTWH(20, 20, 100, 50),
|
||||||
|
|
|
@ -10,7 +10,7 @@ Future<void> theUserPlacesItInMultipleLocationsInTheDocument(
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
final notifier = container.read(pdfProvider.notifier);
|
final notifier = container.read(documentRepositoryProvider.notifier);
|
||||||
// Always open a fresh doc to avoid state bleed between scenarios
|
// Always open a fresh doc to avoid state bleed between scenarios
|
||||||
notifier.openPicked(path: 'mock.pdf', pageCount: 6);
|
notifier.openPicked(path: 'mock.pdf', pageCount: 6);
|
||||||
// Place two on page 2 and one on page 4
|
// Place two on page 2 and one on page 4
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: the user places two signature placements on the same page
|
/// Usage: the user places two signature placements on the same page
|
||||||
|
@ -12,10 +12,10 @@ Future<void> theUserPlacesTwoSignaturePlacementsOnTheSamePage(
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
final page = pdf.currentPage;
|
final page = pdf.currentPage;
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: page,
|
page: page,
|
||||||
rect: Rect.fromLTWH(10, 10, 100, 50),
|
rect: Rect.fromLTWH(10, 10, 100, 50),
|
||||||
|
@ -26,7 +26,7 @@ Future<void> theUserPlacesTwoSignaturePlacementsOnTheSamePage(
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: page,
|
page: page,
|
||||||
rect: Rect.fromLTWH(120, 10, 100, 50),
|
rect: Rect.fromLTWH(120, 10, 100, 50),
|
||||||
|
|
|
@ -12,7 +12,7 @@ Future<void> theUserSavesexportsTheDocument(WidgetTester tester) async {
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
|
|
||||||
// Ensure state looks exportable
|
// Ensure state looks exportable
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
final sig = container.read(signatureProvider);
|
final sig = container.read(signatureProvider);
|
||||||
expect(pdf.loaded, isTrue, reason: 'PDF must be loaded before export');
|
expect(pdf.loaded, isTrue, reason: 'PDF must be loaded before export');
|
||||||
// Check if there are placements
|
// Check if there are placements
|
||||||
|
|
|
@ -11,9 +11,9 @@ Future<void> theUserSelects(WidgetTester tester, dynamic file) async {
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
// Mark page for signing to enable signature ops
|
// Mark page for signing to enable signature ops
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.openPicked(path: 'mock.pdf', pageCount: 1);
|
.openPicked(path: 'mock.pdf', pageCount: 1);
|
||||||
container.read(pdfProvider.notifier).setSignedPage(1);
|
container.read(documentRepositoryProvider.notifier).setSignedPage(1);
|
||||||
// For invalid/unsupported/empty selections we do NOT set image bytes.
|
// For invalid/unsupported/empty selections we do NOT set image bytes.
|
||||||
// This simulates a failed load and keeps rect null.
|
// This simulates a failed load and keeps rect null.
|
||||||
final token = file.toString();
|
final token = file.toString();
|
||||||
|
|
|
@ -11,6 +11,6 @@ Future<void> theUserTypesIntoTheGoToInputAndPressesEnter(
|
||||||
final target = param1.toInt();
|
final target = param1.toInt();
|
||||||
final c = TestWorld.container ?? ProviderContainer();
|
final c = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = c;
|
TestWorld.container = c;
|
||||||
c.read(pdfProvider.notifier).jumpTo(target);
|
c.read(documentRepositoryProvider.notifier).jumpTo(target);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ import '_world.dart';
|
||||||
/// Usage: the user uses rotate controls
|
/// Usage: the user uses rotate controls
|
||||||
Future<void> theUserUsesRotateControls(WidgetTester tester) async {
|
Future<void> theUserUsesRotateControls(WidgetTester tester) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
final pdfN = container.read(pdfProvider.notifier);
|
final pdfN = container.read(documentRepositoryProvider.notifier);
|
||||||
|
|
||||||
if (pdf.selectedPlacementIndex != null) {
|
if (pdf.selectedPlacementIndex != null) {
|
||||||
// Rotate the selected placement by 45 degrees
|
// Rotate the selected placement by 45 degrees
|
||||||
|
|
|
@ -3,9 +3,9 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_library_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_asset_repository.dart';
|
||||||
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
import 'package:pdf_signature/data/repositories/signature_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import '_world.dart';
|
import '_world.dart';
|
||||||
|
|
||||||
/// Usage: three signature placements are placed on the current page
|
/// Usage: three signature placements are placed on the current page
|
||||||
|
@ -14,14 +14,19 @@ Future<void> threeSignaturePlacementsArePlacedOnTheCurrentPage(
|
||||||
) async {
|
) async {
|
||||||
final container = TestWorld.container ?? ProviderContainer();
|
final container = TestWorld.container ?? ProviderContainer();
|
||||||
TestWorld.container = container;
|
TestWorld.container = container;
|
||||||
container.read(signatureLibraryProvider.notifier).state = [];
|
container.read(signatureAssetRepositoryProvider.notifier).state = [];
|
||||||
container.read(pdfProvider.notifier).state = PdfState.initial();
|
container.read(documentRepositoryProvider.notifier).state =
|
||||||
container.read(signatureProvider.notifier).state = SignatureState.initial();
|
Document.initial();
|
||||||
|
container.read(signatureCardProvider.notifier).state =
|
||||||
|
SignatureCard.initial();
|
||||||
|
container.read(currentRectProvider.notifier).state = null;
|
||||||
|
container.read(editingEnabledProvider.notifier).state = false;
|
||||||
|
container.read(aspectLockedProvider.notifier).state = false;
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.openPicked(path: 'mock.pdf', pageCount: 5);
|
.openPicked(path: 'mock.pdf', pageCount: 5);
|
||||||
final pdfN = container.read(pdfProvider.notifier);
|
final pdfN = container.read(documentRepositoryProvider.notifier);
|
||||||
final pdf = container.read(pdfProvider);
|
final pdf = container.read(documentRepositoryProvider);
|
||||||
final page = pdf.currentPage;
|
final page = pdf.currentPage;
|
||||||
pdfN.addPlacement(
|
pdfN.addPlacement(
|
||||||
page: page,
|
page: page,
|
||||||
|
|
|
@ -26,8 +26,8 @@ void main() {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
ProviderScope(
|
ProviderScope(
|
||||||
overrides: [
|
overrides: [
|
||||||
pdfProvider.overrideWith(
|
documentRepositoryProvider.overrideWith(
|
||||||
(ref) => PdfController()..openPicked(path: 'test.pdf'),
|
(ref) => DocumentStateNotifier()..openPicked(path: 'test.pdf'),
|
||||||
),
|
),
|
||||||
signatureProvider.overrideWith(
|
signatureProvider.overrideWith(
|
||||||
(ref) => SignatureController()..placeDefaultRect(),
|
(ref) => SignatureController()..placeDefaultRect(),
|
||||||
|
|
|
@ -15,8 +15,8 @@ Future<void> pumpWithOpenPdf(WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
ProviderScope(
|
ProviderScope(
|
||||||
overrides: [
|
overrides: [
|
||||||
pdfProvider.overrideWith(
|
documentRepositoryProvider.overrideWith(
|
||||||
(ref) => PdfController()..openPicked(path: 'test.pdf'),
|
(ref) => DocumentStateNotifier()..openPicked(path: 'test.pdf'),
|
||||||
),
|
),
|
||||||
useMockViewerProvider.overrideWith((ref) => true),
|
useMockViewerProvider.overrideWith((ref) => true),
|
||||||
// Continuous mode is always-on; no page view override needed
|
// Continuous mode is always-on; no page view override needed
|
||||||
|
@ -49,8 +49,8 @@ Future<void> pumpWithOpenPdfAndSig(WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
ProviderScope(
|
ProviderScope(
|
||||||
overrides: [
|
overrides: [
|
||||||
pdfProvider.overrideWith(
|
documentRepositoryProvider.overrideWith(
|
||||||
(ref) => PdfController()..openPicked(path: 'test.pdf'),
|
(ref) => DocumentStateNotifier()..openPicked(path: 'test.pdf'),
|
||||||
),
|
),
|
||||||
signatureProvider.overrideWith(
|
signatureProvider.overrideWith(
|
||||||
(ref) =>
|
(ref) =>
|
||||||
|
|
|
@ -4,14 +4,14 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
import 'package:pdf_signature/ui/features/pdf/widgets/pdf_screen.dart';
|
import 'package:pdf_signature/ui/features/pdf/widgets/pdf_screen.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
import 'package:pdf_signature/data/services/export_providers.dart';
|
import 'package:pdf_signature/data/services/export_providers.dart';
|
||||||
import 'package:pdf_signature/l10n/app_localizations.dart';
|
import 'package:pdf_signature/l10n/app_localizations.dart';
|
||||||
|
|
||||||
class _TestPdfController extends PdfController {
|
class _TestPdfController extends DocumentStateNotifier {
|
||||||
_TestPdfController() : super() {
|
_TestPdfController() : super() {
|
||||||
// Start with a loaded multi-page doc, page 1 of 5
|
// Start with a loaded multi-page doc, page 1 of 5
|
||||||
state = PdfState.initial().copyWith(
|
state = Document.initial().copyWith(
|
||||||
loaded: true,
|
loaded: true,
|
||||||
pageCount: 5,
|
pageCount: 5,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
|
@ -27,7 +27,9 @@ void main() {
|
||||||
ProviderScope(
|
ProviderScope(
|
||||||
overrides: [
|
overrides: [
|
||||||
useMockViewerProvider.overrideWithValue(true),
|
useMockViewerProvider.overrideWithValue(true),
|
||||||
pdfProvider.overrideWith((ref) => _TestPdfController()),
|
documentRepositoryProvider.overrideWith(
|
||||||
|
(ref) => _TestPdfController(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||||
|
|
|
@ -6,11 +6,11 @@ import 'package:pdf_signature/ui/features/pdf/widgets/pdf_page_area.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/services/export_providers.dart';
|
import 'package:pdf_signature/data/services/export_providers.dart';
|
||||||
import 'package:pdf_signature/l10n/app_localizations.dart';
|
import 'package:pdf_signature/l10n/app_localizations.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
|
|
||||||
class _TestPdfController extends PdfController {
|
class _TestPdfController extends DocumentStateNotifier {
|
||||||
_TestPdfController() : super() {
|
_TestPdfController() : super() {
|
||||||
state = PdfState.initial().copyWith(
|
state = Document.initial().copyWith(
|
||||||
loaded: true,
|
loaded: true,
|
||||||
pageCount: 6,
|
pageCount: 6,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
|
@ -30,7 +30,7 @@ void main() {
|
||||||
overrides: [
|
overrides: [
|
||||||
useMockViewerProvider.overrideWithValue(true),
|
useMockViewerProvider.overrideWithValue(true),
|
||||||
// Continuous mode is always-on; no page view override needed
|
// Continuous mode is always-on; no page view override needed
|
||||||
pdfProvider.overrideWith((ref) => ctrl),
|
documentRepositoryProvider.overrideWith((ref) => ctrl),
|
||||||
],
|
],
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||||
|
|
|
@ -6,11 +6,11 @@ import 'package:pdf_signature/ui/features/pdf/widgets/pdf_page_area.dart';
|
||||||
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
import 'package:pdf_signature/data/repositories/pdf_repository.dart';
|
||||||
import 'package:pdf_signature/data/services/export_providers.dart';
|
import 'package:pdf_signature/data/services/export_providers.dart';
|
||||||
import 'package:pdf_signature/l10n/app_localizations.dart';
|
import 'package:pdf_signature/l10n/app_localizations.dart';
|
||||||
import 'package:pdf_signature/data/model/model.dart';
|
import 'package:pdf_signature/domain/models/model.dart';
|
||||||
|
|
||||||
class _TestPdfController extends PdfController {
|
class _TestPdfController extends DocumentStateNotifier {
|
||||||
_TestPdfController() : super() {
|
_TestPdfController() : super() {
|
||||||
state = PdfState.initial().copyWith(
|
state = Document.initial().copyWith(
|
||||||
loaded: true,
|
loaded: true,
|
||||||
pageCount: 6,
|
pageCount: 6,
|
||||||
currentPage: 2,
|
currentPage: 2,
|
||||||
|
@ -29,7 +29,7 @@ void main() {
|
||||||
overrides: [
|
overrides: [
|
||||||
useMockViewerProvider.overrideWithValue(true),
|
useMockViewerProvider.overrideWithValue(true),
|
||||||
// Continuous mode is always-on; no page view override needed
|
// Continuous mode is always-on; no page view override needed
|
||||||
pdfProvider.overrideWith((ref) => ctrl),
|
documentRepositoryProvider.overrideWith((ref) => ctrl),
|
||||||
],
|
],
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||||
|
|
|
@ -53,10 +53,10 @@ void main() {
|
||||||
await tester.pumpWidget(buildHarness(width: 480));
|
await tester.pumpWidget(buildHarness(width: 480));
|
||||||
|
|
||||||
// Open sample and add a normalized placement to page 1
|
// Open sample and add a normalized placement to page 1
|
||||||
container.read(pdfProvider.notifier).openSample();
|
container.read(documentRepositoryProvider.notifier).openSample();
|
||||||
// One placement at (25% x, 50% y), size 10% x 10%
|
// One placement at (25% x, 50% y), size 10% x 10%
|
||||||
container
|
container
|
||||||
.read(pdfProvider.notifier)
|
.read(documentRepositoryProvider.notifier)
|
||||||
.addPlacement(
|
.addPlacement(
|
||||||
page: 1,
|
page: 1,
|
||||||
rect: const Rect.fromLTWH(0.25, 0.50, 0.10, 0.10),
|
rect: const Rect.fromLTWH(0.25, 0.50, 0.10, 0.10),
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue