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 56ed8598..5f5601eb 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 @@ -730,4 +732,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 70cb6c65..f4ca91be 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 @@ -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 ca4535e5..4bfe1144 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'; @@ -219,7 +220,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 66939105..751ed2a4 100644 --- a/ios/Classes/PspdfkitPlatformViewImpl.swift +++ b/ios/Classes/PspdfkitPlatformViewImpl.swift @@ -402,6 +402,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 a879e9e6..4d950ea0 100644 --- a/ios/Classes/api/PspdfkitApi.g.swift +++ b/ios/Classes/api/PspdfkitApi.g.swift @@ -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 227bf815..eb813563 100644 --- a/lib/src/api/pspdfkit_api.g.dart +++ b/lib/src/api/pspdfkit_api.g.dart @@ -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 8fcd1d6e..061e4bf4 100644 --- a/lib/src/widgets/pspdfkit_flutter_widget_controller_impl.dart +++ b/lib/src/widgets/pspdfkit_flutter_widget_controller_impl.dart @@ -296,6 +296,13 @@ class PspdfkitFlutterWidgetControllerImpl } @override + Future enableAnnotationEditing( + {bool enable = true, AnnotationType? annotationType, String? toolName}) { + return _pspdfkitWidgetControllerApi.enableAnnotationEditing( + enable, + annotationType, + toolName, + ); void onCustomToolbarItemTapped(String identifier) { onCustomToolbarItemTappedListener?.call(identifier); } 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 39b8635a..6c687257 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()