diff --git a/integration_test/export_flow_test.dart b/integration_test/export_flow_test.dart index 812f848..792a29d 100644 --- a/integration_test/export_flow_test.dart +++ b/integration_test/export_flow_test.dart @@ -39,7 +39,7 @@ void main() { documentRepositoryProvider.overrideWith( (ref) => DocumentStateNotifier(service: ExportService()) - ..openPicked(pageCount: 3, bytes: pdfBytes), + ..openPickedWithPageCount(pageCount: 3, bytes: pdfBytes), ), pdfViewModelProvider.overrideWith( (ref) => PdfViewModel(ref, useMockViewer: false), @@ -95,7 +95,7 @@ void main() { documentRepositoryProvider.overrideWith( (ref) => DocumentStateNotifier(service: ExportService()) - ..openPicked(pageCount: 3, bytes: pdfBytes), + ..openPickedWithPageCount(pageCount: 3, bytes: pdfBytes), ), pdfViewModelProvider.overrideWith( (ref) => PdfViewModel(ref, useMockViewer: false), @@ -164,7 +164,7 @@ void main() { documentRepositoryProvider.overrideWith( (ref) => DocumentStateNotifier( service: ExportService(enableRaster: false), - )..openPicked(pageCount: 3, bytes: pdfBytes), + )..openPickedWithPageCount(pageCount: 3, bytes: pdfBytes), ), pdfViewModelProvider.overrideWith( (ref) => PdfViewModel(ref, useMockViewer: false), @@ -210,7 +210,7 @@ void main() { documentRepositoryProvider.overrideWith( (ref) => DocumentStateNotifier( service: ExportService(enableRaster: false), - )..openPicked(pageCount: 3, bytes: pdfBytes), + )..openPickedWithPageCount(pageCount: 3, bytes: pdfBytes), ), pdfViewModelProvider.overrideWith( (ref) => PdfViewModel(ref, useMockViewer: false), @@ -259,7 +259,7 @@ void main() { documentRepositoryProvider.overrideWith( (ref) => DocumentStateNotifier( service: ExportService(enableRaster: false), - )..openPicked(pageCount: 3, bytes: pdfBytes), + )..openPickedWithPageCount(pageCount: 3, bytes: pdfBytes), ), pdfViewModelProvider.overrideWith( (ref) => PdfViewModel(ref, useMockViewer: false), @@ -311,7 +311,7 @@ void main() { documentRepositoryProvider.overrideWith( (ref) => DocumentStateNotifier(service: ExportService()) - ..openPicked(pageCount: 3, bytes: pdfBytes), + ..openPickedWithPageCount(pageCount: 3, bytes: pdfBytes), ), pdfViewModelProvider.overrideWith( (ref) => PdfViewModel(ref, useMockViewer: false), @@ -363,7 +363,7 @@ void main() { documentRepositoryProvider.overrideWith( (ref) => DocumentStateNotifier(service: ExportService()) - ..openPicked(pageCount: 3, bytes: pdfBytes), + ..openPickedWithPageCount(pageCount: 3, bytes: pdfBytes), ), pdfViewModelProvider.overrideWith( (ref) => PdfViewModel(ref, useMockViewer: false), diff --git a/integration_test/pdf_view_test.dart b/integration_test/pdf_view_test.dart index 4cdc9af..15a78fc 100644 --- a/integration_test/pdf_view_test.dart +++ b/integration_test/pdf_view_test.dart @@ -34,7 +34,7 @@ void main() { documentRepositoryProvider.overrideWith( (ref) => DocumentStateNotifier() - ..openPicked(pageCount: 3, bytes: pdfBytes), + ..openPickedWithPageCount(pageCount: 3, bytes: pdfBytes), ), pdfViewModelProvider.overrideWith( (ref) => PdfViewModel(ref, useMockViewer: false), @@ -62,14 +62,31 @@ void main() { final vm = container.read(pdfViewModelProvider); expect(vm.currentPage, 1); - container.read(pdfViewModelProvider.notifier).jumpToPage(2); - await tester.pumpAndSettle(); - await tester.pump(const Duration(milliseconds: 120)); - expect(container.read(pdfViewModelProvider).currentPage, 2); + final controller = container.read(pdfViewModelProvider).controller; + // Wait until the underlying viewer controller reports ready. + final readyStart = DateTime.now(); + while (!controller.isReady) { + await tester.pump(const Duration(milliseconds: 40)); + if (DateTime.now().difference(readyStart) > const Duration(seconds: 5)) { + fail('PdfViewerController never became ready'); + } + } + Future goAndAwait(int target) async { + controller.goToPage(pageNumber: target); + final start = DateTime.now(); + while (container.read(pdfViewModelProvider).currentPage != target) { + await tester.pump(const Duration(milliseconds: 40)); + if (DateTime.now().difference(start) > const Duration(seconds: 3)) { + fail( + 'Timeout waiting to reach page $target (current=${container.read(pdfViewModelProvider).currentPage})', + ); + } + } + } - container.read(pdfViewModelProvider.notifier).jumpToPage(3); - await tester.pumpAndSettle(); - await tester.pump(const Duration(milliseconds: 120)); + await goAndAwait(2); + expect(container.read(pdfViewModelProvider).currentPage, 2); + await goAndAwait(3); expect(container.read(pdfViewModelProvider).currentPage, 3); }); @@ -88,7 +105,7 @@ void main() { documentRepositoryProvider.overrideWith( (ref) => DocumentStateNotifier() - ..openPicked(pageCount: 3, bytes: pdfBytes), + ..openPickedWithPageCount(pageCount: 3, bytes: pdfBytes), ), pdfViewModelProvider.overrideWith( (ref) => PdfViewModel(ref, useMockViewer: false), @@ -142,7 +159,7 @@ void main() { documentRepositoryProvider.overrideWith( (ref) => DocumentStateNotifier() - ..openPicked(pageCount: 3, bytes: pdfBytes), + ..openPickedWithPageCount(pageCount: 3, bytes: pdfBytes), ), pdfViewModelProvider.overrideWith( (ref) => PdfViewModel(ref, useMockViewer: false), @@ -229,7 +246,7 @@ void main() { documentRepositoryProvider.overrideWith( (ref) => DocumentStateNotifier() - ..openPicked(pageCount: 3, bytes: pdfBytes), + ..openPickedWithPageCount(pageCount: 3, bytes: pdfBytes), ), pdfViewModelProvider.overrideWith( (ref) => PdfViewModel(ref, useMockViewer: false), @@ -295,7 +312,7 @@ void main() { documentRepositoryProvider.overrideWith( (ref) => DocumentStateNotifier() - ..openPicked(pageCount: 3, bytes: pdfBytes), + ..openPickedWithPageCount(pageCount: 3, bytes: pdfBytes), ), pdfViewModelProvider.overrideWith( (ref) => PdfViewModel(ref, useMockViewer: false), @@ -339,4 +356,113 @@ void main() { await tester.pumpAndSettle(); expect(container.read(pdfViewModelProvider).currentPage, 3); }); + + testWidgets('PDF View: reopen another PDF via toolbar picker updates viewer', ( + tester, + ) async { + final initialBytes = + await File('integration_test/data/sample-local-pdf.pdf').readAsBytes(); + // 3 pages + final newBytes = + await File( + 'integration_test/data/PPFZ-Local-Purchase-Form.pdf', + ).readAsBytes(); + // 10 pages + SharedPreferences.setMockInitialValues({}); + final prefs = await SharedPreferences.getInstance(); + + // We'll override onPickPdf to simulate opening a new file with a different page count + // TODO: Replace PPFZ-Local-Purchase-Form.pdf with a 10-page PDF to test page count change + late ProviderContainer container; // capture to use inside callback + Future simulatePick() async { + container + .read(documentRepositoryProvider.notifier) + .openPicked(bytes: newBytes); + // Reset the current page explicitly to 1 as openPicked establishes new doc + container.read(pdfViewModelProvider.notifier).jumpToPage(1); + } + + int? lastDocPageCount; // capture page count from callback + await tester.pumpWidget( + ProviderScope( + overrides: [ + preferencesRepositoryProvider.overrideWith( + (ref) => PreferencesStateNotifier(prefs), + ), + documentRepositoryProvider.overrideWith( + (ref) => + DocumentStateNotifier() + ..openPickedWithPageCount(pageCount: 3, bytes: initialBytes), + ), + pdfViewModelProvider.overrideWith( + (ref) => PdfViewModel(ref, useMockViewer: false), + ), + ], + child: Builder( + builder: (context) { + container = ProviderScope.containerOf(context); + return MaterialApp( + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + locale: const Locale('en'), + home: PdfSignatureHomePage( + onPickPdf: simulatePick, + onClosePdf: () {}, + currentFile: XFile('initial.pdf'), + // The only reliable way to detect the new document load correctly + onDocumentChanged: (doc) { + if (doc != null) { + lastDocPageCount = doc.pages.length; + } + }, + ), + ); + }, + ), + ), + ); + + await tester.pumpAndSettle(); + // Verify initial state Page 1/3 + expect(find.byKey(const Key('lbl_page_info')), findsOneWidget); + final initialLabel = + tester.widget(find.byKey(const Key('lbl_page_info'))).data; + expect(initialLabel, contains('/3')); + + // Tap open picker button to simulate opening new PDF + await tester.tap(find.byKey(const Key('btn_open_pdf_picker'))); + // Allow frame to process state changes from simulatePick + await tester.pump(); + await tester.pump(const Duration(milliseconds: 50)); + await tester.pumpAndSettle(); + + // Wait for async page count detection to complete in repository + await tester.runAsync(() async { + final start = DateTime.now(); + while (container.read(documentRepositoryProvider).pageCount != 10) { + await Future.delayed(const Duration(milliseconds: 50)); + await tester.pump(); + + if (DateTime.now().difference(start) > const Duration(seconds: 8)) { + final pageCount = + container.read(documentRepositoryProvider).pageCount; + fail( + 'Timeout waiting for repository page count to update to 10 (current=$pageCount)', + ); + } + } + + // Wait for restoration mechanism to complete + await Future.delayed(const Duration(milliseconds: 500)); + await tester.pump(); + }); + + final updatedLabel = + tester.widget(find.byKey(const Key('lbl_page_info'))).data; + expect(updatedLabel, contains('/10')); + // Verify that repository correctly analyzed PDF bytes and updated page count + expect(container.read(documentRepositoryProvider).pageCount, 10); + expect(lastDocPageCount, 10); + expect(container.read(pdfViewModelProvider).currentPage, 1); + }); } diff --git a/lib/data/repositories/document_repository.dart b/lib/data/repositories/document_repository.dart index 94c4ba8..7df5593 100644 --- a/lib/data/repositories/document_repository.dart +++ b/lib/data/repositories/document_repository.dart @@ -4,6 +4,7 @@ import 'package:image/image.dart' as img; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:pdf_signature/data/services/export_service.dart'; +import 'package:pdfrx/pdfrx.dart'; import '../../domain/models/model.dart'; @@ -24,7 +25,61 @@ class DocumentStateNotifier extends StateNotifier { ); } - void openPicked({required int pageCount, Uint8List? bytes}) { + void openPicked({Uint8List? bytes}) { + debugPrint( + '[DocumentRepository] openPicked called (bytes length: ${bytes?.length})', + ); + + // For real usage, determine page count from PDF bytes asynchronously + if (bytes != null) { + _openPickedAsync(bytes); + } else { + // Handle null bytes case + state = state.copyWith( + loaded: true, + pageCount: 1, + pickedPdfBytes: bytes, + placementsByPage: >{}, + ); + } + } + + Future _openPickedAsync(Uint8List bytes) async { + int pageCount = 1; // default fallback + + try { + // Determine actual page count from PDF bytes + final doc = await PdfDocument.openData(bytes); + pageCount = doc.pages.length; + debugPrint('[DocumentRepository] PDF has $pageCount pages'); + } catch (e) { + debugPrint('[DocumentRepository] Failed to read PDF page count: $e'); + // Keep default pageCount = 1 on error + } + + state = state.copyWith( + loaded: true, + pageCount: pageCount, + pickedPdfBytes: bytes, + placementsByPage: >{}, + ); + + // Schedule delayed check to ensure our page count wasn't overridden by UI callbacks + Future.delayed(const Duration(milliseconds: 100), () { + if (state.loaded && + state.pickedPdfBytes == bytes && + state.pageCount != pageCount) { + state = state.copyWith(pageCount: pageCount); + } + }); + } + + // For tests that need to specify page count explicitly + @visibleForTesting + void openPickedWithPageCount({required int pageCount, Uint8List? bytes}) { + debugPrint( + '[DocumentRepository] openPickedWithPageCount called (pageCount=$pageCount)', + ); state = state.copyWith( loaded: true, pageCount: pageCount, @@ -39,6 +94,9 @@ class DocumentStateNotifier extends StateNotifier { void setPageCount(int count) { if (!state.loaded) return; + debugPrint( + '[DocumentRepository] setPageCount called: $count (current: ${state.pageCount})', + ); state = state.copyWith(pageCount: count.clamp(1, 9999)); } diff --git a/lib/main.dart b/lib/main.dart index 8862cce..2f0d15e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,12 +1,33 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:pdfrx/pdfrx.dart'; +import 'package:path_provider/path_provider.dart'; +import 'dart:io'; import 'package:pdf_signature/app.dart'; export 'package:pdf_signature/app.dart'; -void main() { - // Ensure Flutter bindings are initialized before platform channel usage +Future _initPdfrxCache() async { + try { + // Only set once; guard for hot reload/tests + if (Pdfrx.getCacheDirectory == null) { + final dir = await getTemporaryDirectory(); + final cacheDir = Directory('${dir.path}/pdfrx_cache'); + if (!await cacheDir.exists()) { + await cacheDir.create(recursive: true); + } + Pdfrx.getCacheDirectory = () async => cacheDir.path; + debugPrint('[main] Pdfrx cache directory set to ${cacheDir.path}'); + } + } catch (e, st) { + debugPrint('[main] Failed to initialize Pdfrx cache directory: $e'); + debugPrint(st.toString()); + } +} + +Future main() async { WidgetsFlutterBinding.ensureInitialized(); + await _initPdfrxCache(); // Disable right-click context menu on web using Flutter API if (kReleaseMode) { debugPrint = (String? message, {int? wrapWidth}) { diff --git a/lib/routing/router.dart b/lib/routing/router.dart index f817702..8c489b6 100644 --- a/lib/routing/router.dart +++ b/lib/routing/router.dart @@ -33,7 +33,7 @@ final routerProvider = Provider((ref) { ({String? path, Uint8List? bytes, String? fileName}) => sessionVm.openPdf( path: path, - bytes: bytes, + bytes: bytes ?? Uint8List(0), fileName: fileName, ), ); diff --git a/lib/ui/features/pdf/view_model/document_version.dart b/lib/ui/features/pdf/view_model/document_version.dart new file mode 100644 index 0000000..c51bbb4 --- /dev/null +++ b/lib/ui/features/pdf/view_model/document_version.dart @@ -0,0 +1,31 @@ +import 'dart:typed_data'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'document_version.freezed.dart'; + +/// Internal data model for tracking document versions in the UI layer. +/// This is separate from the domain Document model to avoid coupling UI concerns with business logic. +@freezed +abstract class DocumentVersion with _$DocumentVersion { + const factory DocumentVersion({ + @Default(0) int version, + Uint8List? lastBytes, + }) = _DocumentVersion; + + factory DocumentVersion.initial() => const DocumentVersion(); +} + +extension DocumentVersionMethods on DocumentVersion { + /// Generate the source name for PdfDocumentRefData based on version + String get sourceName => 'document_v$version.pdf'; + + /// Check if bytes have changed and need version increment + bool shouldIncrementVersion(Uint8List? newBytes) { + return !identical(lastBytes, newBytes); + } + + /// Increment version and update bytes + DocumentVersion incrementVersion(Uint8List? newBytes) { + return copyWith(version: version + 1, lastBytes: newBytes); + } +} diff --git a/lib/ui/features/pdf/view_model/pdf_view_model.dart b/lib/ui/features/pdf/view_model/pdf_view_model.dart index 32a4b64..5b49cee 100644 --- a/lib/ui/features/pdf/view_model/pdf_view_model.dart +++ b/lib/ui/features/pdf/view_model/pdf_view_model.dart @@ -5,9 +5,11 @@ import 'package:flutter_riverpod/flutter_riverpod.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 'package:pdf_signature/ui/features/pdf/view_model/document_version.dart'; import 'package:pdfrx/pdfrx.dart'; import 'package:file_picker/file_picker.dart' as fp; import 'package:go_router/go_router.dart'; +import 'package:path_provider/path_provider.dart'; class PdfViewModel extends ChangeNotifier { final Ref ref; @@ -31,6 +33,26 @@ class PdfViewModel extends ChangeNotifier { final Set _lockedPlacements = {}; Set get lockedPlacements => Set.unmodifiable(_lockedPlacements); + // Document version tracking for UI consistency + DocumentVersion _documentVersion = DocumentVersion.initial(); + + // Get current document source name for PdfDocumentRefData + String get documentSourceName { + // Ensure document version is up to date, but only update if really needed + _updateDocumentVersionIfNeeded(); + return _documentVersion.sourceName; + } + + void _updateDocumentVersionIfNeeded() { + final document = ref.read(documentRepositoryProvider); + if (!identical(_documentVersion.lastBytes, document.pickedPdfBytes)) { + _documentVersion = DocumentVersion( + version: _documentVersion.version + 1, + lastBytes: document.pickedPdfBytes, + ); + } + } + // const bool.fromEnvironment('FLUTTER_TEST', defaultValue: false); PdfViewModel(this.ref, {bool? useMockViewer}) : _useMockViewer = @@ -275,30 +297,59 @@ class PdfSessionViewModel extends ChangeNotifier { if (effectiveBytes == null && path != null && path.isNotEmpty) { try { effectiveBytes = await XFile(path).readAsBytes(); - } catch (_) { + } catch (e, st) { effectiveBytes = null; + debugPrint( + '[PdfSessionViewModel] Failed to read PDF data from path=$path error=$e', + ); + debugPrint(st.toString()); } } - await openPdf(path: path, bytes: effectiveBytes, fileName: name); + if (effectiveBytes != null) { + await openPdf(path: path, bytes: effectiveBytes, fileName: name); + } else { + debugPrint( + '[PdfSessionViewModel] No PDF data available to open (path=$path, name=$name)', + ); + } } Future openPdf({ String? path, - Uint8List? bytes, + required Uint8List bytes, String? fileName, }) async { int pageCount = 1; // default - if (bytes != null) { - try { - final doc = await PdfDocument.openData(bytes); - pageCount = doc.pages.length; - } catch (_) { - // ignore invalid bytes + try { + // Defensive: ensure Pdfrx cache directory set (in case main init skipped in tests) + if (Pdfrx.getCacheDirectory == null) { + debugPrint( + '[PdfSessionViewModel] Pdfrx.getCacheDirectory was null; setting temp directory', + ); + try { + final temp = await getTemporaryDirectory(); + Pdfrx.getCacheDirectory = () async => temp.path; + } catch (e, st) { + debugPrint( + '[PdfSessionViewModel] Failed to set fallback cache dir error=$e', + ); + debugPrint(st.toString()); + } } + final doc = await PdfDocument.openData(bytes); + pageCount = doc.pages.length; + debugPrint( + '[PdfSessionViewModel] Opened PDF bytes length=${bytes.length} pages=$pageCount', + ); + } catch (e, st) { + debugPrint( + '[PdfSessionViewModel] Failed to read PDF data from bytes error=$e', + ); + debugPrint(st.toString()); } if (path != null && path.isNotEmpty) { _currentFile = XFile(path); - } else if (bytes != null && (fileName != null && fileName.isNotEmpty)) { + } else if ((fileName != null && fileName.isNotEmpty)) { // Keep in-memory XFile so .name is available for suggestion try { _currentFile = XFile.fromData( @@ -306,8 +357,12 @@ class PdfSessionViewModel extends ChangeNotifier { name: fileName, mimeType: 'application/pdf', ); - } catch (_) { + } catch (e, st) { _currentFile = XFile(fileName); + debugPrint( + '[PdfSessionViewModel] Failed to create XFile.fromData name=$fileName error=$e', + ); + debugPrint(st.toString()); } } else { _currentFile = XFile(''); @@ -322,13 +377,14 @@ class PdfSessionViewModel extends ChangeNotifier { } else { _displayFileName = ''; } - ref - .read(documentRepositoryProvider.notifier) - .openPicked(pageCount: pageCount, bytes: bytes); + debugPrint('[PdfSessionViewModel] Calling openPicked with bytes'); + ref.read(documentRepositoryProvider.notifier).openPicked(bytes: bytes); // Keep existing signature cards when opening a new document. // The feature "Open a different document will reset signature placements but keep signature cards" // relies on this behavior. Placements are reset by openPicked() above. + debugPrint('[PdfSessionViewModel] Navigating to /pdf'); router.go('/pdf'); + debugPrint('[PdfSessionViewModel] Notifying listeners after open'); notifyListeners(); } diff --git a/lib/ui/features/pdf/widgets/pdf_page_area.dart b/lib/ui/features/pdf/widgets/pdf_page_area.dart index 35a4130..1579dcf 100644 --- a/lib/ui/features/pdf/widgets/pdf_page_area.dart +++ b/lib/ui/features/pdf/widgets/pdf_page_area.dart @@ -13,10 +13,12 @@ class PdfPageArea extends ConsumerStatefulWidget { super.key, required this.pageSize, required this.controller, + this.onDocumentChanged, }); final Size pageSize; final PdfViewerController controller; + final void Function(PdfDocument?)? onDocumentChanged; @override ConsumerState createState() => _PdfPageAreaState(); } @@ -163,7 +165,9 @@ class _PdfPageAreaState extends ConsumerState { pageKeyBuilder: _pageKey, scrollToPage: _scrollToPage, controller: widget.controller, - innerViewerKey: const ValueKey('viewer_idle'), + // Remove fixed innerViewerKey to allow PdfViewerWidget to generate dynamic keys + // innerViewerKey: const ValueKey('viewer_idle'), + onDocumentChanged: widget.onDocumentChanged, ); } return const SizedBox.shrink(); diff --git a/lib/ui/features/pdf/widgets/pdf_screen.dart b/lib/ui/features/pdf/widgets/pdf_screen.dart index ddb0372..2baa017 100644 --- a/lib/ui/features/pdf/widgets/pdf_screen.dart +++ b/lib/ui/features/pdf/widgets/pdf_screen.dart @@ -29,6 +29,8 @@ class PdfSignatureHomePage extends ConsumerStatefulWidget { // available, this name preserves the user-selected filename so we can // suggest a proper "signed_*.pdf" on save. final String? currentFileName; + // Optional listener for underlying Pdfrx document change events. + final void Function(PdfDocument?)? onDocumentChanged; const PdfSignatureHomePage({ super.key, @@ -36,6 +38,7 @@ class PdfSignatureHomePage extends ConsumerStatefulWidget { required this.onClosePdf, required this.currentFile, this.currentFileName, + this.onDocumentChanged, }); @override @@ -333,7 +336,7 @@ class _PdfSignatureHomePageState extends ConsumerState { pdf.loaded && pdf.pickedPdfBytes != null ? PdfDocumentRefData( pdf.pickedPdfBytes!, - sourceName: 'document.pdf', + sourceName: pdfViewModel.documentSourceName, ) : null; @@ -354,6 +357,7 @@ class _PdfSignatureHomePageState extends ConsumerState { controller: _viewModel.controller, key: const ValueKey('pdf_page_area'), pageSize: _pageSize, + onDocumentChanged: widget.onDocumentChanged, ), ), ), diff --git a/lib/ui/features/pdf/widgets/pdf_toolbar.dart b/lib/ui/features/pdf/widgets/pdf_toolbar.dart index 504d54e..362d4d5 100644 --- a/lib/ui/features/pdf/widgets/pdf_toolbar.dart +++ b/lib/ui/features/pdf/widgets/pdf_toolbar.dart @@ -5,6 +5,7 @@ import 'package:pdf_signature/l10n/app_localizations.dart'; import 'package:responsive_framework/responsive_framework.dart'; import 'package:pdf_signature/ui/features/pdf/view_model/pdf_view_model.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; class PdfToolbar extends ConsumerStatefulWidget { const PdfToolbar({ @@ -59,7 +60,9 @@ class _PdfToolbarState extends ConsumerState { @override Widget build(BuildContext context) { final pdfViewModel = ref.watch(pdfViewModelProvider); - final pdf = pdfViewModel.document; + final pdf = ref.watch( + documentRepositoryProvider, + ); // Watch document directly for updates final currentPage = pdfViewModel.currentPage; final l = AppLocalizations.of(context); final pageInfo = l.pageInfo(currentPage, pdf.pageCount); diff --git a/lib/ui/features/pdf/widgets/pdf_viewer_widget.dart b/lib/ui/features/pdf/widgets/pdf_viewer_widget.dart index 58a65b1..dadf2d6 100644 --- a/lib/ui/features/pdf/widgets/pdf_viewer_widget.dart +++ b/lib/ui/features/pdf/widgets/pdf_viewer_widget.dart @@ -5,6 +5,9 @@ import 'package:pdf_signature/l10n/app_localizations.dart'; import 'pdf_page_overlays.dart'; import './pdf_mock_continuous_list.dart'; import '../view_model/pdf_view_model.dart'; +import 'package:pdf_signature/domain/models/document.dart'; +import 'package:pdf_signature/data/repositories/document_repository.dart'; +import 'dart:typed_data'; // Provider to control whether viewer overlays (like scroll thumbs) are enabled. // Integration tests can override this to false to avoid long-running animations. @@ -18,6 +21,7 @@ class PdfViewerWidget extends ConsumerStatefulWidget { this.scrollToPage, required this.controller, this.innerViewerKey, + this.onDocumentChanged, }); final Size pageSize; @@ -26,13 +30,43 @@ class PdfViewerWidget extends ConsumerStatefulWidget { final PdfViewerController controller; // Optional key applied to the inner Pdfrx PdfViewer to force disposal/rebuild final Key? innerViewerKey; + // External hook to observe document changes (forwarded from Pdfrx onDocumentChanged) + final void Function(PdfDocument?)? onDocumentChanged; @override ConsumerState createState() => _PdfViewerWidgetState(); } class _PdfViewerWidgetState extends ConsumerState { - PdfDocumentRef? _documentRef; + final ValueNotifier _docRefNotifier = ValueNotifier(null); + Uint8List? _lastBytes; + void _updateDocRef(Document doc) { + if (!doc.loaded || doc.pickedPdfBytes == null) { + if (_docRefNotifier.value != null) { + debugPrint('[PdfViewerWidget] Clearing docRef (no document loaded)'); + _docRefNotifier.value = null; + } + return; + } + final bytes = doc.pickedPdfBytes!; + if (!identical(bytes, _lastBytes)) { + _lastBytes = bytes; + final viewModel = ref.read(pdfViewModelProvider); + debugPrint( + '[PdfViewerWidget] New PDF bytes detected -> ${viewModel.documentSourceName}', + ); + // Force a full detach by setting null first so PdfViewer unmounts even if the + // framework would otherwise optimize rebuilds with same key ordering. + if (_docRefNotifier.value != null) { + _docRefNotifier.value = null; + } + final newRef = PdfDocumentRefData( + bytes, + sourceName: viewModel.documentSourceName, + ); + _docRefNotifier.value = newRef; + } + } // Public getter for testing the actual viewer page int? get viewerCurrentPage => widget.controller.pageNumber; @@ -51,31 +85,9 @@ class _PdfViewerWidgetState extends ConsumerState { @override Widget build(BuildContext context) { final pdfViewModel = ref.watch(pdfViewModelProvider); - final document = pdfViewModel.document; + final document = ref.watch(documentRepositoryProvider); final useMock = pdfViewModel.useMockViewer; - // trigger rebuild when active rect changes - - // Update document ref when document changes - if (document.loaded && document.pickedPdfBytes != null) { - if (_documentRef == null) { - _documentRef = PdfDocumentRefData( - document.pickedPdfBytes!, - sourceName: 'document.pdf', - ); - } - } else { - _documentRef = null; - } - - if (_documentRef == null && !useMock) { - String text; - try { - text = AppLocalizations.of(context).noPdfLoaded; - } catch (_) { - text = 'No PDF loaded'; - } - return Center(child: Text(text)); - } + _updateDocRef(document); if (useMock) { return PdfMockContinuousList( @@ -89,80 +101,119 @@ class _PdfViewerWidgetState extends ConsumerState { } final overlaysEnabled = ref.watch(viewerOverlaysEnabledProvider); - return PdfViewer( - _documentRef!, - key: widget.innerViewerKey ?? const Key('pdf_continuous_mock_list'), - controller: widget.controller, - params: PdfViewerParams( - onViewerReady: (document, controller) { - // Update page count in repository - ref - .read(pdfViewModelProvider.notifier) - .setPageCount(document.pages.length); - }, - onPageChanged: (page) { - if (page != null) { - // Also update the view model to keep them in sync - ref.read(pdfViewModelProvider.notifier).jumpToPage(page); + return ValueListenableBuilder( + valueListenable: _docRefNotifier, + builder: (context, docRef, _) { + if (docRef == null) { + String text; + try { + text = AppLocalizations.of(context).noPdfLoaded; + } catch (_) { + text = 'No PDF loaded'; } - }, - viewerOverlayBuilder: - overlaysEnabled - ? (context, size, handle) { - return [ - // Vertical scroll thumb on the right - PdfViewerScrollThumb( - controller: widget.controller, - orientation: ScrollbarOrientation.right, - thumbSize: const Size(40, 25), - thumbBuilder: - (context, thumbSize, pageNumber, controller) => - Container( - color: Colors.black.withValues(alpha: 0.7), - child: Center( - child: Text( - 'Pg $pageNumber', - style: const TextStyle( - color: Colors.white, - fontSize: 12, + return Center(child: Text(text)); + } + final pdfViewModel = ref.read(pdfViewModelProvider); + final viewerKey = + widget.innerViewerKey ?? + Key('pdf_viewer_${pdfViewModel.documentSourceName}'); + + return PdfViewer( + docRef, + key: viewerKey, + controller: widget.controller, + params: PdfViewerParams( + onViewerReady: (document, controller) { + // Update page count in repository + ref + .read(pdfViewModelProvider.notifier) + .setPageCount(document.pages.length); + }, + onPageChanged: (page) { + if (page != null) { + // Also update the view model to keep them in sync + ref.read(pdfViewModelProvider.notifier).jumpToPage(page); + } + }, + onDocumentChanged: (doc) async { + final pc = doc?.pages.length; + debugPrint( + '[PdfViewerWidget] onDocumentChanged called (pages=$pc)', + ); + if (doc != null) { + // Update internal page count state + ref + .read(pdfViewModelProvider.notifier) + .setPageCount(doc.pages.length); + } + // Invoke external listener after internal handling + try { + widget.onDocumentChanged?.call(doc); + } catch (e, st) { + debugPrint( + '[PdfViewerWidget] external onDocumentChanged threw: $e\n$st', + ); + } + }, + viewerOverlayBuilder: + overlaysEnabled + ? (context, size, handle) { + return [ + // Vertical scroll thumb on the right + PdfViewerScrollThumb( + controller: widget.controller, + orientation: ScrollbarOrientation.right, + thumbSize: const Size(40, 25), + thumbBuilder: + (context, thumbSize, pageNumber, controller) => + Container( + color: Colors.black.withValues(alpha: 0.7), + child: Center( + child: Text( + 'Pg $pageNumber', + style: const TextStyle( + color: Colors.white, + fontSize: 12, + ), + ), ), ), - ), - ), - ), - // Horizontal scroll thumb on the bottom - PdfViewerScrollThumb( - controller: widget.controller, - orientation: ScrollbarOrientation.bottom, - thumbSize: const Size(40, 25), - thumbBuilder: - (context, thumbSize, pageNumber, controller) => - Container( - color: Colors.black.withValues(alpha: 0.7), - child: Center( - child: Text( - 'Pg $pageNumber', - style: const TextStyle( - color: Colors.white, - fontSize: 12, + ), + // Horizontal scroll thumb on the bottom + PdfViewerScrollThumb( + controller: widget.controller, + orientation: ScrollbarOrientation.bottom, + thumbSize: const Size(40, 25), + thumbBuilder: + (context, thumbSize, pageNumber, controller) => + Container( + color: Colors.black.withValues(alpha: 0.7), + child: Center( + child: Text( + 'Pg $pageNumber', + style: const TextStyle( + color: Colors.white, + fontSize: 12, + ), + ), ), ), - ), - ), - ), - ]; - } - : (context, size, handle) => const [], - // Per-page overlays to enable page-specific drag targets and placed signatures - pageOverlaysBuilder: (context, pageRect, page) { - return [ - PdfPageOverlays( - pageSize: Size(pageRect.width, pageRect.height), - pageNumber: page.pageNumber, - ), - ]; - }, - ), + ), + ]; + } + : (context, size, handle) => const [], + // Per-page overlays to enable page-specific drag targets and placed signatures + pageOverlaysBuilder: (context, pageRect, page) { + return [ + PdfPageOverlays( + pageSize: Size(pageRect.width, pageRect.height), + pageNumber: page.pageNumber, + ), + ]; + }, + ), + ); + }, ); } } diff --git a/lib/ui/features/welcome/view_model/welcome_view_model.dart b/lib/ui/features/welcome/view_model/welcome_view_model.dart index a6037ed..8a17753 100644 --- a/lib/ui/features/welcome/view_model/welcome_view_model.dart +++ b/lib/ui/features/welcome/view_model/welcome_view_model.dart @@ -1,4 +1,4 @@ -import 'dart:typed_data'; +import 'package:flutter/foundation.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:pdf_signature/ui/features/pdf/view_model/pdf_view_model.dart'; import 'package:go_router/go_router.dart'; @@ -11,6 +11,14 @@ class WelcomeViewModel { WelcomeViewModel(this.ref, this.router); Future openPdf({required String path, Uint8List? bytes}) async { + // Return early if no bytes provided - can't open PDF without data + if (bytes == null) { + debugPrint( + '[WelcomeViewModel] Cannot open PDF: no bytes provided for $path', + ); + return; + } + // Use PdfSessionViewModel to open and navigate. final session = ref.read(pdfSessionViewModelProvider(router)); await session.openPdf(path: path, bytes: bytes); 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 4bf6406..6093b94 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 @@ -12,7 +12,7 @@ Future aDocumentIsOpenAndContainsAtLeastOneSignaturePlacement( ) async { final container = TestWorld.container ?? ProviderContainer(); TestWorld.container = container; - container.read(documentRepositoryProvider.notifier).openPicked(pageCount: 5); + container.read(documentRepositoryProvider.notifier).openPickedWithPageCount(pageCount: 5); container .read(documentRepositoryProvider.notifier) .addPlacement( 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 4f014cf..86cc001 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 @@ -13,7 +13,7 @@ aDocumentIsOpenAndContainsMultiplePlacedSignaturePlacementsAcrossPages( ) async { final container = TestWorld.container ?? ProviderContainer(); TestWorld.container = container; - container.read(documentRepositoryProvider.notifier).openPicked(pageCount: 5); + container.read(documentRepositoryProvider.notifier).openPickedWithPageCount(pageCount: 5); container .read(documentRepositoryProvider.notifier) .addPlacement( 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 8ccccff..5052e00 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 @@ -11,6 +11,6 @@ Future aDocumentIsOpenWithNoSignaturePlacementsPlaced( TestWorld.container = container; container .read(documentRepositoryProvider.notifier) - .openPicked(pageCount: 5); + .openPickedWithPageCount(pageCount: 5); // No placements added } 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 3af7083..77485a9 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 @@ -11,7 +11,7 @@ Future aDocumentPageIsSelectedForSigning(WidgetTester tester) async { // Ensure a document is open final repo = container.read(documentRepositoryProvider.notifier); if (!container.read(documentRepositoryProvider).loaded) { - repo.openPicked(pageCount: 5); + repo.openPickedWithPageCount(pageCount: 5); } // Ensure current page is 1 for consistent subsequent steps try { diff --git a/test/features/step/a_multipage_document_is_open.dart b/test/features/step/a_multipage_document_is_open.dart index fceb6ec..f3201ef 100644 --- a/test/features/step/a_multipage_document_is_open.dart +++ b/test/features/step/a_multipage_document_is_open.dart @@ -18,7 +18,7 @@ Future aMultipageDocumentIsOpen(WidgetTester tester) async { container.read(signatureCardRepositoryProvider.notifier).state = [ SignatureCard.initial(), ]; - container.read(documentRepositoryProvider.notifier).openPicked(pageCount: 5); + container.read(documentRepositoryProvider.notifier).openPickedWithPageCount(pageCount: 5); // Reset page state providers try { container.read(pdfViewModelProvider.notifier).jumpToPage(1); 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 29660f2..54ec731 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 @@ -11,5 +11,5 @@ Future aSampleMultipageDocument5PagesIsAvailable( TestWorld.container = container; container .read(documentRepositoryProvider.notifier) - .openPicked(pageCount: 5); + .openPickedWithPageCount(pageCount: 5); } 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 251686a..f118576 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 @@ -17,7 +17,7 @@ Future aSignatureAssetIsPlacedOnThePage(WidgetTester tester) async { if (!container.read(documentRepositoryProvider).loaded) { container .read(documentRepositoryProvider.notifier) - .openPicked(pageCount: 5); + .openPickedWithPageCount(pageCount: 5); } // Get or create an asset 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 92ec293..1e42487 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 @@ -17,7 +17,7 @@ Future aSignaturePlacementIsPlacedOnPage( if (!container.read(documentRepositoryProvider).loaded) { container .read(documentRepositoryProvider.notifier) - .openPicked(pageCount: 5); + .openPickedWithPageCount(pageCount: 5); } final page = param1.toInt(); container 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 8b5b161..b3ec08f 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 @@ -16,7 +16,7 @@ Future aSignaturePlacementIsPlacedWithAPositionAndSizeRelativeToThePage( if (!container.read(documentRepositoryProvider).loaded) { container .read(documentRepositoryProvider.notifier) - .openPicked(pageCount: 5); + .openPickedWithPageCount(pageCount: 5); } final currentPage = container.read(pdfViewModelProvider).currentPage; container 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 17da18c..c0c49e4 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 @@ -25,7 +25,7 @@ theUserDragsItOnThePageOfTheDocumentToPlaceSignaturePlacementsInMultipleLocation if (!container.read(documentRepositoryProvider).loaded) { container .read(documentRepositoryProvider.notifier) - .openPicked(pageCount: 5); + .openPickedWithPageCount(pageCount: 5); } container 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 7448cc5..83179aa 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 @@ -21,7 +21,7 @@ theUserDragsThisSignatureCardOnThePageOfTheDocumentToPlaceASignaturePlacement( if (!container.read(documentRepositoryProvider).loaded) { container .read(documentRepositoryProvider.notifier) - .openPicked(pageCount: 5); + .openPickedWithPageCount(pageCount: 5); } // Get or create an asset diff --git a/test/features/step/the_user_opens_a_different_document_with_pages.dart b/test/features/step/the_user_opens_a_different_document_with_pages.dart index ef48ae6..3f62744 100644 --- a/test/features/step/the_user_opens_a_different_document_with_pages.dart +++ b/test/features/step/the_user_opens_a_different_document_with_pages.dart @@ -19,7 +19,7 @@ Future theUserOpensADifferentDocumentWithPages( // Simulate "open a different document": reset placements and set page count. container .read(documentRepositoryProvider.notifier) - .openPicked(pageCount: pageCount); + .openPickedWithPageCount(pageCount: pageCount); // Ensure there are 2 signature cards available as per scenario. final cards = container.read(signatureCardRepositoryProvider); if (cards.length < 2) { 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 b48c7cf..b2e5612 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 @@ -12,7 +12,7 @@ Future theUserPlacesItInMultipleLocationsInTheDocument( TestWorld.container = container; final notifier = container.read(documentRepositoryProvider.notifier); // Always open a fresh doc to avoid state bleed between scenarios - notifier.openPicked(pageCount: 6); + notifier.openPickedWithPageCount(pageCount: 6); // Place two on page 2 and one on page 4 notifier.addPlacement(page: 2, rect: const Rect.fromLTWH(10, 10, 80, 40)); notifier.addPlacement(page: 2, rect: const Rect.fromLTWH(120, 50, 80, 40)); diff --git a/test/features/step/the_user_savesexports_the_document.dart b/test/features/step/the_user_savesexports_the_document.dart index b3f785a..e7d52fa 100644 --- a/test/features/step/the_user_savesexports_the_document.dart +++ b/test/features/step/the_user_savesexports_the_document.dart @@ -17,7 +17,7 @@ Future theUserSavesexportsTheDocument(WidgetTester tester) async { // Load a minimal sample so the expectation passes in logic-only tests container .read(documentRepositoryProvider.notifier) - .openPicked(pageCount: 2, bytes: Uint8List(10)); + .openPickedWithPageCount(pageCount: 2, bytes: Uint8List(10)); } expect(pdf.loaded, isTrue, reason: 'PDF must be loaded before export'); // Check if there are placements diff --git a/test/features/step/the_user_selects.dart b/test/features/step/the_user_selects.dart index 9580e06..2a361f7 100644 --- a/test/features/step/the_user_selects.dart +++ b/test/features/step/the_user_selects.dart @@ -10,7 +10,7 @@ Future theUserSelects(WidgetTester tester, dynamic file) async { final container = ProviderContainer(); TestWorld.container = container; // Mark page for signing to enable signature ops - container.read(documentRepositoryProvider.notifier).openPicked(pageCount: 1); + container.read(documentRepositoryProvider.notifier).openPickedWithPageCount(pageCount: 1); // For invalid/unsupported/empty selections we do NOT set image bytes. // This simulates a failed load and keeps rect null. final token = file.toString(); 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 c99fb1b..0797cbf 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 @@ -22,7 +22,7 @@ Future threeSignaturePlacementsArePlacedOnTheCurrentPage( container.read(signatureCardRepositoryProvider.notifier).state = [ SignatureCard.initial(), ]; - container.read(documentRepositoryProvider.notifier).openPicked(pageCount: 5); + container.read(documentRepositoryProvider.notifier).openPickedWithPageCount(pageCount: 5); final pdfN = container.read(documentRepositoryProvider.notifier); final page = container.read(pdfViewModelProvider).currentPage; pdfN.addPlacement( diff --git a/test/widget/export_flow_test.dart b/test/widget/export_flow_test.dart index b70ae1d..4cafb36 100644 --- a/test/widget/export_flow_test.dart +++ b/test/widget/export_flow_test.dart @@ -49,7 +49,7 @@ void main() { documentRepositoryProvider.overrideWith( (ref) => DocumentStateNotifier() - ..openPicked(pageCount: 5, bytes: Uint8List(0)), + ..openPickedWithPageCount(pageCount: 5, bytes: Uint8List(0)), ), pdfViewModelProvider.overrideWith( (ref) => PdfViewModel(ref, useMockViewer: true), diff --git a/test/widget/pdf_thumbnail_sync_test.dart b/test/widget/pdf_thumbnail_sync_test.dart new file mode 100644 index 0000000..3b5b7d3 --- /dev/null +++ b/test/widget/pdf_thumbnail_sync_test.dart @@ -0,0 +1,33 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:pdf_signature/ui/features/pdf/view_model/document_version.dart'; +import 'dart:typed_data'; + +void main() { + group('DocumentVersion', () { + test('should generate consistent source names', () { + final version1 = DocumentVersion(version: 1); + final version2 = DocumentVersion(version: 2); + + expect(version1.sourceName, 'document_v1.pdf'); + expect(version2.sourceName, 'document_v2.pdf'); + }); + + test('should increment version when bytes change', () { + final bytes1 = Uint8List.fromList([1, 2, 3]); + final bytes2 = Uint8List.fromList([4, 5, 6]); + + final version = DocumentVersion(version: 1, lastBytes: bytes1); + + expect(version.shouldIncrementVersion(bytes2), true); + expect(version.shouldIncrementVersion(bytes1), false); + }); + + test('should detect identical bytes correctly', () { + final bytes = Uint8List.fromList([1, 2, 3]); + final version = DocumentVersion(version: 1, lastBytes: bytes); + + // Same bytes object should not trigger increment + expect(version.shouldIncrementVersion(bytes), false); + }); + }); +} diff --git a/test/widget/welcome_drop_test.dart b/test/widget/welcome_drop_test.dart index 3ada86d..fcf1136 100644 --- a/test/widget/welcome_drop_test.dart +++ b/test/widget/welcome_drop_test.dart @@ -51,7 +51,7 @@ void main() { }) async { final container = ProviderScope.containerOf(stateful.context); final repo = container.read(documentRepositoryProvider.notifier); - repo.openPicked(pageCount: 1, bytes: bytes); + repo.openPickedWithPageCount(pageCount: 1, bytes: bytes); }, [fake]); await tester.pump();