diff --git a/AGENTS.md b/AGENTS.md index 4ba5a70..bda2cf6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,5 +8,5 @@ Additionally read relevant files depends on task. * read [`FRs.md`](docs/FRs.md) * If want to modify code (implement or test) of `ViewModel`, `View` of MVVM (UI widget) (files at `lib/ui/features/*/widgets/*`) * read [`wireframe.md`](docs/wireframe.md), [`NFRs.md`](docs/NFRs.md), `test/features/*.feature` -* If want to modify code (implement or test) of non-View e.g. `Model`, services... +* If want to modify code (implement or test) of non-View e.g. `Model`, repositories, services... * read `test/features/*.feature`, [`NFRs.md`](docs/NFRs.md) diff --git a/docs/meta-arch.md b/docs/meta-arch.md index 5c43048..84c8846 100644 --- a/docs/meta-arch.md +++ b/docs/meta-arch.md @@ -60,7 +60,9 @@ But with slight modifications. * `integration_test/` for integration tests. They should be volatile to follow UI layout changes. Some rule of thumb: -* `Provider` only placed at `/lib/data/repositories/` or `/lib/data/services/` to provide data source. +* global provider + * `RepositoryProvider` only placed in `/lib/data/repositories/`, provide data to `/lib/ui`. + * `lib/data/services/*` should be stateless, and should only accessible by `Repository`. ## Abstraction diff --git a/integration_test/export_flow_test.dart b/integration_test/export_flow_test.dart index 8f370ff..f564f26 100644 --- a/integration_test/export_flow_test.dart +++ b/integration_test/export_flow_test.dart @@ -8,8 +8,8 @@ import 'package:image/image.dart' as img; import 'package:pdf_signature/data/services/export_service.dart'; import 'package:pdf_signature/data/services/export_providers.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/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/ui/features/pdf/widgets/pdf_screen.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; @@ -36,7 +36,7 @@ void main() { (ref) => DocumentStateNotifier()..openPicked(path: 'test.pdf'), ), signatureProvider.overrideWith( - (ref) => SignatureController()..placeDefaultRect(), + (ref) => SignatureCardStateNotifier()..placeDefaultRect(), ), useMockViewerProvider.overrideWith((ref) => true), exportServiceProvider.overrideWith((_) => fake), diff --git a/lib/app.dart b/lib/app.dart index aee5bb4..7452577 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -3,9 +3,9 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_localized_locales/flutter_localized_locales.dart'; import 'package:pdf_signature/l10n/app_localizations.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/document_repository.dart'; import 'package:pdf_signature/ui/features/welcome/widgets/welcome_screen.dart'; -import 'data/services/preferences_providers.dart'; +import 'data/repositories/preferences_repository.dart'; import 'package:pdf_signature/ui/features/preferences/widgets/settings_screen.dart'; class MyApp extends StatelessWidget { diff --git a/lib/data/repositories/pdf_repository.dart b/lib/data/repositories/document_repository.dart similarity index 84% rename from lib/data/repositories/pdf_repository.dart rename to lib/data/repositories/document_repository.dart index 73f2c9b..ad0a38f 100644 --- a/lib/data/repositories/pdf_repository.dart +++ b/lib/data/repositories/document_repository.dart @@ -1,12 +1,15 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:pdf_signature/data/services/export_service.dart'; import '../../domain/models/model.dart'; class DocumentStateNotifier extends StateNotifier { DocumentStateNotifier() : super(Document.initial()); + final ExportService _service = ExportService(); + @visibleForTesting void openSample() { state = state.copyWith( @@ -57,7 +60,7 @@ class DocumentStateNotifier extends StateNotifier { list.add( SignaturePlacement( rect: rect, - asset: asset ?? SignatureAsset(id: '', bytes: Uint8List(0)), + asset: asset ?? SignatureAsset(bytes: Uint8List(0)), rotationDeg: rotationDeg, ), ); @@ -121,14 +124,29 @@ class DocumentStateNotifier extends StateNotifier { ); } - // NOTE: Programmatic reassignment of images has been removed. - // Convenience to get asset for a placement SignatureAsset? assetOfPlacement({required int page, required int index}) { final list = state.placementsByPage[page] ?? const []; if (index < 0 || index >= list.length) return null; return list[index].asset; } + + Future exportDocument({ + required String outputPath, + required Size uiPageSize, + required Uint8List? signatureImageBytes, + }) async { + if (!state.loaded || state.pickedPdfBytes == null) return; + final bytes = await _service.exportSignedPdfFromBytes( + srcBytes: state.pickedPdfBytes!, + uiPageSize: uiPageSize, + signatureImageBytes: signatureImageBytes, + placementsByPage: state.placementsByPage, + ); + if (bytes == null) return; + _service.saveBytesToFile(bytes: bytes, outputPath: outputPath); + // await + } } final documentRepositoryProvider = diff --git a/lib/data/services/preferences_providers.dart b/lib/data/repositories/preferences_repository.dart similarity index 80% rename from lib/data/services/preferences_providers.dart rename to lib/data/repositories/preferences_repository.dart index f893d84..da0a6bf 100644 --- a/lib/data/services/preferences_providers.dart +++ b/lib/data/repositories/preferences_repository.dart @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; import 'package:flutter_localized_locales/flutter_localized_locales.dart'; +import 'package:pdf_signature/domain/models/preferences.dart'; // Helpers to work with BCP-47 language tags String toLanguageTag(Locale loc) { @@ -27,6 +28,7 @@ Set _supportedTags() { // Keys const _kTheme = 'theme'; // 'light'|'dark'|'system' +const _kThemeColor = 'theme_color'; // 'blue'|'green'|'red'|'purple' const _kLanguage = 'language'; // BCP-47 tag like 'en', 'zh-TW', 'es' const _kPageView = 'page_view'; // now only 'continuous' const _kExportDpi = 'export_dpi'; // double, allowed: 96,144,200,300 @@ -63,34 +65,9 @@ String _normalizeLanguageTag(String tag) { return tags.contains('en') ? 'en' : tags.first; } -class PreferencesState { - final String theme; // 'light' | 'dark' | 'system' - final String language; // 'en' | 'zh-TW' | 'es' - final String pageView; // only 'continuous' - final double exportDpi; // 96.0 | 144.0 | 200.0 | 300.0 - const PreferencesState({ - required this.theme, - required this.language, - required this.pageView, - required this.exportDpi, - }); - - PreferencesState copyWith({ - String? theme, - String? language, - String? pageView, - double? exportDpi, - }) => PreferencesState( - theme: theme ?? this.theme, - language: language ?? this.language, - pageView: pageView ?? this.pageView, - exportDpi: exportDpi ?? this.exportDpi, - ); -} - -class PreferencesNotifier extends StateNotifier { +class PreferencesStateNotifier extends StateNotifier { final SharedPreferences prefs; - PreferencesNotifier(this.prefs) + PreferencesStateNotifier(this.prefs) : super( PreferencesState( theme: prefs.getString(_kTheme) ?? 'system', @@ -99,8 +76,8 @@ class PreferencesNotifier extends StateNotifier { WidgetsBinding.instance.platformDispatcher.locale .toLanguageTag(), ), - pageView: prefs.getString(_kPageView) ?? 'continuous', exportDpi: _readDpi(prefs), + theme_color: prefs.getString(_kThemeColor) ?? 'blue', ), ) { // normalize language to supported/fallback @@ -125,11 +102,6 @@ class PreferencesNotifier extends StateNotifier { state = state.copyWith(language: normalized); prefs.setString(_kLanguage, normalized); } - final pageViewValid = {'continuous'}; - if (!pageViewValid.contains(state.pageView)) { - state = state.copyWith(pageView: 'continuous'); - prefs.setString(_kPageView, 'continuous'); - } // Ensure DPI is one of allowed values const allowed = [96.0, 144.0, 200.0, 300.0]; if (!allowed.contains(state.exportDpi)) { @@ -158,8 +130,8 @@ class PreferencesNotifier extends StateNotifier { state = PreferencesState( theme: 'system', language: normalized, - pageView: 'continuous', exportDpi: 144.0, + theme_color: '', ); await prefs.setString(_kTheme, 'system'); await prefs.setString(_kLanguage, normalized); @@ -167,13 +139,6 @@ class PreferencesNotifier extends StateNotifier { await prefs.setDouble(_kExportDpi, 144.0); } - Future setPageView(String pageView) async { - final valid = {'continuous'}; - if (!valid.contains(pageView)) return; - state = state.copyWith(pageView: pageView); - await prefs.setString(_kPageView, pageView); - } - Future setExportDpi(double dpi) async { const allowed = [96.0, 144.0, 200.0, 300.0]; if (!allowed.contains(dpi)) return; @@ -189,8 +154,8 @@ final sharedPreferencesProvider = FutureProvider(( return p; }); -final preferencesProvider = - StateNotifierProvider((ref) { +final preferencesRepositoryProvider = + StateNotifierProvider((ref) { // In tests, you can override sharedPreferencesProvider final prefs = ref .watch(sharedPreferencesProvider) @@ -198,14 +163,14 @@ final preferencesProvider = data: (p) => p, orElse: () => throw StateError('SharedPreferences not ready'), ); - return PreferencesNotifier(prefs); + return PreferencesStateNotifier(prefs); }); // pageViewModeProvider removed; the app always runs in continuous mode. /// Derive the active ThemeMode based on preference and platform brightness final themeModeProvider = Provider((ref) { - final prefs = ref.watch(preferencesProvider); + final prefs = ref.watch(preferencesRepositoryProvider); switch (prefs.theme) { case 'light': return ThemeMode.light; @@ -218,7 +183,7 @@ final themeModeProvider = Provider((ref) { }); final localeProvider = Provider((ref) { - final prefs = ref.watch(preferencesProvider); + final prefs = ref.watch(preferencesRepositoryProvider); final supported = _supportedTags(); // Return explicit Locale for supported ones; if not supported, null to follow device if (supported.contains(prefs.language)) { diff --git a/lib/data/repositories/signature_asset_repository.dart b/lib/data/repositories/signature_asset_repository.dart index fd405fd..de530e7 100644 --- a/lib/data/repositories/signature_asset_repository.dart +++ b/lib/data/repositories/signature_asset_repository.dart @@ -6,25 +6,15 @@ import 'package:pdf_signature/domain/models/model.dart'; class SignatureAssetRepository extends StateNotifier> { SignatureAssetRepository() : super(const []); - String add(Uint8List bytes, {String? name}) { + void add(Uint8List bytes, {String? name}) { // Always add a new asset (allow duplicates). This lets users create multiple cards // even when loading the same image repeatedly for different adjustments/usages. - if (bytes.isEmpty) return ''; - final id = DateTime.now().microsecondsSinceEpoch.toString(); - state = List.of(state) - ..add(SignatureAsset(id: id, bytes: bytes, name: name)); - return id; + if (bytes.isEmpty) return; + state = List.of(state)..add(SignatureAsset(bytes: bytes, name: name)); } - void remove(String id) { - state = state.where((a) => a.id != id).toList(growable: false); - } - - SignatureAsset? byId(String id) { - for (final a in state) { - if (a.id == id) return a; - } - return null; + void remove(SignatureAsset asset) { + state = state.where((a) => a != asset).toList(growable: false); } } diff --git a/lib/data/repositories/signature_card_repository.dart b/lib/data/repositories/signature_card_repository.dart new file mode 100644 index 0000000..7c43b3c --- /dev/null +++ b/lib/data/repositories/signature_card_repository.dart @@ -0,0 +1,45 @@ +import 'dart:typed_data'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:image/image.dart' as img; +import '../../domain/models/model.dart'; + +class SignatureCardStateNotifier extends StateNotifier> { + SignatureCardStateNotifier() : super(const []); + + add({required SignatureAsset asset, double rotationDeg = 0.0}) { + state = List.of(state) + ..add(SignatureCard(asset: asset, rotationDeg: rotationDeg)); + } + + void update({ + required SignatureCard card, + double? rotationDeg, + GraphicAdjust? graphicAdjust, + }) { + final list = List.of(state); + for (var i = 0; i < list.length; i++) { + final c = list[i]; + if (c == card) { + list[i] = c.copyWith( + rotationDeg: rotationDeg ?? c.rotationDeg, + graphicAdjust: graphicAdjust ?? c.graphicAdjust, + ); + state = list; + return; + } + } + } + + void remove(SignatureCard card) { + state = state.where((c) => c != card).toList(growable: false); + } + + void clearAll() { + state = const []; + } +} + +final signatureCardProvider = + StateNotifierProvider>( + (ref) => SignatureCardStateNotifier(), + ); diff --git a/lib/data/repositories/signature_repository.dart b/lib/data/repositories/signature_repository.dart deleted file mode 100644 index cee68c9..0000000 --- a/lib/data/repositories/signature_repository.dart +++ /dev/null @@ -1,374 +0,0 @@ -import 'dart:math' as math; -import 'dart:math'; -import 'dart:typed_data'; -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:image/image.dart' as img; -import 'package:pdf_signature/l10n/app_localizations.dart'; - -import '../../domain/models/model.dart'; -import 'pdf_repository.dart'; - -class SignatureController extends StateNotifier { - final Ref ref; - SignatureController(this.ref) : super(SignatureCard.initial()); - static const Size pageSize = Size(400, 560); - - void resetForNewPage() { - state = SignatureCard.initial(); - ref.read(currentRectProvider.notifier).setRect(null); - ref.read(editingEnabledProvider.notifier).set(false); - } - - @visibleForTesting - void placeDefaultRect() { - final w = 120.0, h = 60.0; - final rand = Random(); - // Generate a center within 10%..90% of each axis to reduce off-screen risk - final cx = pageSize.width * (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); - r = _clampRectToPage(r); - ref.read(currentRectProvider.notifier).setRect(r); - ref.read(editingEnabledProvider.notifier).set(true); - } - - void loadSample() { - final w = 120.0, h = 60.0; - ref - .read(currentRectProvider.notifier) - .setRect( - Rect.fromCenter( - center: Offset(pageSize.width / 2, pageSize.height * 0.75), - width: w, - height: h, - ), - ); - ref.read(editingEnabledProvider.notifier).set(true); - } - - void setInvalidSelected(BuildContext context) { - // Fallback message without localization to keep core logic testable - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - Localizations.of( - context, - AppLocalizations, - )!.invalidOrUnsupportedFile, - ), - ), - ); - } - - void drag(Offset delta) { - final currentRect = ref.read(currentRectProvider); - if (currentRect == null || !ref.read(editingEnabledProvider)) return; - final moved = currentRect.shift(delta); - ref.read(currentRectProvider.notifier).setRect(_clampRectToPage(moved)); - } - - void resize(Offset delta) { - final currentRect = ref.read(currentRectProvider); - if (currentRect == null || !ref.read(editingEnabledProvider)) return; - final r = currentRect; - double newW = r.width + delta.dx; - double newH = r.height + delta.dy; - if (ref.read(aspectLockedProvider)) { - final aspect = r.width / r.height; - // Keep ratio based on the dominant proportional delta - final dxRel = (delta.dx / r.width).abs(); - final dyRel = (delta.dy / r.height).abs(); - if (dxRel >= dyRel) { - newW = newW.clamp(20.0, double.infinity); - newH = newW / aspect; - } else { - newH = newH.clamp(20.0, double.infinity); - newW = newH * aspect; - } - // Scale down to fit within page bounds while preserving ratio - final scaleW = pageSize.width / newW; - final scaleH = pageSize.height / newH; - final scale = math.min(1.0, math.min(scaleW, scaleH)); - newW *= scale; - newH *= scale; - // Ensure minimum size of 20x20, scaling up proportionally if needed - final minScale = math.max(1.0, math.max(20.0 / newW, 20.0 / newH)); - newW *= minScale; - newH *= minScale; - Rect resized = Rect.fromLTWH(r.left, r.top, newW, newH); - resized = _clampRectPositionToPage(resized); - ref.read(currentRectProvider.notifier).setRect(resized); - return; - } - // Unlocked aspect: clamp each dimension independently - newW = newW.clamp(20.0, pageSize.width); - newH = newH.clamp(20.0, pageSize.height); - Rect resized = Rect.fromLTWH(r.left, r.top, newW, newH); - resized = _clampRectToPage(resized); - ref.read(currentRectProvider.notifier).setRect(resized); - } - - Rect _clampRectToPage(Rect r) { - // Ensure size never exceeds page bounds first, to avoid invalid clamp ranges - final double w = r.width.clamp(20.0, pageSize.width); - final double h = r.height.clamp(20.0, pageSize.height); - final double left = r.left.clamp(0.0, pageSize.width - w); - final double top = r.top.clamp(0.0, pageSize.height - h); - return Rect.fromLTWH(left, top, w, h); - } - - Rect _clampRectPositionToPage(Rect r) { - final double left = r.left.clamp(0.0, pageSize.width - r.width); - final double top = r.top.clamp(0.0, pageSize.height - r.height); - return Rect.fromLTWH(left, top, r.width, r.height); - } - - void toggleAspect(bool v) => ref.read(aspectLockedProvider.notifier).set(v); - void setBgRemoval(bool v) => - state = state.copyWith( - graphicAdjust: state.graphicAdjust.copyWith(bgRemoval: v), - ); - 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( - center: Offset(pageSize.width / 2, pageSize.height * 0.75), - width: 140, - height: 70, - ), - ); - ref.read(editingEnabledProvider.notifier).set(true); - } - } - - void setImageBytes(Uint8List bytes) { - final newAsset = SignatureAsset(id: 'drawn', bytes: bytes); - state = state.copyWith(asset: newAsset); - if (ref.read(currentRectProvider) == null) { - placeDefaultRect(); - } - ref.read(editingEnabledProvider.notifier).set(true); - } - - // Select image from the shared signature library - void setImageFromLibrary({required SignatureAsset asset}) { - state = state.copyWith(asset: asset); - if (ref.read(currentRectProvider) == null) { - placeDefaultRect(); - } - ref.read(editingEnabledProvider.notifier).set(true); - } - - void clearImage() { - 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}) { - Rect r = Rect.fromCenter(center: center, width: width, height: height); - r = _clampRectToPage(r); - 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. - // Stores the placement rect in UI-space (SignatureController.pageSize units). - // Returns the Rect placed, or null if no rect to confirm. - Rect? confirmCurrentSignature(WidgetRef ref) { - final r = ref.read(currentRectProvider); - if (r == null) return null; - // Place onto the current page - final pdf = ref.read(documentRepositoryProvider); - if (!pdf.loaded) return null; - ref - .read(documentRepositoryProvider.notifier) - .addPlacement( - page: pdf.currentPage, - rect: r, - asset: state.asset, - rotationDeg: state.rotationDeg, - ); - // Newly placed index is the last one on the page - final idx = - (ref - .read(documentRepositoryProvider) - .placementsByPage[pdf.currentPage] - ?.length ?? - 1) - - 1; - // Auto-select the newly placed item so the red box appears - if (idx >= 0) { - ref.read(documentRepositoryProvider.notifier).selectPlacement(idx); - } - // Freeze editing: keep rect for preview but disable interaction - ref.read(editingEnabledProvider.notifier).set(false); - return r; - } - - // Test/helper variant: confirm using a ProviderContainer instead of WidgetRef. - // Useful in widget tests where obtaining a WidgetRef is not straightforward. - @visibleForTesting - Rect? confirmCurrentSignatureWithContainer(ProviderContainer container) { - final r = container.read(currentRectProvider); - if (r == null) return null; - final pdf = container.read(documentRepositoryProvider); - if (!pdf.loaded) return null; - container - .read(documentRepositoryProvider.notifier) - .addPlacement( - page: pdf.currentPage, - rect: r, - asset: state.asset, - rotationDeg: state.rotationDeg, - ); - final idx = - (container - .read(documentRepositoryProvider) - .placementsByPage[pdf.currentPage] - ?.length ?? - 1) - - 1; - // Auto-select the newly placed item so the red box appears - if (idx >= 0) { - container.read(documentRepositoryProvider.notifier).selectPlacement(idx); - } - // Freeze editing: keep rect for preview but disable interaction - container.read(editingEnabledProvider.notifier).set(false); - return r; - } - - // Remove the active overlay (draft or confirmed preview) but keep image settings intact - void clearActiveOverlay() { - ref.read(currentRectProvider.notifier).setRect(null); - ref.read(editingEnabledProvider.notifier).set(false); - } -} - -final signatureCardProvider = - StateNotifierProvider( - (ref) => SignatureController(ref), - ); - -final currentRectProvider = StateNotifierProvider( - (ref) => RectNotifier(), -); - -class RectNotifier extends StateNotifier { - RectNotifier() : super(null); - - void setRect(Rect? r) => state = r; -} - -final editingEnabledProvider = StateNotifierProvider( - (ref) => BoolNotifier(false), -); - -class BoolNotifier extends StateNotifier { - BoolNotifier(bool initial) : super(initial); - - void set(bool v) => state = v; -} - -final aspectLockedProvider = StateNotifierProvider( - (ref) => BoolNotifier(false), -); - -/// Derived provider that returns processed signature image bytes according to -/// current adjustment settings (contrast/brightness) and background removal. -/// Returns null if no image is loaded. The output is a PNG to preserve alpha. -final processedSignatureImageProvider = Provider((ref) { - final SignatureAsset asset = ref.watch( - signatureCardProvider.select((s) => s.asset), - ); - final double contrast = ref.watch( - signatureCardProvider.select((s) => s.graphicAdjust.contrast), - ); - final double brightness = ref.watch( - signatureCardProvider.select((s) => s.graphicAdjust.brightness), - ); - final bool bgRemoval = ref.watch( - signatureCardProvider.select((s) => s.graphicAdjust.bgRemoval), - ); - - Uint8List? bytes = asset.bytes; - if (bytes.isEmpty) return null; - - // Decode (supports PNG/JPEG, etc.) - final decoded = img.decodeImage(bytes); - if (decoded == null) return bytes; - - // Work on a copy and ensure an alpha channel is present (RGBA) - var out = decoded.clone(); - if (out.hasPalette || !out.hasAlpha) { - // Force truecolor RGBA image so per-pixel alpha writes take effect - out = out.convert(numChannels: 4); - } - - // Parameters - // Rotation is not applied here (UI uses Transform; export applies once). - const int thrLow = 220; // begin soft transparency from this avg luminance - const int thrHigh = 245; // fully transparent from this avg luminance - - // Helper to clamp int - int clamp255(num v) => v.clamp(0, 255).toInt(); - - // Iterate pixels - for (int y = 0; y < out.height; y++) { - for (int x = 0; x < out.width; x++) { - final p = out.getPixel(x, y); - int a = clamp255(p.aNormalized * 255.0); - int r = clamp255(p.rNormalized * 255.0); - int g = clamp255(p.gNormalized * 255.0); - int b = clamp255(p.bNormalized * 255.0); - - // Apply contrast/brightness in sRGB space - // new = (old-128)*contrast + 128 + brightness*255 - final double brOffset = brightness * 255.0; - r = clamp255((r - 128) * contrast + 128 + brOffset); - g = clamp255((g - 128) * contrast + 128 + brOffset); - b = clamp255((b - 128) * contrast + 128 + brOffset); - - // Near-white background removal (compute average luminance) - final int avg = ((r + g + b) / 3).round(); - int remAlpha = 255; // 255 = fully opaque, 0 = transparent - if (bgRemoval) { - if (avg >= thrHigh) { - remAlpha = 0; - } else if (avg >= thrLow) { - // Soft fade between thrLow..thrHigh - final double t = (avg - thrLow) / (thrHigh - thrLow); - remAlpha = clamp255(255 * (1.0 - t)); - } else { - remAlpha = 255; - } - } - - // Combine with existing alpha (preserve existing transparency) - final newA = math.min(a, remAlpha); - - out.setPixelRgba(x, y, r, g, b, newA); - } - } - - // NOTE: Do not rotate here to keep UI responsive while dragging the slider. - // Rotation is applied in the UI using Transform.rotate for preview and - // performed once on confirm/export to avoid per-frame recomputation. - - // Encode as PNG to preserve transparency - final png = img.encodePng(out, level: 6); - return Uint8List.fromList(png); -}); diff --git a/lib/data/services/export_providers.dart b/lib/data/services/export_providers.dart deleted file mode 100644 index f117b6d..0000000 --- a/lib/data/services/export_providers.dart +++ /dev/null @@ -1,60 +0,0 @@ -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:path_provider/path_provider.dart' as pp; -import 'package:file_selector/file_selector.dart' as fs; -import 'package:pdf_signature/data/services/export_service.dart'; -import 'package:pdf_signature/data/services/preferences_providers.dart'; - -// Feature-scoped DI and configuration providers - -// Toggle mock viewer (used by tests to show a gray placeholder instead of real PDF pages) -final useMockViewerProvider = Provider((_) => false); - -// Export service injection for testability -final exportServiceProvider = Provider((_) => ExportService()); - -// Export DPI setting (points per inch mapping). Reads from SharedPreferences when available, -// otherwise falls back to 144.0 to keep tests deterministic without bootstrapping prefs. -final exportDpiProvider = Provider((ref) { - final sp = ref.watch(sharedPreferencesProvider); - return sp.maybeWhen( - data: (prefs) { - const allowed = [96.0, 144.0, 200.0, 300.0]; - final v = prefs.getDouble('export_dpi'); - return (v != null && allowed.contains(v)) ? v : 144.0; - }, - orElse: () => 144.0, - ); -}); - -// Controls whether signature overlay is visible (used to hide on non-stamped pages during export) -final signatureVisibilityProvider = StateProvider((_) => true); - -// Global exporting state to show loading UI and block interactions while saving/exporting -final exportingProvider = StateProvider((_) => false); - -// Save path picker (injected for tests) -final savePathPickerProvider = Provider Function()>((ref) { - return () async { - String? initialDir; - try { - final d = await pp.getDownloadsDirectory(); - initialDir = d?.path; - } catch (_) {} - if (initialDir == null) { - try { - final d = await pp.getApplicationDocumentsDirectory(); - initialDir = d.path; - } catch (_) {} - } - final location = await fs.getSaveLocation( - suggestedName: 'signed.pdf', - acceptedTypeGroups: [ - const fs.XTypeGroup(label: 'PDF', extensions: ['pdf']), - ], - initialDirectory: initialDir, - ); - if (location == null) return null; - final path = location.path; - return path.toLowerCase().endsWith('.pdf') ? path : '$path.pdf'; - }; -}); diff --git a/lib/data/services/export_service.dart b/lib/data/services/export_service.dart index d284ee9..8320a8c 100644 --- a/lib/data/services/export_service.dart +++ b/lib/data/services/export_service.dart @@ -21,25 +21,18 @@ class ExportService { /// Inputs: /// - [inputPath]: Path to the original PDF to read /// - [outputPath]: Path to write the composed PDF - /// - [signedPage]: 1-based page index to place the signature on (null = no overlay) - /// - [signatureRectUi]: Rect in the UI's logical page space (e.g. 400x560) - /// - [uiPageSize]: The logical page size used by the UI layout (SignatureController.pageSize) + /// - [uiPageSize]: The logical page size used by the UI layout (SignatureCardStateNotifier.pageSize) /// - [signatureImageBytes]: PNG/JPEG bytes of the signature image to overlay /// - [targetDpi]: Rasterization DPI for background pages Future exportSignedPdfFromFile({ required String inputPath, required String outputPath, - required int? signedPage, - required Rect? signatureRectUi, required Size uiPageSize, required Uint8List? signatureImageBytes, Map>? placementsByPage, Map? libraryBytes, double targetDpi = 144.0, }) async { - // print( - // 'exportSignedPdfFromFile: enter signedPage=$signedPage outputPath=$outputPath', - // ); // Read source bytes and delegate to bytes-based exporter Uint8List? srcBytes; try { @@ -50,8 +43,6 @@ class ExportService { if (srcBytes == null) return false; final bytes = await exportSignedPdfFromBytes( srcBytes: srcBytes, - signedPage: signedPage, - signatureRectUi: signatureRectUi, uiPageSize: uiPageSize, signatureImageBytes: signatureImageBytes, placementsByPage: placementsByPage, @@ -71,13 +62,11 @@ class ExportService { /// Compose a new PDF from source PDF bytes; returns the resulting PDF bytes. Future exportSignedPdfFromBytes({ required Uint8List srcBytes, - required int? signedPage, - required Rect? signatureRectUi, required Size uiPageSize, required Uint8List? signatureImageBytes, Map>? placementsByPage, Map? libraryBytes, - double targetDpi = 144.0, + double targetDpi = 144.0 }) async { final out = pw.Document(version: pdf.PdfVersion.pdf_1_4, compress: false); int pageIndex = 0; @@ -97,27 +86,13 @@ class ExportService { final bgPng = await raster.toPng(); final bgImg = pw.MemoryImage(bgPng); - pw.MemoryImage? sigImgObj; + final hasMulti = (placementsByPage != null && placementsByPage.isNotEmpty); final pagePlacements = hasMulti ? (placementsByPage[pageIndex] ?? const []) : const []; - final shouldStampSingle = - !hasMulti && - signedPage != null && - pageIndex == signedPage && - signatureRectUi != null && - signatureImageBytes != null && - signatureImageBytes.isNotEmpty; - if (shouldStampSingle) { - try { - sigImgObj = pw.MemoryImage(signatureImageBytes); - } catch (_) { - sigImgObj = null; - } - } out.addPage( pw.Page( @@ -148,10 +123,7 @@ class ExportService { final w = r.width / uiPageSize.width * widthPts; final h = r.height / uiPageSize.height * heightPts; Uint8List? bytes; - final id = placement.asset.id; - if (id.isNotEmpty) { - bytes = libraryBytes?[id]; - } + bytes ??= signatureImageBytes; // fallback if (bytes != null && bytes.isNotEmpty) { pw.MemoryImage? imgObj; @@ -184,26 +156,6 @@ class ExportService { } } } - } else if (shouldStampSingle && sigImgObj != null) { - final r = signatureRectUi; - final left = r.left / uiPageSize.width * widthPts; - final top = r.top / uiPageSize.height * heightPts; - final w = r.width / uiPageSize.width * widthPts; - final h = r.height / uiPageSize.height * heightPts; - children.add( - pw.Positioned( - left: left, - top: top, - child: pw.SizedBox( - width: w, - height: h, - child: pw.FittedBox( - fit: pw.BoxFit.contain, - child: pw.Image(sigImgObj), - ), - ), - ), - ); } return pw.Stack(children: children); }, @@ -218,39 +170,14 @@ class ExportService { // Fallback as A4 blank page with optional signature final widthPts = pdf.PdfPageFormat.a4.width; final heightPts = pdf.PdfPageFormat.a4.height; - pw.MemoryImage? sigImgObj; + final hasMulti = (placementsByPage != null && placementsByPage.isNotEmpty); final pagePlacements = hasMulti ? (placementsByPage[1] ?? const []) : const []; - final shouldStampSingle = - !hasMulti && - signedPage != null && - signedPage == 1 && - signatureRectUi != null && - signatureImageBytes != null && - signatureImageBytes.isNotEmpty; - if (shouldStampSingle) { - try { - // If it's already PNG, keep as-is to preserve alpha; otherwise decode/encode PNG - final asStr = String.fromCharCodes(signatureImageBytes.take(8)); - final isPng = - signatureImageBytes.length > 8 && - signatureImageBytes[0] == 0x89 && - asStr.startsWith('\u0089PNG'); - if (isPng) { - sigImgObj = pw.MemoryImage(signatureImageBytes); - } else { - final decoded = img.decodeImage(signatureImageBytes); - if (decoded != null) { - final png = img.encodePng(decoded, level: 6); - sigImgObj = pw.MemoryImage(Uint8List.fromList(png)); - } - } - } catch (_) {} - } + out.addPage( pw.Page( pageTheme: pw.PageTheme( @@ -275,10 +202,7 @@ class ExportService { final w = r.width / uiPageSize.width * widthPts; final h = r.height / uiPageSize.height * heightPts; Uint8List? bytes; - final id = placement.asset.id; - if (id.isNotEmpty) { - bytes = libraryBytes?[id]; - } + bytes ??= signatureImageBytes; // fallback if (bytes != null && bytes.isNotEmpty) { pw.MemoryImage? imgObj; @@ -323,26 +247,6 @@ class ExportService { } } } - } else if (shouldStampSingle && sigImgObj != null) { - final r = signatureRectUi; - final left = r.left / uiPageSize.width * widthPts; - final top = r.top / uiPageSize.height * heightPts; - final w = r.width / uiPageSize.width * widthPts; - final h = r.height / uiPageSize.height * heightPts; - children.add( - pw.Positioned( - left: left, - top: top, - child: pw.SizedBox( - width: w, - height: h, - child: pw.FittedBox( - fit: pw.BoxFit.contain, - child: pw.Image(sigImgObj), - ), - ), - ), - ); } return pw.Stack(children: children); }, diff --git a/lib/domain/models/model.dart b/lib/domain/models/model.dart index 9cffa74..a40e593 100644 --- a/lib/domain/models/model.dart +++ b/lib/domain/models/model.dart @@ -1,3 +1,4 @@ +/// TODO: remove this file and export models directly from their files. export 'signature_asset.dart'; export 'graphic_adjust.dart'; export 'signature_card.dart'; diff --git a/lib/domain/models/preferences.dart b/lib/domain/models/preferences.dart new file mode 100644 index 0000000..5bb48f9 --- /dev/null +++ b/lib/domain/models/preferences.dart @@ -0,0 +1,25 @@ +/// TODO: add `freeze` and `json_serializable` to generate immutable data class with copyWith, toString, equality, and JSON support. +class PreferencesState { + final String theme; // 'light' | 'dark' | 'system' + final String theme_color; // 'blue' | 'green' | 'red' | 'purple' + final String language; // 'en' | 'zh-TW' | 'es' + final double exportDpi; // 96.0 | 144.0 | 200.0 | 300.0 + const PreferencesState({ + required this.theme, + required this.theme_color, + required this.language, + required this.exportDpi, + }); + + PreferencesState copyWith({ + String? theme, + String? theme_color, + String? language, + double? exportDpi, + }) => PreferencesState( + theme: theme ?? this.theme, + theme_color: theme_color ?? this.theme_color, + language: language ?? this.language, + exportDpi: exportDpi ?? this.exportDpi, + ); +} diff --git a/lib/domain/models/signature_asset.dart b/lib/domain/models/signature_asset.dart index 2ae6a59..6ff564f 100644 --- a/lib/domain/models/signature_asset.dart +++ b/lib/domain/models/signature_asset.dart @@ -2,9 +2,8 @@ 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>? strokes; final String? name; // optional display name (e.g., filename) - const SignatureAsset({required this.id, required this.bytes, this.name}); + const SignatureAsset({required this.bytes, this.name}); } diff --git a/lib/domain/models/signature_card.dart b/lib/domain/models/signature_card.dart index f821b48..c6aeafe 100644 --- a/lib/domain/models/signature_card.dart +++ b/lib/domain/models/signature_card.dart @@ -12,8 +12,8 @@ class SignatureCard { final GraphicAdjust graphicAdjust; const SignatureCard({ - required this.rotationDeg, required this.asset, + required this.rotationDeg, this.graphicAdjust = const GraphicAdjust(), }); @@ -28,8 +28,8 @@ class SignatureCard { ); factory SignatureCard.initial() => SignatureCard( + asset: SignatureAsset(bytes: Uint8List(0)), rotationDeg: 0.0, - asset: SignatureAsset(id: '', bytes: Uint8List(0)), graphicAdjust: const GraphicAdjust(), ); } diff --git a/lib/ui/features/pdf/widgets/adjustments_panel.dart b/lib/ui/features/pdf/widgets/adjustments_panel.dart index 415502e..bde63d0 100644 --- a/lib/ui/features/pdf/widgets/adjustments_panel.dart +++ b/lib/ui/features/pdf/widgets/adjustments_panel.dart @@ -3,7 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; import '../../../../domain/models/model.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; class AdjustmentsPanel extends ConsumerWidget { const AdjustmentsPanel({super.key, required this.sig}); diff --git a/lib/ui/features/pdf/widgets/image_editor_dialog.dart b/lib/ui/features/pdf/widgets/image_editor_dialog.dart index 8889a65..2c37d3d 100644 --- a/lib/ui/features/pdf/widgets/image_editor_dialog.dart +++ b/lib/ui/features/pdf/widgets/image_editor_dialog.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import 'adjustments_panel.dart'; import '../../signature/widgets/rotated_signature_image.dart'; diff --git a/lib/ui/features/pdf/widgets/pdf_page_area.dart b/lib/ui/features/pdf/widgets/pdf_page_area.dart index 0f8e1f4..a3cbe28 100644 --- a/lib/ui/features/pdf/widgets/pdf_page_area.dart +++ b/lib/ui/features/pdf/widgets/pdf_page_area.dart @@ -4,8 +4,8 @@ import 'package:pdf_signature/l10n/app_localizations.dart'; import 'package:pdfrx/pdfrx.dart'; import '../../../../data/services/export_providers.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/signature_card_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '../../signature/widgets/signature_drag_data.dart'; import 'pdf_mock_continuous_list.dart'; import 'pdf_page_overlays.dart'; diff --git a/lib/ui/features/pdf/widgets/pdf_page_overlays.dart b/lib/ui/features/pdf/widgets/pdf_page_overlays.dart index d7f70c9..d45b734 100644 --- a/lib/ui/features/pdf/widgets/pdf_page_overlays.dart +++ b/lib/ui/features/pdf/widgets/pdf_page_overlays.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import '../../../../domain/models/model.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'signature_overlay.dart'; /// Builds all overlays for a given page: placed signatures and the active one. @@ -36,7 +36,7 @@ class PdfPageOverlays extends ConsumerWidget { final widgets = []; for (int i = 0; i < placed.length; i++) { - // Stored as UI-space rects (SignatureController.pageSize). + // Stored as UI-space rects (SignatureCardStateNotifier.pageSize). final uiRect = placed[i].rect; widgets.add( SignatureOverlay( diff --git a/lib/ui/features/pdf/widgets/pdf_pages_overview.dart b/lib/ui/features/pdf/widgets/pdf_pages_overview.dart index d2c6452..89703ad 100644 --- a/lib/ui/features/pdf/widgets/pdf_pages_overview.dart +++ b/lib/ui/features/pdf/widgets/pdf_pages_overview.dart @@ -3,7 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:pdfrx/pdfrx.dart'; import '../../../../data/services/export_providers.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; class PdfPagesOverview extends ConsumerWidget { const PdfPagesOverview({super.key}); diff --git a/lib/ui/features/pdf/widgets/pdf_screen.dart b/lib/ui/features/pdf/widgets/pdf_screen.dart index 0855bed..c6fab1a 100644 --- a/lib/ui/features/pdf/widgets/pdf_screen.dart +++ b/lib/ui/features/pdf/widgets/pdf_screen.dart @@ -3,6 +3,8 @@ import 'package:file_selector/file_selector.dart' as fs; import 'package:flutter/foundation.dart' show kIsWeb; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:pdf_signature/data/repositories/preferences_repository.dart'; +import 'package:pdf_signature/domain/models/preferences.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; import 'package:printing/printing.dart' as printing; import 'package:pdfrx/pdfrx.dart'; @@ -10,8 +12,8 @@ import 'package:multi_split_view/multi_split_view.dart'; import '../../../../data/services/export_providers.dart'; import 'package:image/image.dart' as img; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/data/repositories/signature_asset_repository.dart'; import 'draw_canvas.dart'; import 'pdf_toolbar.dart'; @@ -28,7 +30,7 @@ class PdfSignatureHomePage extends ConsumerStatefulWidget { } class _PdfSignatureHomePageState extends ConsumerState { - static const Size _pageSize = SignatureController.pageSize; + static const Size _pageSize = SignatureCardStateNotifier.pageSize; final PdfViewerController _viewerController = PdfViewerController(); bool _showPagesSidebar = true; bool _showSignaturesSidebar = true; @@ -142,7 +144,11 @@ class _PdfSignatureHomePageState extends ConsumerState { return; } final exporter = ref.read(exportServiceProvider); - final targetDpi = ref.read(exportDpiProvider); + + // get DPI from preferences + final targetDpi = ref.read(preferencesRepositoryProvider).select( + (p) => p.exportDpi, + ); final useMock = ref.read(useMockViewerProvider); bool ok = false; String? savedPath; @@ -177,7 +183,7 @@ class _PdfSignatureHomePageState extends ConsumerState { srcBytes: src, signedPage: pdf.signedPage, signatureRectUi: sig.rect, - uiPageSize: SignatureController.pageSize, + uiPageSize: SignatureCardStateNotifier.pageSize, signatureImageBytes: rotated, placementsByPage: pdf.placementsByPage, libraryBytes: { @@ -214,7 +220,7 @@ class _PdfSignatureHomePageState extends ConsumerState { srcBytes: pdf.pickedPdfBytes!, signedPage: pdf.signedPage, signatureRectUi: sig.rect, - uiPageSize: SignatureController.pageSize, + uiPageSize: SignatureCardStateNotifier.pageSize, signatureImageBytes: rotated, placementsByPage: pdf.placementsByPage, libraryBytes: { @@ -245,7 +251,7 @@ class _PdfSignatureHomePageState extends ConsumerState { outputPath: fullPath, signedPage: pdf.signedPage, signatureRectUi: sig.rect, - uiPageSize: SignatureController.pageSize, + uiPageSize: SignatureCardStateNotifier.pageSize, signatureImageBytes: rotated, placementsByPage: pdf.placementsByPage, libraryBytes: { @@ -467,3 +473,7 @@ class _PdfSignatureHomePageState extends ConsumerState { ); } } + +extension on PreferencesState { + select(Function(dynamic p) param0) {} +} diff --git a/lib/ui/features/pdf/widgets/pdf_toolbar.dart b/lib/ui/features/pdf/widgets/pdf_toolbar.dart index 4e40d41..69cc7d8 100644 --- a/lib/ui/features/pdf/widgets/pdf_toolbar.dart +++ b/lib/ui/features/pdf/widgets/pdf_toolbar.dart @@ -3,7 +3,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; class PdfToolbar extends ConsumerStatefulWidget { const PdfToolbar({ diff --git a/lib/ui/features/pdf/widgets/signature_drawer.dart b/lib/ui/features/pdf/widgets/signature_drawer.dart index fd7e32e..26fc3ed 100644 --- a/lib/ui/features/pdf/widgets/signature_drawer.dart +++ b/lib/ui/features/pdf/widgets/signature_drawer.dart @@ -5,7 +5,7 @@ import 'package:pdf_signature/l10n/app_localizations.dart'; import 'package:pdf_signature/domain/models/model.dart' as model; import '../../../../data/services/export_providers.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import 'package:pdf_signature/data/repositories/signature_asset_repository.dart'; import 'image_editor_dialog.dart'; import '../../signature/widgets/signature_card.dart'; diff --git a/lib/ui/features/pdf/widgets/signature_overlay.dart b/lib/ui/features/pdf/widgets/signature_overlay.dart index f4cce60..397427d 100644 --- a/lib/ui/features/pdf/widgets/signature_overlay.dart +++ b/lib/ui/features/pdf/widgets/signature_overlay.dart @@ -5,8 +5,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; import '../../../../domain/models/model.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/signature_card_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/data/repositories/signature_asset_repository.dart'; import 'image_editor_dialog.dart'; import '../../signature/widgets/rotated_signature_image.dart'; diff --git a/lib/ui/features/preferences/widgets/settings_screen.dart b/lib/ui/features/preferences/widgets/settings_screen.dart index a80c4be..a3c9a87 100644 --- a/lib/ui/features/preferences/widgets/settings_screen.dart +++ b/lib/ui/features/preferences/widgets/settings_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; -import '../../../../data/services/preferences_providers.dart'; +import '../../../../data/repositories/preferences_repository.dart'; class SettingsDialog extends ConsumerStatefulWidget { const SettingsDialog({super.key}); @@ -19,7 +19,7 @@ class _SettingsDialogState extends ConsumerState { @override void initState() { super.initState(); - final prefs = ref.read(preferencesProvider); + final prefs = ref.read(preferencesRepositoryProvider); _theme = prefs.theme; _language = prefs.language; _exportDpi = prefs.exportDpi; @@ -186,7 +186,9 @@ class _SettingsDialogState extends ConsumerState { const SizedBox(width: 8), FilledButton( onPressed: () async { - final n = ref.read(preferencesProvider.notifier); + final n = ref.read( + preferencesRepositoryProvider.notifier, + ); if (_theme != null) await n.setTheme(_theme!); if (_language != null) await n.setLanguage(_language!); if (_exportDpi != null) await n.setExportDpi(_exportDpi!); diff --git a/lib/ui/features/welcome/widgets/welcome_screen.dart b/lib/ui/features/welcome/widgets/welcome_screen.dart index a6fc4a0..191a92f 100644 --- a/lib/ui/features/welcome/widgets/welcome_screen.dart +++ b/lib/ui/features/welcome/widgets/welcome_screen.dart @@ -7,8 +7,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; // Settings dialog is provided via global AppBar in MyApp // Abstraction to make drop handling testable without constructing diff --git a/test/export_signature_test.dart b/test/export_signature_test.dart deleted file mode 100644 index 35f8b60..0000000 --- a/test/export_signature_test.dart +++ /dev/null @@ -1,87 +0,0 @@ -import 'dart:io'; -import 'dart:typed_data'; -import 'dart:ui' show Rect, Size; - -import 'package:flutter_test/flutter_test.dart'; -import 'package:image/image.dart' as img; -import 'package:pdf/pdf.dart' as pdf; -import 'package:pdf/widgets.dart' as pw; - -import 'package:pdf_signature/data/services/export_service.dart'; - -void main() { - test( - 'exportSignedPdfFromFile overlays signature image (structure/size check)', - () async { - // 1) Create a simple 1-page white PDF as the source - final srcDoc = pw.Document(); - srcDoc.addPage( - pw.Page( - pageFormat: pdf.PdfPageFormat.a4, - build: (_) => pw.Container(color: pdf.PdfColors.white), - ), - ); - final srcBytes = await srcDoc.save(); - final srcPath = - '${Directory.systemTemp.path}/export_src_${DateTime.now().millisecondsSinceEpoch}.pdf'; - await File(srcPath).writeAsBytes(srcBytes, flush: true); - - // 2) Create a small opaque black PNG as the signature image - final sigW = 60, sigH = 30; - final sigBitmap = img.Image(width: sigW, height: sigH); - img.fill(sigBitmap, color: img.ColorRgb8(0, 0, 0)); - final sigPng = Uint8List.fromList(img.encodePng(sigBitmap)); - - // 3) Define signature rect in UI logical space (400x560), centered - const uiSize = Size(400, 560); - final r = Rect.fromLTWH( - uiSize.width / 2 - sigW / 2, - uiSize.height / 2 - sigH / 2, - sigW.toDouble(), - sigH.toDouble(), - ); - - // 4) Baseline export without signature (no overlay) - final baselinePath = - '${Directory.systemTemp.path}/export_baseline_${DateTime.now().millisecondsSinceEpoch}.pdf'; - final svc = ExportService(); - final okBase = await svc.exportSignedPdfFromFile( - inputPath: srcPath, - outputPath: baselinePath, - signedPage: null, - signatureRectUi: null, - uiPageSize: uiSize, - signatureImageBytes: null, - targetDpi: 144.0, - ); - expect(okBase, isTrue, reason: 'baseline export should succeed'); - final baseBytes = await File(baselinePath).readAsBytes(); - expect(baseBytes.isNotEmpty, isTrue); - - // 5) Export with overlay - final outPath = - '${Directory.systemTemp.path}/export_out_${DateTime.now().millisecondsSinceEpoch}.pdf'; - final ok = await svc.exportSignedPdfFromFile( - inputPath: srcPath, - outputPath: outPath, - signedPage: 1, - signatureRectUi: r, - uiPageSize: uiSize, - signatureImageBytes: sigPng, - targetDpi: 144.0, - ); - expect(ok, isTrue, reason: 'export should succeed'); - final outBytes = await File(outPath).readAsBytes(); - expect(outBytes.isNotEmpty, isTrue); - - // 6) Heuristic validations without rasterization: - // - The output with overlay should be larger than the baseline. - // - The output should contain at least one image object marker. - expect(outBytes.length, greaterThan(baseBytes.length)); - // Decode as latin1 to preserve byte-to-char mapping, then look for the image marker - final outText = String.fromCharCodes(outBytes); - final hasImageMarker = RegExp(r"/Subtype\s*/Image").hasMatch(outText); - expect(hasImageMarker, isTrue); - }, - ); -} diff --git a/test/features/step/a_document_is_open_and_contains_at_least_one_signature_placement.dart b/test/features/step/a_document_is_open_and_contains_at_least_one_signature_placement.dart index 1170cc9..77a9777 100644 --- a/test/features/step/a_document_is_open_and_contains_at_least_one_signature_placement.dart +++ b/test/features/step/a_document_is_open_and_contains_at_least_one_signature_placement.dart @@ -2,7 +2,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/a_document_is_open_and_contains_multiple_placed_signature_placements_across_pages.dart b/test/features/step/a_document_is_open_and_contains_multiple_placed_signature_placements_across_pages.dart index e11c368..b7f2ee5 100644 --- a/test/features/step/a_document_is_open_and_contains_multiple_placed_signature_placements_across_pages.dart +++ b/test/features/step/a_document_is_open_and_contains_multiple_placed_signature_placements_across_pages.dart @@ -2,7 +2,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/a_document_is_open_with_no_signature_placements_placed.dart b/test/features/step/a_document_is_open_with_no_signature_placements_placed.dart index fab4a0c..ddc140e 100644 --- a/test/features/step/a_document_is_open_with_no_signature_placements_placed.dart +++ b/test/features/step/a_document_is_open_with_no_signature_placements_placed.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: a document is open with no signature placements placed diff --git a/test/features/step/a_document_page_is_selected_for_signing.dart b/test/features/step/a_document_page_is_selected_for_signing.dart index 79f88e4..cddbcbf 100644 --- a/test/features/step/a_document_page_is_selected_for_signing.dart +++ b/test/features/step/a_document_page_is_selected_for_signing.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: a document page is selected for signing diff --git a/test/features/step/a_drawn_signature_exists_in_the_canvas.dart b/test/features/step/a_drawn_signature_exists_in_the_canvas.dart index a5873be..c57c617 100644 --- a/test/features/step/a_drawn_signature_exists_in_the_canvas.dart +++ b/test/features/step/a_drawn_signature_exists_in_the_canvas.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import '_world.dart'; /// Usage: a drawn signature exists in the canvas diff --git a/test/features/step/a_multipage_document_is_open.dart b/test/features/step/a_multipage_document_is_open.dart index a299b37..7295f6d 100644 --- a/test/features/step/a_multipage_document_is_open.dart +++ b/test/features/step/a_multipage_document_is_open.dart @@ -1,7 +1,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.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/document_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import 'package:pdf_signature/data/repositories/signature_asset_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/a_sample_multipage_document5_pages_is_available.dart b/test/features/step/a_sample_multipage_document5_pages_is_available.dart index 2054d67..a436b43 100644 --- a/test/features/step/a_sample_multipage_document5_pages_is_available.dart +++ b/test/features/step/a_sample_multipage_document5_pages_is_available.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: a sample multi-page document (5 pages) is available diff --git a/test/features/step/a_signature_asset_is_created.dart b/test/features/step/a_signature_asset_is_created.dart index 156c654..9ab2a0e 100644 --- a/test/features/step/a_signature_asset_is_created.dart +++ b/test/features/step/a_signature_asset_is_created.dart @@ -2,7 +2,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/data/repositories/signature_asset_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/a_signature_asset_is_loaded_or_drawn.dart b/test/features/step/a_signature_asset_is_loaded_or_drawn.dart index 73b6974..b3e63a6 100644 --- a/test/features/step/a_signature_asset_is_loaded_or_drawn.dart +++ b/test/features/step/a_signature_asset_is_loaded_or_drawn.dart @@ -2,8 +2,8 @@ import 'dart:typed_data'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.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/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/a_signature_asset_is_placed_on_the_page.dart b/test/features/step/a_signature_asset_is_placed_on_the_page.dart index 6fd7e6f..c792bc0 100644 --- a/test/features/step/a_signature_asset_is_placed_on_the_page.dart +++ b/test/features/step/a_signature_asset_is_placed_on_the_page.dart @@ -2,7 +2,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/data/repositories/signature_asset_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/a_signature_asset_loaded_or_drawn_is_wrapped_in_a_signature_card.dart b/test/features/step/a_signature_asset_loaded_or_drawn_is_wrapped_in_a_signature_card.dart index 8f416d1..1edcc6e 100644 --- a/test/features/step/a_signature_asset_loaded_or_drawn_is_wrapped_in_a_signature_card.dart +++ b/test/features/step/a_signature_asset_loaded_or_drawn_is_wrapped_in_a_signature_card.dart @@ -2,8 +2,8 @@ import 'dart:typed_data'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.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/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/a_signature_placement_appears_on_the_page_based_on_the_signature_card.dart b/test/features/step/a_signature_placement_appears_on_the_page_based_on_the_signature_card.dart index 40433a2..7b1b20c 100644 --- a/test/features/step/a_signature_placement_appears_on_the_page_based_on_the_signature_card.dart +++ b/test/features/step/a_signature_placement_appears_on_the_page_based_on_the_signature_card.dart @@ -1,5 +1,5 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: a signature placement appears on the page based on the signature card diff --git a/test/features/step/a_signature_placement_is_placed_on_page.dart b/test/features/step/a_signature_placement_is_placed_on_page.dart index fb9809b..0fe71c4 100644 --- a/test/features/step/a_signature_placement_is_placed_on_page.dart +++ b/test/features/step/a_signature_placement_is_placed_on_page.dart @@ -2,7 +2,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/a_signature_placement_is_placed_with_a_position_and_size_relative_to_the_page.dart b/test/features/step/a_signature_placement_is_placed_with_a_position_and_size_relative_to_the_page.dart index 5cadc26..f35520b 100644 --- a/test/features/step/a_signature_placement_is_placed_with_a_position_and_size_relative_to_the_page.dart +++ b/test/features/step/a_signature_placement_is_placed_with_a_position_and_size_relative_to_the_page.dart @@ -2,7 +2,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/adjusting_one_instance_does_not_affect_the_others.dart b/test/features/step/adjusting_one_instance_does_not_affect_the_others.dart index 33c0d14..a105d05 100644 --- a/test/features/step/adjusting_one_instance_does_not_affect_the_others.dart +++ b/test/features/step/adjusting_one_instance_does_not_affect_the_others.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/adjusting_one_of_the_signature_placements_does_not_affect_the_others.dart b/test/features/step/adjusting_one_of_the_signature_placements_does_not_affect_the_others.dart index c7803f2..28352a7 100644 --- a/test/features/step/adjusting_one_of_the_signature_placements_does_not_affect_the_others.dart +++ b/test/features/step/adjusting_one_of_the_signature_placements_does_not_affect_the_others.dart @@ -1,5 +1,5 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: adjusting one of the signature placements does not affect the others diff --git a/test/features/step/all_placed_signature_placements_appear_on_their_corresponding_pages_in_the_output.dart b/test/features/step/all_placed_signature_placements_appear_on_their_corresponding_pages_in_the_output.dart index c4c203d..23ba72d 100644 --- a/test/features/step/all_placed_signature_placements_appear_on_their_corresponding_pages_in_the_output.dart +++ b/test/features/step/all_placed_signature_placements_appear_on_their_corresponding_pages_in_the_output.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: all placed signature placements appear on their corresponding pages in the output diff --git a/test/features/step/an_empty_signature_canvas.dart b/test/features/step/an_empty_signature_canvas.dart index c92a7c3..1065312 100644 --- a/test/features/step/an_empty_signature_canvas.dart +++ b/test/features/step/an_empty_signature_canvas.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import '_world.dart'; /// Usage: an empty signature canvas diff --git a/test/features/step/both_signature_placements_are_shown_on_their_respective_pages.dart b/test/features/step/both_signature_placements_are_shown_on_their_respective_pages.dart index 0848794..fe81fee 100644 --- a/test/features/step/both_signature_placements_are_shown_on_their_respective_pages.dart +++ b/test/features/step/both_signature_placements_are_shown_on_their_respective_pages.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: both signature placements are shown on their respective pages diff --git a/test/features/step/dragging_or_resizing_one_does_not_change_the_other.dart b/test/features/step/dragging_or_resizing_one_does_not_change_the_other.dart index de5623c..6cd87c9 100644 --- a/test/features/step/dragging_or_resizing_one_does_not_change_the_other.dart +++ b/test/features/step/dragging_or_resizing_one_does_not_change_the_other.dart @@ -1,7 +1,7 @@ import 'dart:ui'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/each_signature_placement_can_be_dragged_and_resized_independently.dart b/test/features/step/each_signature_placement_can_be_dragged_and_resized_independently.dart index c14b648..56215cf 100644 --- a/test/features/step/each_signature_placement_can_be_dragged_and_resized_independently.dart +++ b/test/features/step/each_signature_placement_can_be_dragged_and_resized_independently.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: each signature placement can be dragged and resized independently diff --git a/test/features/step/identical_signature_instances_appear_in_each_location.dart b/test/features/step/identical_signature_instances_appear_in_each_location.dart index f38ac9b..008a9c4 100644 --- a/test/features/step/identical_signature_instances_appear_in_each_location.dart +++ b/test/features/step/identical_signature_instances_appear_in_each_location.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: identical signature instances appear in each location diff --git a/test/features/step/identical_signature_placements_appear_in_each_location.dart b/test/features/step/identical_signature_placements_appear_in_each_location.dart index 02d18be..fed898f 100644 --- a/test/features/step/identical_signature_placements_appear_in_each_location.dart +++ b/test/features/step/identical_signature_placements_appear_in_each_location.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: identical signature placements appear in each location diff --git a/test/features/step/multiple_strokes_were_drawn.dart b/test/features/step/multiple_strokes_were_drawn.dart index 255720a..0412daa 100644 --- a/test/features/step/multiple_strokes_were_drawn.dart +++ b/test/features/step/multiple_strokes_were_drawn.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import '_world.dart'; /// Usage: multiple strokes were drawn diff --git a/test/features/step/nearwhite_background_becomes_transparent_in_the_preview.dart b/test/features/step/nearwhite_background_becomes_transparent_in_the_preview.dart index 2d0cb1c..bf9650f 100644 --- a/test/features/step/nearwhite_background_becomes_transparent_in_the_preview.dart +++ b/test/features/step/nearwhite_background_becomes_transparent_in_the_preview.dart @@ -2,7 +2,7 @@ import 'dart:typed_data'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:image/image.dart' as img; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import '_world.dart'; /// Usage: near-white background becomes transparent in the preview diff --git a/test/features/step/only_the_selected_signature_placement_is_removed.dart b/test/features/step/only_the_selected_signature_placement_is_removed.dart index 6078012..5fe5cff 100644 --- a/test/features/step/only_the_selected_signature_placement_is_removed.dart +++ b/test/features/step/only_the_selected_signature_placement_is_removed.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: only the selected signature placement is removed diff --git a/test/features/step/page_becomes_visible_in_the_scroll_area.dart b/test/features/step/page_becomes_visible_in_the_scroll_area.dart index 3baaea6..d81a925 100644 --- a/test/features/step/page_becomes_visible_in_the_scroll_area.dart +++ b/test/features/step/page_becomes_visible_in_the_scroll_area.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: page {5} becomes visible in the scroll area diff --git a/test/features/step/page_is_displayed.dart b/test/features/step/page_is_displayed.dart index c5b8a56..36898ef 100644 --- a/test/features/step/page_is_displayed.dart +++ b/test/features/step/page_is_displayed.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: page {1} is displayed diff --git a/test/features/step/resize_to_fit_within_bounding_box.dart b/test/features/step/resize_to_fit_within_bounding_box.dart index f0d8ce8..96dec49 100644 --- a/test/features/step/resize_to_fit_within_bounding_box.dart +++ b/test/features/step/resize_to_fit_within_bounding_box.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: resize to fit within bounding box diff --git a/test/features/step/signature_placement_occurs_on_the_selected_page.dart b/test/features/step/signature_placement_occurs_on_the_selected_page.dart index 2238cd3..4c15439 100644 --- a/test/features/step/signature_placement_occurs_on_the_selected_page.dart +++ b/test/features/step/signature_placement_occurs_on_the_selected_page.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: signature placement occurs on the selected page diff --git a/test/features/step/the_canvas_becomes_blank.dart b/test/features/step/the_canvas_becomes_blank.dart index 6d0299a..b915314 100644 --- a/test/features/step/the_canvas_becomes_blank.dart +++ b/test/features/step/the_canvas_becomes_blank.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import '_world.dart'; /// Usage: the canvas becomes blank diff --git a/test/features/step/the_document_is_open.dart b/test/features/step/the_document_is_open.dart index f59d389..0065e34 100644 --- a/test/features/step/the_document_is_open.dart +++ b/test/features/step/the_document_is_open.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the document is open diff --git a/test/features/step/the_first_page_is_displayed.dart b/test/features/step/the_first_page_is_displayed.dart index 01e2f89..40c36eb 100644 --- a/test/features/step/the_first_page_is_displayed.dart +++ b/test/features/step/the_first_page_is_displayed.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the first page is displayed diff --git a/test/features/step/the_go_to_input_cannot_be_used.dart b/test/features/step/the_go_to_input_cannot_be_used.dart index 7e8e936..ce50931 100644 --- a/test/features/step/the_go_to_input_cannot_be_used.dart +++ b/test/features/step/the_go_to_input_cannot_be_used.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the Go to input cannot be used diff --git a/test/features/step/the_last_page_is_displayed_page.dart b/test/features/step/the_last_page_is_displayed_page.dart index 5efb379..c6d9f49 100644 --- a/test/features/step/the_last_page_is_displayed_page.dart +++ b/test/features/step/the_last_page_is_displayed_page.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the last page is displayed (page {5}) diff --git a/test/features/step/the_last_stroke_is_removed.dart b/test/features/step/the_last_stroke_is_removed.dart index 8d86f09..6f8cd9e 100644 --- a/test/features/step/the_last_stroke_is_removed.dart +++ b/test/features/step/the_last_stroke_is_removed.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import '_world.dart'; /// Usage: the last stroke is removed diff --git a/test/features/step/the_left_pages_overview_highlights_page.dart b/test/features/step/the_left_pages_overview_highlights_page.dart index ce46890..e7ef554 100644 --- a/test/features/step/the_left_pages_overview_highlights_page.dart +++ b/test/features/step/the_left_pages_overview_highlights_page.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the left pages overview highlights page {5} diff --git a/test/features/step/the_other_signature_placements_remain_unchanged.dart b/test/features/step/the_other_signature_placements_remain_unchanged.dart index 123f40f..74c464a 100644 --- a/test/features/step/the_other_signature_placements_remain_unchanged.dart +++ b/test/features/step/the_other_signature_placements_remain_unchanged.dart @@ -1,5 +1,5 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the other signature placements remain unchanged diff --git a/test/features/step/the_page_label_shows_page_of.dart b/test/features/step/the_page_label_shows_page_of.dart index 79b9643..ea032a4 100644 --- a/test/features/step/the_page_label_shows_page_of.dart +++ b/test/features/step/the_page_label_shows_page_of.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the page label shows "Page {5} of {5}" diff --git a/test/features/step/the_preview_updates_immediately.dart b/test/features/step/the_preview_updates_immediately.dart index 586646c..4384f06 100644 --- a/test/features/step/the_preview_updates_immediately.dart +++ b/test/features/step/the_preview_updates_immediately.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import '_world.dart'; /// Usage: the preview updates immediately diff --git a/test/features/step/the_signature_placement_is_stamped_at_the_exact_pdf_page_coordinates_and_size.dart b/test/features/step/the_signature_placement_is_stamped_at_the_exact_pdf_page_coordinates_and_size.dart index 8264ea5..d175652 100644 --- a/test/features/step/the_signature_placement_is_stamped_at_the_exact_pdf_page_coordinates_and_size.dart +++ b/test/features/step/the_signature_placement_is_stamped_at_the_exact_pdf_page_coordinates_and_size.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the signature placement is stamped at the exact PDF page coordinates and size diff --git a/test/features/step/the_signature_placement_on_page_is_shown_on_page.dart b/test/features/step/the_signature_placement_on_page_is_shown_on_page.dart index a094c29..87cadd5 100644 --- a/test/features/step/the_signature_placement_on_page_is_shown_on_page.dart +++ b/test/features/step/the_signature_placement_on_page_is_shown_on_page.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the signature placement on page {5} is shown on page {5} diff --git a/test/features/step/the_signature_placement_on_page_remains.dart b/test/features/step/the_signature_placement_on_page_remains.dart index 7f24950..10a9ff2 100644 --- a/test/features/step/the_signature_placement_on_page_remains.dart +++ b/test/features/step/the_signature_placement_on_page_remains.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the signature placement on page {2} remains diff --git a/test/features/step/the_signature_placement_remains_within_the_page_area.dart b/test/features/step/the_signature_placement_remains_within_the_page_area.dart index 29eeb53..344cfee 100644 --- a/test/features/step/the_signature_placement_remains_within_the_page_area.dart +++ b/test/features/step/the_signature_placement_remains_within_the_page_area.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the signature placement remains within the page area diff --git a/test/features/step/the_signature_placement_rotates_around_its_center_in_real_time.dart b/test/features/step/the_signature_placement_rotates_around_its_center_in_real_time.dart index 1815877..58dfd9b 100644 --- a/test/features/step/the_signature_placement_rotates_around_its_center_in_real_time.dart +++ b/test/features/step/the_signature_placement_rotates_around_its_center_in_real_time.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the signature placement rotates around its center in real time diff --git a/test/features/step/the_signature_placements_appear_on_the_corresponding_page_in_the_output.dart b/test/features/step/the_signature_placements_appear_on_the_corresponding_page_in_the_output.dart index 0b44b47..eb7329b 100644 --- a/test/features/step/the_signature_placements_appear_on_the_corresponding_page_in_the_output.dart +++ b/test/features/step/the_signature_placements_appear_on_the_corresponding_page_in_the_output.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the signature placements appear on the corresponding page in the output diff --git a/test/features/step/the_size_and_position_update_in_real_time.dart b/test/features/step/the_size_and_position_update_in_real_time.dart index 37bf23d..1824abc 100644 --- a/test/features/step/the_size_and_position_update_in_real_time.dart +++ b/test/features/step/the_size_and_position_update_in_real_time.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the size and position update in real time diff --git a/test/features/step/the_user_attempts_to_save.dart b/test/features/step/the_user_attempts_to_save.dart index 32e6990..22fe1e4 100644 --- a/test/features/step/the_user_attempts_to_save.dart +++ b/test/features/step/the_user_attempts_to_save.dart @@ -1,7 +1,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.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/signature_card_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the user attempts to save diff --git a/test/features/step/the_user_can_apply_or_reset_adjustments.dart b/test/features/step/the_user_can_apply_or_reset_adjustments.dart index a975a9f..149e08b 100644 --- a/test/features/step/the_user_can_apply_or_reset_adjustments.dart +++ b/test/features/step/the_user_can_apply_or_reset_adjustments.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import '_world.dart'; /// Usage: the user can apply or reset adjustments diff --git a/test/features/step/the_user_can_move_to_the_next_or_previous_page.dart b/test/features/step/the_user_can_move_to_the_next_or_previous_page.dart index 0193f62..fc0a9a1 100644 --- a/test/features/step/the_user_can_move_to_the_next_or_previous_page.dart +++ b/test/features/step/the_user_can_move_to_the_next_or_previous_page.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the user can move to the next or previous page diff --git a/test/features/step/the_user_changes_contrast_and_brightness_controls.dart b/test/features/step/the_user_changes_contrast_and_brightness_controls.dart index 2f93c19..b864aff 100644 --- a/test/features/step/the_user_changes_contrast_and_brightness_controls.dart +++ b/test/features/step/the_user_changes_contrast_and_brightness_controls.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import '_world.dart'; /// Usage: the user changes contrast and brightness controls diff --git a/test/features/step/the_user_chooses_undo.dart b/test/features/step/the_user_chooses_undo.dart index 7a40a01..a6591cd 100644 --- a/test/features/step/the_user_chooses_undo.dart +++ b/test/features/step/the_user_chooses_undo.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import '_world.dart'; /// Usage: the user chooses undo diff --git a/test/features/step/the_user_clears_the_canvas.dart b/test/features/step/the_user_clears_the_canvas.dart index 0c705a4..8931223 100644 --- a/test/features/step/the_user_clears_the_canvas.dart +++ b/test/features/step/the_user_clears_the_canvas.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import '_world.dart'; /// Usage: the user clears the canvas diff --git a/test/features/step/the_user_clicks_the_go_to_apply_button.dart b/test/features/step/the_user_clicks_the_go_to_apply_button.dart index 5710c64..9e05367 100644 --- a/test/features/step/the_user_clicks_the_go_to_apply_button.dart +++ b/test/features/step/the_user_clicks_the_go_to_apply_button.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the user clicks the Go to apply button diff --git a/test/features/step/the_user_clicks_the_thumbnail_for_page.dart b/test/features/step/the_user_clicks_the_thumbnail_for_page.dart index d641a46..946bfa1 100644 --- a/test/features/step/the_user_clicks_the_thumbnail_for_page.dart +++ b/test/features/step/the_user_clicks_the_thumbnail_for_page.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the user clicks the thumbnail for page {2} diff --git a/test/features/step/the_user_deletes_one_selected_signature_placement.dart b/test/features/step/the_user_deletes_one_selected_signature_placement.dart index 5418460..33d8614 100644 --- a/test/features/step/the_user_deletes_one_selected_signature_placement.dart +++ b/test/features/step/the_user_deletes_one_selected_signature_placement.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the user deletes one selected signature placement diff --git a/test/features/step/the_user_drags_handles_to_resize_and_drags_to_reposition.dart b/test/features/step/the_user_drags_handles_to_resize_and_drags_to_reposition.dart index 335572c..8fd228b 100644 --- a/test/features/step/the_user_drags_handles_to_resize_and_drags_to_reposition.dart +++ b/test/features/step/the_user_drags_handles_to_resize_and_drags_to_reposition.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the user drags handles to resize and drags to reposition diff --git a/test/features/step/the_user_drags_it_on_the_page_of_the_document_to_place_signature_placements_in_multiple_locations_in_the_document.dart b/test/features/step/the_user_drags_it_on_the_page_of_the_document_to_place_signature_placements_in_multiple_locations_in_the_document.dart index 465e4c2..8331f9c 100644 --- a/test/features/step/the_user_drags_it_on_the_page_of_the_document_to_place_signature_placements_in_multiple_locations_in_the_document.dart +++ b/test/features/step/the_user_drags_it_on_the_page_of_the_document_to_place_signature_placements_in_multiple_locations_in_the_document.dart @@ -2,7 +2,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/data/repositories/signature_asset_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/the_user_drags_this_signature_card_on_the_page_of_the_document_to_place_a_signature_placement.dart b/test/features/step/the_user_drags_this_signature_card_on_the_page_of_the_document_to_place_a_signature_placement.dart index 12452fe..75ee6f4 100644 --- a/test/features/step/the_user_drags_this_signature_card_on_the_page_of_the_document_to_place_a_signature_placement.dart +++ b/test/features/step/the_user_drags_this_signature_card_on_the_page_of_the_document_to_place_a_signature_placement.dart @@ -2,7 +2,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/data/repositories/signature_asset_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/the_user_draws_strokes_and_confirms.dart b/test/features/step/the_user_draws_strokes_and_confirms.dart index 57d0d79..2539db6 100644 --- a/test/features/step/the_user_draws_strokes_and_confirms.dart +++ b/test/features/step/the_user_draws_strokes_and_confirms.dart @@ -1,7 +1,7 @@ import 'dart:typed_data'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import '_world.dart'; /// Usage: the user draws strokes and confirms diff --git a/test/features/step/the_user_enables_background_removal.dart b/test/features/step/the_user_enables_background_removal.dart index a80d99b..a1de725 100644 --- a/test/features/step/the_user_enables_background_removal.dart +++ b/test/features/step/the_user_enables_background_removal.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import '_world.dart'; /// Usage: the user enables background removal diff --git a/test/features/step/the_user_enters_into_the_go_to_input_and_applies_it.dart b/test/features/step/the_user_enters_into_the_go_to_input_and_applies_it.dart index 99590ab..a747268 100644 --- a/test/features/step/the_user_enters_into_the_go_to_input_and_applies_it.dart +++ b/test/features/step/the_user_enters_into_the_go_to_input_and_applies_it.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the user enters {99} into the Go to input and applies it diff --git a/test/features/step/the_user_is_notified_of_the_issue.dart b/test/features/step/the_user_is_notified_of_the_issue.dart index b27050e..76ce9e9 100644 --- a/test/features/step/the_user_is_notified_of_the_issue.dart +++ b/test/features/step/the_user_is_notified_of_the_issue.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/signature_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import '_world.dart'; /// Usage: the user is notified of the issue diff --git a/test/features/step/the_user_jumps_to_page.dart b/test/features/step/the_user_jumps_to_page.dart index 440b952..56aac70 100644 --- a/test/features/step/the_user_jumps_to_page.dart +++ b/test/features/step/the_user_jumps_to_page.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the user jumps to page {2} diff --git a/test/features/step/the_user_navigates_to_page_and_places_another_signature_placement.dart b/test/features/step/the_user_navigates_to_page_and_places_another_signature_placement.dart index 54841ac..a411689 100644 --- a/test/features/step/the_user_navigates_to_page_and_places_another_signature_placement.dart +++ b/test/features/step/the_user_navigates_to_page_and_places_another_signature_placement.dart @@ -2,7 +2,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/the_user_places_a_signature_placement_from_asset_on_page.dart b/test/features/step/the_user_places_a_signature_placement_from_asset_on_page.dart index 6e939aa..ac3b850 100644 --- a/test/features/step/the_user_places_a_signature_placement_from_asset_on_page.dart +++ b/test/features/step/the_user_places_a_signature_placement_from_asset_on_page.dart @@ -2,7 +2,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/data/repositories/signature_asset_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/the_user_places_a_signature_placement_on_page.dart b/test/features/step/the_user_places_a_signature_placement_on_page.dart index 3d8419e..63d1ebe 100644 --- a/test/features/step/the_user_places_a_signature_placement_on_page.dart +++ b/test/features/step/the_user_places_a_signature_placement_on_page.dart @@ -2,7 +2,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/the_user_places_it_in_multiple_locations_in_the_document.dart b/test/features/step/the_user_places_it_in_multiple_locations_in_the_document.dart index d2bb95f..8d19226 100644 --- a/test/features/step/the_user_places_it_in_multiple_locations_in_the_document.dart +++ b/test/features/step/the_user_places_it_in_multiple_locations_in_the_document.dart @@ -1,7 +1,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter/material.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the user places it in multiple locations in the document diff --git a/test/features/step/the_user_places_two_signature_placements_on_the_same_page.dart b/test/features/step/the_user_places_two_signature_placements_on_the_same_page.dart index ce159bf..1fd5b4c 100644 --- a/test/features/step/the_user_places_two_signature_placements_on_the_same_page.dart +++ b/test/features/step/the_user_places_two_signature_placements_on_the_same_page.dart @@ -2,7 +2,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/features/step/the_user_savesexports_the_document.dart b/test/features/step/the_user_savesexports_the_document.dart index 9f4860b..cb102b8 100644 --- a/test/features/step/the_user_savesexports_the_document.dart +++ b/test/features/step/the_user_savesexports_the_document.dart @@ -1,8 +1,8 @@ import 'dart:typed_data'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.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/signature_card_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the user saves/exports the document diff --git a/test/features/step/the_user_selects.dart b/test/features/step/the_user_selects.dart index 307b5f9..e203bd5 100644 --- a/test/features/step/the_user_selects.dart +++ b/test/features/step/the_user_selects.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the user selects "" diff --git a/test/features/step/the_user_types_into_the_go_to_input_and_presses_enter.dart b/test/features/step/the_user_types_into_the_go_to_input_and_presses_enter.dart index d28dfd6..ca2f721 100644 --- a/test/features/step/the_user_types_into_the_go_to_input_and_presses_enter.dart +++ b/test/features/step/the_user_types_into_the_go_to_input_and_presses_enter.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the user types {3} into the Go to input and presses Enter diff --git a/test/features/step/the_user_uses_rotate_controls.dart b/test/features/step/the_user_uses_rotate_controls.dart index a89be16..b47baf9 100644 --- a/test/features/step/the_user_uses_rotate_controls.dart +++ b/test/features/step/the_user_uses_rotate_controls.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import '_world.dart'; /// Usage: the user uses rotate controls diff --git a/test/features/step/three_signature_placements_are_placed_on_the_current_page.dart b/test/features/step/three_signature_placements_are_placed_on_the_current_page.dart index e78ae27..15660ef 100644 --- a/test/features/step/three_signature_placements_are_placed_on_the_current_page.dart +++ b/test/features/step/three_signature_placements_are_placed_on_the_current_page.dart @@ -2,9 +2,9 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pdf_signature/data/repositories/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/document_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_card_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import '_world.dart'; diff --git a/test/widget/export_flow_test.dart b/test/widget/export_flow_test.dart index e71f258..d3bb1b2 100644 --- a/test/widget/export_flow_test.dart +++ b/test/widget/export_flow_test.dart @@ -4,8 +4,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:pdf_signature/data/services/export_service.dart'; import 'package:pdf_signature/data/services/export_providers.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/signature_card_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/ui/features/pdf/widgets/pdf_screen.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; @@ -30,7 +30,7 @@ void main() { (ref) => DocumentStateNotifier()..openPicked(path: 'test.pdf'), ), signatureProvider.overrideWith( - (ref) => SignatureController()..placeDefaultRect(), + (ref) => SignatureCardStateNotifier()..placeDefaultRect(), ), useMockViewerProvider.overrideWith((ref) => true), exportServiceProvider.overrideWith((_) => fake), diff --git a/test/widget/helpers.dart b/test/widget/helpers.dart index 7965322..3a5fbc9 100644 --- a/test/widget/helpers.dart +++ b/test/widget/helpers.dart @@ -5,8 +5,8 @@ import 'package:image/image.dart' as img; import 'dart:typed_data'; import 'package:pdf_signature/ui/features/pdf/widgets/pdf_screen.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/signature_card_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/data/services/export_providers.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; // preferences_providers.dart no longer exports pageViewModeProvider @@ -19,7 +19,6 @@ Future pumpWithOpenPdf(WidgetTester tester) async { (ref) => DocumentStateNotifier()..openPicked(path: 'test.pdf'), ), useMockViewerProvider.overrideWith((ref) => true), - // Continuous mode is always-on; no page view override needed ], child: MaterialApp( localizationsDelegates: AppLocalizations.localizationsDelegates, @@ -54,12 +53,11 @@ Future pumpWithOpenPdfAndSig(WidgetTester tester) async { ), signatureProvider.overrideWith( (ref) => - SignatureController() + SignatureCardStateNotifier() ..setImageBytes(sigBytes) ..placeDefaultRect(), ), useMockViewerProvider.overrideWith((ref) => true), - // Continuous mode is always-on; no page view override needed ], child: MaterialApp( localizationsDelegates: AppLocalizations.localizationsDelegates, diff --git a/test/widget/pdf_navigation_widget_test.dart b/test/widget/pdf_navigation_widget_test.dart index 24c18de..d18a650 100644 --- a/test/widget/pdf_navigation_widget_test.dart +++ b/test/widget/pdf_navigation_widget_test.dart @@ -3,7 +3,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.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/document_repository.dart'; import 'package:pdf_signature/domain/models/model.dart'; import 'package:pdf_signature/data/services/export_providers.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; diff --git a/test/widget/pdf_page_area_early_jump_test.dart b/test/widget/pdf_page_area_early_jump_test.dart index 5e48ca3..dfe6a3e 100644 --- a/test/widget/pdf_page_area_early_jump_test.dart +++ b/test/widget/pdf_page_area_early_jump_test.dart @@ -3,7 +3,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; 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/document_repository.dart'; import 'package:pdf_signature/data/services/export_providers.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; import 'package:pdf_signature/domain/models/model.dart'; diff --git a/test/widget/pdf_page_area_jump_test.dart b/test/widget/pdf_page_area_jump_test.dart index 946483b..5a473e8 100644 --- a/test/widget/pdf_page_area_jump_test.dart +++ b/test/widget/pdf_page_area_jump_test.dart @@ -3,7 +3,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; 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/document_repository.dart'; import 'package:pdf_signature/data/services/export_providers.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; import 'package:pdf_signature/domain/models/model.dart'; diff --git a/test/widget/pdf_page_area_test.dart b/test/widget/pdf_page_area_test.dart index 62604d7..e8d8259 100644 --- a/test/widget/pdf_page_area_test.dart +++ b/test/widget/pdf_page_area_test.dart @@ -3,7 +3,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; 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/document_repository.dart'; import 'package:pdf_signature/data/services/export_providers.dart'; void main() { diff --git a/test/widget/regression_signature_tests.dart b/test/widget/regression_signature_tests.dart index e29b9e6..bd35c31 100644 --- a/test/widget/regression_signature_tests.dart +++ b/test/widget/regression_signature_tests.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.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/pdf_repository.dart'; +import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/ui/features/pdf/widgets/pdf_screen.dart'; import 'helpers.dart'; diff --git a/test/widget/welcome_drop_test.dart b/test/widget/welcome_drop_test.dart index d469876..37681ce 100644 --- a/test/widget/welcome_drop_test.dart +++ b/test/widget/welcome_drop_test.dart @@ -6,8 +6,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; import 'package:pdf_signature/ui/features/welcome/widgets/welcome_screen.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/signature_card_repository.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; class _FakeDropReadable implements DropReadable { final String _name;