From 62ad4ae541d5147909c1663079b35d847f108df6 Mon Sep 17 00:00:00 2001 From: Julius Kato Mutumba Date: Fri, 30 May 2025 21:06:27 +0300 Subject: [PATCH] enable/disable annotation editing --- .../flutter/pspdfkit/PspdfkitViewImpl.kt | 18 +++++ .../flutter/pspdfkit/api/PspdfkitApi.g.kt | 23 +++++- .../diable_annotation_edditing_example.dart | 70 +++++++++++++++++++ example/lib/examples.dart | 11 ++- ios/Classes/PspdfkitPlatformViewImpl.swift | 21 +++++- ios/Classes/api/PspdfkitApi.g.swift | 20 +++++- lib/src/api/pspdfkit_api.g.dart | 33 ++++++++- ...pdfkit_flutter_widget_controller_impl.dart | 10 +++ .../widgets/pspdfkit_widget_controller.dart | 3 + .../pspdfkit_widget_controller_native.dart | 7 ++ .../pspdfkit_widget_controller_web.dart | 7 ++ pigeons/pspdfkit.dart | 3 + 12 files changed, 218 insertions(+), 8 deletions(-) create mode 100644 example/lib/diable_annotation_edditing_example.dart diff --git a/android/src/main/java/com/pspdfkit/flutter/pspdfkit/PspdfkitViewImpl.kt b/android/src/main/java/com/pspdfkit/flutter/pspdfkit/PspdfkitViewImpl.kt index 217af021..8b54857e 100644 --- a/android/src/main/java/com/pspdfkit/flutter/pspdfkit/PspdfkitViewImpl.kt +++ b/android/src/main/java/com/pspdfkit/flutter/pspdfkit/PspdfkitViewImpl.kt @@ -9,6 +9,8 @@ package com.pspdfkit.flutter.pspdfkit import android.graphics.RectF +import com.pspdfkit.configuration.PdfConfiguration +import com.pspdfkit.configuration.activity.PdfActivityConfiguration import com.pspdfkit.document.formatters.DocumentJsonFormatter import com.pspdfkit.document.formatters.XfdfFormatter import com.pspdfkit.document.processor.PdfProcessor @@ -724,4 +726,20 @@ class PspdfkitViewImpl : PspdfkitWidgetControllerApi { ) } } + + override fun enableAnnotationEditing( + enable: Boolean, + annotationType: AnnotationType?, + toolName: String? + ) { + // Create a new PdfActivityConfiguration with the updated annotation editing settings. + PdfActivityConfiguration + pdfUiFragment?.let { + val oldConfig = it.configuration + val newConfig = PdfActivityConfiguration.Builder(oldConfig) + .annotationEditingEnabled(enable) + .build() + it.configuration = newConfig + } + } } \ No newline at end of file diff --git a/android/src/main/java/com/pspdfkit/flutter/pspdfkit/api/PspdfkitApi.g.kt b/android/src/main/java/com/pspdfkit/flutter/pspdfkit/api/PspdfkitApi.g.kt index cc73d84f..c34f5f35 100644 --- a/android/src/main/java/com/pspdfkit/flutter/pspdfkit/api/PspdfkitApi.g.kt +++ b/android/src/main/java/com/pspdfkit/flutter/pspdfkit/api/PspdfkitApi.g.kt @@ -4,7 +4,7 @@ // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. // This notice may not be removed from this file. -// Autogenerated from Pigeon (v24.2.1), do not edit directly. +// Autogenerated from Pigeon (v24.2.2), do not edit directly. // See also: https://pub.dev/packages/pigeon @file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") @@ -1635,6 +1635,7 @@ interface PspdfkitWidgetControllerApi { * exiting annotation creation mode was successful. */ fun exitAnnotationCreationMode(callback: (Result) -> Unit) + fun enableAnnotationEditing(enable: Boolean, annotationType: AnnotationType?, toolName: String?) companion object { /** The codec used by PspdfkitWidgetControllerApi. */ @@ -2040,6 +2041,26 @@ interface PspdfkitWidgetControllerApi { channel.setMessageHandler(null) } } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pspdfkit_flutter.PspdfkitWidgetControllerApi.enableAnnotationEditing$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enableArg = args[0] as Boolean + val annotationTypeArg = args[1] as AnnotationType? + val toolNameArg = args[2] as String? + val wrapped: List = try { + api.enableAnnotationEditing(enableArg, annotationTypeArg, toolNameArg) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } } } } diff --git a/example/lib/diable_annotation_edditing_example.dart b/example/lib/diable_annotation_edditing_example.dart new file mode 100644 index 00000000..80ba59a5 --- /dev/null +++ b/example/lib/diable_annotation_edditing_example.dart @@ -0,0 +1,70 @@ +/// +/// Copyright © 2024-2025 PSPDFKit GmbH. All rights reserved. +/// +/// THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW +/// AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. +/// UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. +/// This notice may not be removed from this file. +/// + +import 'package:flutter/material.dart'; +import 'package:pspdfkit_flutter/pspdfkit.dart'; + +class DisableAnnotationEditingExample extends StatefulWidget { + final String documentPath; + + const DisableAnnotationEditingExample( + {super.key, required this.documentPath}); + + @override + State createState() => + _DisableAnnotationEditingExampleState(); +} + +class _DisableAnnotationEditingExampleState + extends State { + PspdfkitWidgetController? _pspdfkitWidgetController; + var isAnnotationEditingEnabled = true; + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + top: false, + bottom: false, + child: Stack( + children: [ + PspdfkitWidget( + documentPath: widget.documentPath, + onPspdfkitWidgetCreated: (view) { + _pspdfkitWidgetController = view; + // Disable annotation editing + }, + ), + Positioned( + bottom: 16, + left: 16, + child: ElevatedButton( + onPressed: () async { + if (_pspdfkitWidgetController != null) { + // Disable annotation editing + await _pspdfkitWidgetController + ?.enableAnnotationEditing( + enable: !isAnnotationEditingEnabled); + setState(() { + isAnnotationEditingEnabled = + !isAnnotationEditingEnabled; + }); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Annotation editing disabled')), + ); + } + }, + child: const Text('Disable Annotation Editing'), + ), + ), + ], + ))); + } +} diff --git a/example/lib/examples.dart b/example/lib/examples.dart index b8fd5188..3af331f7 100644 --- a/example/lib/examples.dart +++ b/example/lib/examples.dart @@ -13,6 +13,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:pspdfkit_example/diable_annotation_edditing_example.dart'; import 'package:pspdfkit_example/models/papsdkit_example_item.dart'; import 'package:pspdfkit_example/pspdfkit_toolbar_customization.dart'; @@ -210,7 +211,15 @@ List examples(BuildContext context) => [ NutrientAnnotationCreationModeExampleWidget( documentPath: value.path), context)); - }) + }), + PspdfkitExampleItem( + title: 'Disable Annotation Editing', + description: 'Shows how to disable annotation editing.', + onTap: () async { + await extractAsset(context, _documentPath).then((value) => goTo( + DisableAnnotationEditingExample(documentPath: value.path), + context)); + }), ]; List globalExamples(BuildContext context) => [ diff --git a/ios/Classes/PspdfkitPlatformViewImpl.swift b/ios/Classes/PspdfkitPlatformViewImpl.swift index 38279566..3dc9792d 100644 --- a/ios/Classes/PspdfkitPlatformViewImpl.swift +++ b/ios/Classes/PspdfkitPlatformViewImpl.swift @@ -335,8 +335,25 @@ public class PspdfkitPlatformViewImpl: NSObject, PspdfkitWidgetControllerApi, PD completion(.failure(PspdfkitApiError(code: "error", message: "Error exiting annotation creation mode: \(error.localizedDescription)", details: nil))) } } - - + + func enableAnnotationEditing(enable: Bool, annotationType: AnnotationType?, toolName: String?) throws { + guard let pdfViewController = pdfViewController else { + throw PspdfkitApiError(code: "error", message: "PDF view controller is null", details: nil) + } + pdfViewController.updateConfiguration { builder in + if enable { + // Enable all annotation types - set to a comprehensive set of annotation tools + builder.editableAnnotationTypes = [ + .ink, .highlight, .strikeOut, .underline, .squiggly, .note, .freeText, + .square, .circle, .line, .polygon, .polyLine, .stamp, .image, + .signature, .eraser, .sound, .redaction + ] + } else { + // Disable all annotation editing by setting to nil + builder.editableAnnotationTypes = nil + } + } + } @objc func spreadIndexDidChange(_ notification: Notification) { if let newSpreadIndex = notification.userInfo?["PSPDFDocumentViewControllerSpreadIndexKey"] as? Int, diff --git a/ios/Classes/api/PspdfkitApi.g.swift b/ios/Classes/api/PspdfkitApi.g.swift index 6ae21bfe..c5f09615 100644 --- a/ios/Classes/api/PspdfkitApi.g.swift +++ b/ios/Classes/api/PspdfkitApi.g.swift @@ -4,7 +4,7 @@ // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. // This notice may not be removed from this file. -// Autogenerated from Pigeon (v24.2.1), do not edit directly. +// Autogenerated from Pigeon (v24.2.2), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation @@ -1560,6 +1560,7 @@ protocol PspdfkitWidgetControllerApi { /// Returns a [Future] that completes with a boolean indicating whether /// exiting annotation creation mode was successful. func exitAnnotationCreationMode(completion: @escaping (Result) -> Void) + func enableAnnotationEditing(enable: Bool, annotationType: AnnotationType?, toolName: String?) throws } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. @@ -1945,6 +1946,23 @@ class PspdfkitWidgetControllerApiSetup { } else { exitAnnotationCreationModeChannel.setMessageHandler(nil) } + let enableAnnotationEditingChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pspdfkit_flutter.PspdfkitWidgetControllerApi.enableAnnotationEditing\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + enableAnnotationEditingChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enableArg = args[0] as! Bool + let annotationTypeArg: AnnotationType? = nilOrValue(args[1]) + let toolNameArg: String? = nilOrValue(args[2]) + do { + try api.enableAnnotationEditing(enable: enableArg, annotationType: annotationTypeArg, toolName: toolNameArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + enableAnnotationEditingChannel.setMessageHandler(nil) + } } } /// Generated protocol from Pigeon that represents a handler of messages from Flutter. diff --git a/lib/src/api/pspdfkit_api.g.dart b/lib/src/api/pspdfkit_api.g.dart index 1d175729..37463376 100644 --- a/lib/src/api/pspdfkit_api.g.dart +++ b/lib/src/api/pspdfkit_api.g.dart @@ -4,7 +4,7 @@ // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. // This notice may not be removed from this file. -// Autogenerated from Pigeon (v24.2.1), do not edit directly. +// Autogenerated from Pigeon (v24.2.2), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers @@ -2480,6 +2480,33 @@ class PspdfkitWidgetControllerApi { return (pigeonVar_replyList[0] as bool?); } } + + Future enableAnnotationEditing( + bool enable, AnnotationType? annotationType, String? toolName) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.pspdfkit_flutter.PspdfkitWidgetControllerApi.enableAnnotationEditing$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([enable, annotationType, toolName]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } } class PdfDocumentApi { @@ -3147,7 +3174,7 @@ abstract class PspdfkitWidgetCallbacks { assert(arg_pageIndex != null, 'Argument for dev.flutter.pigeon.pspdfkit_flutter.PspdfkitWidgetCallbacks.onPageClick was null, expected non-null int.'); final PointF? arg_point = (args[2] as PointF?); - final Object? arg_annotation = args[3]; + final Object? arg_annotation = (args[3] as Object?); try { api.onPageClick( arg_documentId!, arg_pageIndex!, arg_point, arg_annotation); @@ -3223,7 +3250,7 @@ abstract class NutrientEventsCallbacks { final NutrientEvent? arg_event = (args[0] as NutrientEvent?); assert(arg_event != null, 'Argument for dev.flutter.pigeon.pspdfkit_flutter.NutrientEventsCallbacks.onEvent was null, expected non-null NutrientEvent.'); - final Object? arg_data = args[1]; + final Object? arg_data = (args[1] as Object?); try { api.onEvent(arg_event!, arg_data); return wrapResponse(empty: true); diff --git a/lib/src/widgets/pspdfkit_flutter_widget_controller_impl.dart b/lib/src/widgets/pspdfkit_flutter_widget_controller_impl.dart index 4f2757a2..425ac3d4 100644 --- a/lib/src/widgets/pspdfkit_flutter_widget_controller_impl.dart +++ b/lib/src/widgets/pspdfkit_flutter_widget_controller_impl.dart @@ -291,4 +291,14 @@ class PspdfkitFlutterWidgetControllerImpl void onDocumentSaved(String documentId, String? path) { onPdfDocumentSaved?.call(documentId, path); } + + @override + Future enableAnnotationEditing( + {bool enable = true, AnnotationType? annotationType, String? toolName}) { + return _pspdfkitWidgetControllerApi.enableAnnotationEditing( + enable, + annotationType, + toolName, + ); + } } diff --git a/lib/src/widgets/pspdfkit_widget_controller.dart b/lib/src/widgets/pspdfkit_widget_controller.dart index 0481b703..a94a3f5d 100644 --- a/lib/src/widgets/pspdfkit_widget_controller.dart +++ b/lib/src/widgets/pspdfkit_widget_controller.dart @@ -115,4 +115,7 @@ abstract class PspdfkitWidgetController { /// Returns a [Future] that completes with a boolean indicating whether /// exiting annotation creation mode was successful. Future exitAnnotationCreationMode(); + + Future enableAnnotationEditing( + {bool enable = true, AnnotationType? annotationType}); } diff --git a/lib/src/widgets/pspdfkit_widget_controller_native.dart b/lib/src/widgets/pspdfkit_widget_controller_native.dart index a7f10b4a..02c9de81 100644 --- a/lib/src/widgets/pspdfkit_widget_controller_native.dart +++ b/lib/src/widgets/pspdfkit_widget_controller_native.dart @@ -192,4 +192,11 @@ class PspdfkitWidgetControllerNative extends PspdfkitWidgetController { throw UnimplementedError( 'Annotation creation mode is not supported in legacy mode'); } + + @override + Future enableAnnotationEditing( + {bool enable = true, AnnotationType? annotationType}) { + // TODO: ignore this method in legacy mode. + throw UnimplementedError(); + } } diff --git a/lib/src/widgets/pspdfkit_widget_controller_web.dart b/lib/src/widgets/pspdfkit_widget_controller_web.dart index 0fc31a91..1f0e0e33 100644 --- a/lib/src/widgets/pspdfkit_widget_controller_web.dart +++ b/lib/src/widgets/pspdfkit_widget_controller_web.dart @@ -251,4 +251,11 @@ class PspdfkitWidgetControllerWeb extends PspdfkitWidgetController Future getZoomScale(int pageIndex) { return pspdfkitInstance.getZoomScale(pageIndex); } + + @override + Future enableAnnotationEditing( + {bool enable = true, AnnotationType? annotationType}) { + // TODO: Implement if you use web. + throw UnimplementedError(); + } } diff --git a/pigeons/pspdfkit.dart b/pigeons/pspdfkit.dart index ee2307f9..915e5f1d 100644 --- a/pigeons/pspdfkit.dart +++ b/pigeons/pspdfkit.dart @@ -566,6 +566,9 @@ abstract class PspdfkitWidgetControllerApi { /// exiting annotation creation mode was successful. @async bool? exitAnnotationCreationMode(); + + void enableAnnotationEditing( + bool enable, AnnotationType? annotationType, String? toolName); } @HostApi()