diff --git a/android/build.gradle b/android/build.gradle index 7bff0f83..e7e2bcb2 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -16,6 +16,7 @@ buildscript { dependencies { classpath "com.android.tools.build:gradle:$androidGradlePluginVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20" } } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index af7be50b..7485a59a 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Sat Oct 12 10:55:54 PKT 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/android/src/main/java/com/pspdfkit/flutter/pspdfkit/ConfigurationAdapter.java b/android/src/main/java/com/pspdfkit/flutter/pspdfkit/ConfigurationAdapter.java index eb45a39a..6c729240 100644 --- a/android/src/main/java/com/pspdfkit/flutter/pspdfkit/ConfigurationAdapter.java +++ b/android/src/main/java/com/pspdfkit/flutter/pspdfkit/ConfigurationAdapter.java @@ -39,6 +39,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import com.pspdfkit.annotations.AnnotationType; +import com.pspdfkit.annotations.configuration.AnnotationConfiguration; +import java.util.EnumSet; +import android.content.Context; +import androidx.annotation.NonNull; + class ConfigurationAdapter { private static final String LOG_TAG = "ConfigurationAdapter"; @@ -127,11 +133,13 @@ class ConfigurationAdapter { * @deprecated This key word was deprecated with PSPDFKit for Fluttter 3.1. * Use {@code FIRST_PAGE_ALWAYS_SINGLE} instead, which replaces it. */ + @Deprecated private static final String IS_FIRST_PAGE_ALWAYS_SINGLE = "isFirstPageAlwaysSingle"; /** * @deprecated This key word was deprecated with PSPDFKit for Fluttter 3.1. * Use {@code SHOW_BOOKMARKS_ACTION} instead, which replaces it. */ + @Deprecated private static final String ENABLE_BOOKMARK_LIST = "enableBookmarkList"; // Document Interaction Values @@ -204,6 +212,14 @@ class ConfigurationAdapter { if (configurationMap != null && !configurationMap.isEmpty()) { String key = null; + key = getKeyOfType(configurationMap, "defaultAuthorName", String.class); + if (key != null) { + configureDefaultAuthorName((String) configurationMap.get(key), context); + } + key = getKeyOfType(configurationMap, "askForAnnotationUsername", Boolean.class); + if (key != null) { + configureAskForAnnotationUsername((Boolean) configurationMap.get(key), context); + } key = getKeyOfType(configurationMap, PAGE_MODE, String.class); if (key != null) { configurePageMode((String) configurationMap.get(key)); @@ -403,6 +419,24 @@ class ConfigurationAdapter { } } + private void configureDefaultAuthorName(@NonNull String defaultAuthorName, @NonNull Context context) { + PSPDFKitPreferences.get(context).setAnnotationCreator(defaultAuthorName); + Log.d(LOG_TAG, "defaultAuthorName set to: " + defaultAuthorName); + } + + private void configureAskForAnnotationUsername(boolean askForAnnotationUsername, @NonNull Context context) { + if (askForAnnotationUsername) { + // Reset the annotation creator to prompt the user + PSPDFKitPreferences.get(context).resetAnnotationCreator(); + Log.d(LOG_TAG, "Annotation creator reset to prompt user."); + } else { + // Ensure annotation creator is set to prevent the dialog + if (!PSPDFKitPreferences.get(context).isAnnotationCreatorSet()) { + PSPDFKitPreferences.get(context).setAnnotationCreator(""); + Log.d(LOG_TAG, "Annotation creator set to empty string to prevent dialog."); + } + } + } private void configurePageTransition(@NonNull final String transition) { switch (transition) { @@ -596,8 +630,10 @@ private void configureInvertColors(boolean invertColors) { private void configureEnableAnnotationEditing(boolean enableAnnotationEditing) { if (enableAnnotationEditing) { configuration.enableAnnotationEditing(); + configuration.enableAnnotationList(); // Enable annotation list when editing is enabled } else { configuration.disableAnnotationEditing(); + configuration.disableAnnotationList(); // Disable annotation list when editing is disabled } } @@ -848,8 +884,9 @@ String getPassword() { } PdfActivityConfiguration build() { -// Turn on Instant comments; + // Turn on Instant comments; if (enableInstantComments) { + PdfConfiguration pdfConfiguration = this.configuration.build().getConfiguration(); final List annotationTools = pdfConfiguration diff --git a/android/src/main/java/com/pspdfkit/flutter/pspdfkit/FlutterPdfUiFragmentCallbacks.kt b/android/src/main/java/com/pspdfkit/flutter/pspdfkit/FlutterPdfUiFragmentCallbacks.kt index ab8a8157..28841f3d 100644 --- a/android/src/main/java/com/pspdfkit/flutter/pspdfkit/FlutterPdfUiFragmentCallbacks.kt +++ b/android/src/main/java/com/pspdfkit/flutter/pspdfkit/FlutterPdfUiFragmentCallbacks.kt @@ -3,6 +3,7 @@ package com.pspdfkit.flutter.pspdfkit import android.content.Context import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager +import com.pspdfkit.annotations.AnnotationProvider.OnAnnotationUpdatedListener import com.pspdfkit.document.PdfDocument import com.pspdfkit.flutter.pspdfkit.document.FlutterPdfDocument import com.pspdfkit.flutter.pspdfkit.util.MeasurementHelper @@ -10,15 +11,17 @@ import com.pspdfkit.listeners.DocumentListener import com.pspdfkit.ui.PdfFragment import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.MethodChannel +import com.pspdfkit.annotations.Annotation class FlutterPdfUiFragmentCallbacks( - private val methodChannel: MethodChannel, private val measurementConfigurations: - List>?, + private val methodChannel: MethodChannel, + private val measurementConfigurations: List>?, private val binaryMessenger: BinaryMessenger ) : FragmentManager.FragmentLifecycleCallbacks(), DocumentListener { private var pdfFragment: PdfFragment? = null private var flutterPdfDocument: FlutterPdfDocument? = null + private var annotationUpdatedListener: OnAnnotationUpdatedListener? = null override fun onFragmentAttached( fm: FragmentManager, @@ -48,8 +51,31 @@ class FlutterPdfUiFragmentCallbacks( ) ) - flutterPdfDocument = - FlutterPdfDocument(document, binaryMessenger); + flutterPdfDocument = FlutterPdfDocument(document, binaryMessenger) + + annotationUpdatedListener = object : OnAnnotationUpdatedListener { + override fun onAnnotationCreated(annotation: Annotation) { + methodChannel.invokeMethod("onAnnotationsChanged", null) + } + + override fun onAnnotationUpdated(annotation: Annotation) { + methodChannel.invokeMethod("onAnnotationsChanged", null) + } + + override fun onAnnotationRemoved(annotation: Annotation) { + methodChannel.invokeMethod("onAnnotationsChanged", null) + } + + override fun onAnnotationZOrderChanged( + pageIndex: Int, + oldOrder: List, + newOrder: List + ) { + methodChannel.invokeMethod("onAnnotationsChanged", null) + } + } + + pdfFragment?.addOnAnnotationUpdatedListener(annotationUpdatedListener!!) } override fun onPageChanged(document: PdfDocument, pageIndex: Int) { @@ -80,9 +106,14 @@ class FlutterPdfUiFragmentCallbacks( } if (pdfFragment == f) { pdfFragment?.removeDocumentListener(this) + // Remove the annotation updated listener + if (annotationUpdatedListener != null) { + pdfFragment?.removeOnAnnotationUpdatedListener(annotationUpdatedListener!!) + annotationUpdatedListener = null + } pdfFragment = null flutterPdfDocument = null } } } -} \ No newline at end of file +} diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 7c643c89..bfc740d8 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -465,7 +465,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = com.pspdfkit.flutter.pspdfkitExample; + PRODUCT_BUNDLE_IDENTIFIER = com.pspdfkit.flutter.example; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -491,7 +491,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = com.pspdfkit.flutter.pspdfkitExample; + PRODUCT_BUNDLE_IDENTIFIER = com.pspdfkit.flutter.example; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; diff --git a/example/lib/pspdfkit_basic_example.dart b/example/lib/pspdfkit_basic_example.dart index 33d9e526..f795265c 100644 --- a/example/lib/pspdfkit_basic_example.dart +++ b/example/lib/pspdfkit_basic_example.dart @@ -18,20 +18,41 @@ class PspdfkitBasicExample extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - extendBodyBehindAppBar: PlatformUtils.isAndroid(), - // Do not resize the the document view on Android or - // it won't be rendered correctly when filling forms. - resizeToAvoidBottomInset: PlatformUtils.isIOS(), - appBar: AppBar(), - body: SafeArea( - top: false, - bottom: false, - child: Container( - padding: PlatformUtils.isAndroid() - ? const EdgeInsets.only(top: kToolbarHeight) - : null, - child: PspdfkitWidget( - documentPath: documentPath, - )))); + extendBodyBehindAppBar: PlatformUtils.isAndroid(), + // Do not resize the the document view on Android or + // it won't be rendered correctly when filling forms. + resizeToAvoidBottomInset: PlatformUtils.isIOS(), + appBar: AppBar(), + body: SafeArea( + top: false, + bottom: false, + child: Container( + padding: PlatformUtils.isAndroid() + ? const EdgeInsets.only(top: kToolbarHeight) + : null, + child: PspdfkitWidget( + documentPath: documentPath, + onAnnotationsChanged: (controller) async { + print("test annotation changed"); + print("test controller ${await controller.getZoomScale(0)}"); + }, + onPspdfkitWidgetCreated: (controller) async { + + await controller.setAnnotationConfigurations({ + AnnotationTool.inkPen: InkAnnotationConfiguration( + thickness: 2, + color: Colors.black, + ) + }); + }, + configuration: PdfConfiguration( + askForAnnotationUsername: false, + allowAnnotationDeletion: false, + enableAnnotationEditing: true, + ), + ), + ), + ), + ); } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d757f3d3..62756685 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Sat Oct 12 10:53:55 PKT 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/ios/Classes/FlutterPdfDocument.swift b/ios/Classes/FlutterPdfDocument.swift index b386d597..159da0f0 100644 --- a/ios/Classes/FlutterPdfDocument.swift +++ b/ios/Classes/FlutterPdfDocument.swift @@ -11,12 +11,12 @@ import Foundation @objc(FlutterPdfDocument) public class FlutterPdfDocument: NSObject { - + // MARK: - Properties var document: Document? var messenger: FlutterBinaryMessenger? var chanel: FlutterMethodChannel? - + @objc public init(document: Document, messenger: FlutterBinaryMessenger) { super.init() self.document = document diff --git a/ios/Classes/PspdfPlatformView.m b/ios/Classes/PspdfPlatformView.m index 6f0bec7b..4287e882 100644 --- a/ios/Classes/PspdfPlatformView.m +++ b/ios/Classes/PspdfPlatformView.m @@ -15,7 +15,21 @@ @import PSPDFKit; @import PSPDFKitUI; -@interface PspdfPlatformView() +// Custom subclass to control swipe-to-delete based on allowAnnotationDeletion +@interface CustomAnnotationTableViewController : PSPDFAnnotationTableViewController +@property (nonatomic, assign) BOOL allowAnnotationDeletion; +@end + +@implementation CustomAnnotationTableViewController + +// Override to control swipe-to-delete +- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { + return self.allowAnnotationDeletion; // Control editing based on the property +} + +@end + +@interface PspdfPlatformView() @property int64_t platformViewId; @property (nonatomic) FlutterMethodChannel *channel; @property (nonatomic) FlutterMethodChannel *broadcastChannel; @@ -24,6 +38,7 @@ @interface PspdfPlatformView() @property (nonatomic) PSPDFNavigationController *navigationController; @property (nonatomic) FlutterPdfDocument *flutterPdfDocument; @property (nonatomic) NSObject *binaryMessenger; +@property (nonatomic, assign) BOOL allowAnnotationDeletion; @end @implementation PspdfPlatformView @@ -59,20 +74,54 @@ - (instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId argum NSDictionary *configurationDictionary = [PspdfkitFlutterConverter processConfigurationOptionsDictionaryForPrefix:args[@"configuration"]]; PSPDFDocument *document = [PspdfkitFlutterHelper documentFromPath:documentPath]; - + + // Extract and assign allowAnnotationDeletion + BOOL allowAnnotationDeletion = YES; + if (configurationDictionary[@"allowAnnotationDeletion"] != nil) { + allowAnnotationDeletion = [configurationDictionary[@"allowAnnotationDeletion"] boolValue]; + } + self.allowAnnotationDeletion = allowAnnotationDeletion; + NSLog(@"[PSPDFKit] allowAnnotationDeletion: %@", self.allowAnnotationDeletion ? @"YES" : @"NO"); + + + BOOL askForAnnotationUsername = YES; + if (configurationDictionary[@"askForAnnotationUsername"] != nil) { + askForAnnotationUsername = [configurationDictionary[@"askForAnnotationUsername"] boolValue]; + } + + if (askForAnnotationUsername == NO) { + document.defaultAnnotationUsername = configurationDictionary[@"defaultAuthorName"]; + } + NSArray *measurementValueConfigurations = configurationDictionary[@"measurementValueConfigurations"]; [PspdfkitFlutterHelper unlockWithPasswordIfNeeded:document dictionary:configurationDictionary]; BOOL isImageDocument = [PspdfkitFlutterHelper isImageDocument:documentPath]; PSPDFConfiguration *configuration = [PspdfkitFlutterConverter configuration:configurationDictionary isImageDocument:isImageDocument]; - _pdfViewController = [[PSPDFViewController alloc] initWithDocument:document configuration:configuration]; + + // Update the configuration to set 'shouldAskForAnnotationUsername' + PSPDFConfiguration *updatedConfiguration = [configuration configurationUpdatedWithBuilder:^(PSPDFConfigurationBuilder *builder) { + builder.shouldAskForAnnotationUsername = askForAnnotationUsername; + NSLog(@"[PSPDFKit] shouldAskForAnnotationUsername: %@", builder.shouldAskForAnnotationUsername ? @"YES" : @"NO"); + NSLog(@"[PSPDFKit] defaultAuthorName %@", configurationDictionary[@"defaultAuthorName"]); + + // Override PSPDFAnnotationTableViewController with our custom subclass + [builder overrideClass:[PSPDFAnnotationTableViewController class] withClass:[CustomAnnotationTableViewController class]]; + }]; + + _pdfViewController = [[PSPDFViewController alloc] initWithDocument:document configuration:updatedConfiguration]; _pdfViewController.appearanceModeManager.appearanceMode = [PspdfkitFlutterConverter appearanceMode:configurationDictionary]; _pdfViewController.pageIndex = [PspdfkitFlutterConverter pageIndex:configurationDictionary]; _pdfViewController.delegate = self; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(documentDidFinishRendering) name:PSPDFDocumentViewControllerDidConfigureSpreadViewNotification object:nil]; + // Start listening to the annotation's change notification. + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(annotationChangedNotification:) name:PSPDFAnnotationChangedNotification object:nil]; + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(annotationChangedNotification:) name:PSPDFAnnotationsAddedNotification object:nil]; + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(annotationChangedNotification:) name:PSPDFAnnotationsRemovedNotification object:nil]; + if ((id)configurationDictionary != NSNull.null) { NSString *key = @"leftBarButtonItems"; if (configurationDictionary[key]) { @@ -122,6 +171,39 @@ - (instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId argum return self; } +// Helper method to find the annotation controller +- (PSPDFAnnotationTableViewController *)findAnnotationControllerIn:(UIViewController *)controller { + if ([controller isKindOfClass:[PSPDFAnnotationTableViewController class]]) { + return (PSPDFAnnotationTableViewController *)controller; + } else if ([controller isKindOfClass:[UINavigationController class]]) { + return [self findAnnotationControllerIn:((UINavigationController *)controller).topViewController]; + } else if ([controller isKindOfClass:[PSPDFContainerViewController class]]) { + for (UIViewController *childController in ((PSPDFContainerViewController *)controller).viewControllers) { + PSPDFAnnotationTableViewController *foundController = [self findAnnotationControllerIn:childController]; + if (foundController) { + return foundController; + } + } + } + return nil; +} + +// Implement the delegate method +- (BOOL)pdfViewController:(PSPDFViewController *)pdfController + shouldShowController:(UIViewController *)controller + options:(NSDictionary *)options + animated:(BOOL)animated { + PSPDFAnnotationTableViewController *annotationController = [self findAnnotationControllerIn:controller]; + if (annotationController) { + if ([annotationController isKindOfClass:[CustomAnnotationTableViewController class]]) { + CustomAnnotationTableViewController *customController = (CustomAnnotationTableViewController *)annotationController; + customController.allowAnnotationDeletion = self.allowAnnotationDeletion; + NSLog(@"[PSPDFKit] Setting allowAnnotationDeletion to %@", self.allowAnnotationDeletion ? @"YES" : @"NO"); + } + } + return YES; +} + - (void)documentDidFinishRendering { // Remove observer after the initial notification [NSNotificationCenter.defaultCenter removeObserver:self @@ -137,6 +219,13 @@ - (void)documentDidFinishRendering { } } +- (void)annotationChangedNotification:(NSNotification *)notification { + NSDictionary *arguments = @{ + @"documentId": self.pdfViewController.document.UID, + }; + [_channel invokeMethod:@"onAnnotationsChanged" arguments: arguments]; +} + - (void) pdfViewController:(PSPDFViewController *)pdfController willBeginDisplayingPageView:(PSPDFPageView *)pageView forPageAtIndex:(NSInteger)pageIndex { NSDictionary *arguments = @{ @"pageIndex": @(pageIndex), @@ -145,6 +234,22 @@ - (void) pdfViewController:(PSPDFViewController *)pdfController willBeginDisplay [_channel invokeMethod:@"onPageChanged" arguments: arguments]; } +// should suppress file conflict alerts https://pspdfkit.com/guides/ios/knowledge-base/suppressing-file-coordination-alerts/ +// ...but seems to be not working +- (BOOL)resolutionManager:(PSPDFConflictResolutionManager *)manager shouldPerformAutomaticResolutionForForDocument:(PSPDFDocument *)document dataProvider:(id)dataProvider conflictType:(PSPDFFileConflictType)type + resolution:(inout PSPDFFileConflictResolution *)resolution { + switch (type) { + case PSPDFFileConflictTypeDeletion: + // Unconditionally close the document — EVEN WHEN THERE ARE UNSAVED CHANGES! + *resolution = PSPDFFileConflictResolutionClose; + return YES; + case PSPDFFileConflictTypeModification: + // Unconditionally reload the document from disk — EVEN WHEN THERE ARE UNSAVED CHANGES! + *resolution = PSPDFFileConflictResolutionReload; + return YES; + } +} + - (void)dealloc { [self cleanup]; } diff --git a/ios/Classes/PspdfkitPlugin.m b/ios/Classes/PspdfkitPlugin.m index 79c24869..a9abd54b 100644 --- a/ios/Classes/PspdfkitPlugin.m +++ b/ios/Classes/PspdfkitPlugin.m @@ -44,13 +44,13 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { if ([licenseKey isKindOfClass:[NSNull class]]|| licenseKey.length <= 0) { return; } - [PSPDFKitGlobal setLicenseKey:licenseKey options:@{PSPDFSettingKeyHybridEnvironment: @"Flutter"}]; + [PSPDFKitGlobal setLicenseKey:licenseKey options:@{PSPDFSettingKeyHybridEnvironment: @"Flutter", PSPDFSettingKeyFileCoordinationEnabled: @false}]; } else if ([@"setLicenseKeys" isEqualToString:call.method]) { NSString *iOSLicenseKey = call.arguments[@"iOSLicenseKey"]; if ([iOSLicenseKey isKindOfClass:[NSNull class]]|| iOSLicenseKey.length <= 0) { return; } - [PSPDFKitGlobal setLicenseKey:iOSLicenseKey options:@{PSPDFSettingKeyHybridEnvironment: @"Flutter"}]; + [PSPDFKitGlobal setLicenseKey:iOSLicenseKey options:@{PSPDFSettingKeyHybridEnvironment: @"Flutter", PSPDFSettingKeyFileCoordinationEnabled: @false}]; }else if ([@"present" isEqualToString:call.method]) { NSString *documentPath = call.arguments[@"document"]; @@ -140,6 +140,19 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } } +- (void)setAnnotationConfigurations:(NSDictionary *)configurations { + if (!self.pdfViewController) { + NSLog(@"[PSPDFKit] pdfViewController is nil. Cannot apply annotation configurations."); + return; + } + + // Convert configurations from Flutter to native PSPDFKit configurations + [AnnotationsPresetConfigurations setConfigurationsWithAnnotationPreset:configurations]; + + NSLog(@"[PSPDFKit] Applied annotation configurations."); +} + + - (void) setupViewController:(NSDictionary *)configurationDictionary result:(FlutterResult)result { self.pdfViewController.appearanceModeManager.appearanceMode = [PspdfkitFlutterConverter appearanceMode:configurationDictionary]; diff --git a/lib/src/pdf_configuration.dart b/lib/src/pdf_configuration.dart index 4a4cb99b..6a9da2ec 100644 --- a/lib/src/pdf_configuration.dart +++ b/lib/src/pdf_configuration.dart @@ -174,6 +174,15 @@ class PdfConfiguration { /// Sets the minimum zoom scale. Defaults to null. final double? minimumZoomScale; + /// Sets whether to ask for the username when adding an annotation. + final bool askForAnnotationUsername; + + /// Sets whether to show the author name in the annotation inspector. + final String defaultAuthorName; + + /// Sets whether to allow the deletion of annotations from outline window. + final bool allowAnnotationDeletion; + PdfConfiguration( {this.scrollDirection, this.pageTransition, @@ -222,7 +231,10 @@ class PdfConfiguration { this.annotationToolsGrouping, this.defaultZoomScale, this.maximumZoomScale, - this.minimumZoomScale}); + this.minimumZoomScale, + this.defaultAuthorName = 'unnamed', + this.askForAnnotationUsername = true, + this.allowAnnotationDeletion = true}); /// Returns a [Map] representation of the [PdfConfiguration] object. /// This is used to pass the configuration to the platform side. @@ -268,6 +280,9 @@ class PdfConfiguration { 'enableMeasurementTools': enableMeasurementTools, 'enableMeasurementToolSnapping': measurementSnappingEnabled, 'enableMagnifier': enableMagnifier, + 'askForAnnotationUsername': askForAnnotationUsername, + 'defaultAuthorName': defaultAuthorName, + 'allowAnnotationDeletion': allowAnnotationDeletion, 'measurementValueConfigurations': measurementValueConfigurations?.map((e) => e.toMap()).toList(), 'toolbarItemGrouping': convertAnnotationToolsGrouping(), diff --git a/lib/src/types.dart b/lib/src/types.dart index 9e9ce33d..fa4328fb 100644 --- a/lib/src/types.dart +++ b/lib/src/types.dart @@ -254,6 +254,8 @@ typedef PdfDocumentLoadFailedCallback = void Function(String error); typedef PageChangedCallback = void Function(int pageIndex); +typedef AnnotationsChangedCallback = void Function(PspdfkitWidgetController controller); + extension WebShowSignatureValidationStatusMode on ShowSignatureValidationStatusMode { String? get webName { diff --git a/lib/src/widgets/pspdfkit_widget.dart b/lib/src/widgets/pspdfkit_widget.dart index 5e88f29f..ccb3586b 100644 --- a/lib/src/widgets/pspdfkit_widget.dart +++ b/lib/src/widgets/pspdfkit_widget.dart @@ -9,13 +9,15 @@ library pspdfkit_widget; import 'dart:async'; -import 'package:flutter/services.dart'; + +import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; -import 'package:flutter/rendering.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; import 'package:pspdfkit_flutter/pspdfkit.dart'; + import 'pspdfkit_widget_controller_native.dart'; class PspdfkitWidget extends StatefulWidget { @@ -25,6 +27,7 @@ class PspdfkitWidget extends StatefulWidget { final PdfDocumentLoadedCallback? onPdfDocumentLoaded; final PdfDocumentLoadFailedCallback? onPdfDocumentError; final PageChangedCallback? onPageChanged; + final AnnotationsChangedCallback? onAnnotationsChanged; const PspdfkitWidget({ Key? key, @@ -34,6 +37,7 @@ class PspdfkitWidget extends StatefulWidget { this.onPdfDocumentLoaded, this.onPdfDocumentError, this.onPageChanged, + this.onAnnotationsChanged, }) : super(key: key); @override @@ -118,6 +122,7 @@ class _PspdfkitWidgetState extends State { onPageChanged: widget.onPageChanged, onPdfDocumentLoadFailed: widget.onPdfDocumentError, onPdfDocumentLoaded: widget.onPdfDocumentLoaded, + onAnnotationsChanged: widget.onAnnotationsChanged, ); widget.onPspdfkitWidgetCreated?.call(controller); } diff --git a/lib/src/widgets/pspdfkit_widget_controller_native.dart b/lib/src/widgets/pspdfkit_widget_controller_native.dart index 2e9af31c..68d4000c 100644 --- a/lib/src/widgets/pspdfkit_widget_controller_native.dart +++ b/lib/src/widgets/pspdfkit_widget_controller_native.dart @@ -8,6 +8,7 @@ /// import 'package:flutter/services.dart'; + import '../../pspdfkit.dart'; import '../document/pdf_document_native.dart'; @@ -20,6 +21,7 @@ class PspdfkitWidgetControllerNative extends PspdfkitWidgetController { PdfDocumentLoadedCallback? onPdfDocumentLoaded, PdfDocumentLoadFailedCallback? onPdfDocumentLoadFailed, PageChangedCallback? onPageChanged, + AnnotationsChangedCallback? onAnnotationsChanged, }) : _channel = MethodChannel('com.pspdfkit.widget.$id') { _channel.setMethodCallHandler((call) async { switch (call.method) { @@ -35,6 +37,9 @@ class PspdfkitWidgetControllerNative extends PspdfkitWidgetController { var pageIndex = call.arguments['pageIndex']; onPageChanged?.call(pageIndex); break; + case 'onAnnotationsChanged': + onAnnotationsChanged?.call(this); + break; } }); } @@ -108,7 +113,7 @@ class PspdfkitWidgetControllerNative extends PspdfkitWidgetController { Map configurations, ) async { await _channel - .invokeMethod('setAnnotationConfigurations', { + .invokeMethod('setAnnotationPresetConfigurations', { 'annotationConfigurations': configurations.map((key, value) { return MapEntry(key.name, value.toMap()); }), diff --git a/pubspec.yaml b/pubspec.yaml index 81e1c176..2f540b37 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: pspdfkit_flutter description: A Flutter plugin providing a feature-rich PDF viewing and editing experience to your users with the powerful PSPDFKit PDF SDK. -version: 3.12.0 +version: 3.12.1 homepage: https://pspdfkit.com/ repository: https://github.com/PSPDFKit/pspdfkit-flutter issue_tracker: https://support.pspdfkit.com/hc/en-us/requests/new