saveDrawing method

Future<void> saveDrawing({
  1. required File pdfFile,
  2. required int totalPages,
  3. required BuildContext context,
  4. required DrawingController drawingController,
  5. required ImageController imageController,
  6. required TextBoxController textBoxController,
  7. required HighlightController highlightController,
  8. required UnderlineController underlineController,
  9. required Function refresh,
})

Saves the current edits (drawings, images, annotations, and text boxes) to a new PDF file.

pdfFile - the original PDF file, totalPages - number of pages in the document, context - BuildContext for getting MediaQuery, drawingController, imageController, textBoxController, highlightController, underlineController - various controllers managing different edit types, refresh - callback to refresh UI if needed.

Implementation

Future<void> saveDrawing({
  required File pdfFile,
  required int totalPages,
  required BuildContext context,
  required DrawingController drawingController,
  required ImageController imageController,
  required TextBoxController textBoxController,
  required HighlightController highlightController,
  required UnderlineController underlineController,
  required Function refresh,
}) async {
  if (isSaving) return;

  isSaving = true;

  try {
    final screenWidth = MediaQuery.of(context).size.width;

    if (!(drawingController.hasAnyContent() ||
        imageController.hasAnyContent() ||
        textBoxController.hasAnyContent() ||
        highlightController.hasAnyContent() ||
        underlineController.hasAnyContent())) {
      return Navigator.pop(context, pdfFile);
    }

    final originalPdfBytes = await pdfFile.readAsBytes();

    final List<PageEditDto> edits = [];

    for (int i = 0; i < totalPages; i++) {
      final pageIndex = i + 1;
      drawingController.setPage(pageIndex);
      await Future.delayed(const Duration(milliseconds: 200));
      final List<ImageBoxDto> imageDtos = [];

      for (final img in imageController.getAllImageBoxes()[pageIndex] ?? []) {
        final bytes = await _convertImageToUint8List(img.image);
        imageDtos.add(
          ImageBoxDto(
            imageBytes: bytes,
            position: img.position,
            width: img.width,
            height: img.height,
            rotation: img.rotation,
          ),
        );
      }

      final textBoxes = textBoxController.getAllTextBoxes()[pageIndex] ?? [];

      final drawingData = await drawingController.getImageData(pageIndex);

      edits.add(
        PageEditDto(
          pageIndex: i,
          highlight: highlightController.getHighlightHistory[pageIndex] ?? [],
          underline: underlineController.getUnderlineHistory[pageIndex] ?? [],
          drawingBytes: drawingData?.buffer.asUint8List(),
          images: imageDtos,
          textBoxes: textBoxes,
        ),
      );
    }

    final Uint8List updatedPdf = await Isolate.run(() async {
      return await processAndSavePdf(
        originalPdfBytes: originalPdfBytes,
        edits: edits,
        screenWidth: screenWidth,
      );
    });

    final output = await getTemporaryDirectory();
    final savedPath =
        '${output.path}/${pdfFile.path.split('/').last.split('.').first}_${DateTime.now().millisecondsSinceEpoch}.pdf';

    final newFile = await File(savedPath).writeAsBytes(updatedPdf);

    Navigator.pop(context, newFile);
  } catch (e) {
    debugPrint("❌ Error in saveDrawing: $e");
  } finally {
    isSaving = false;
  }
}