Selaa lähdekoodia

ComPDFKit(flutter) - 2.2.0-beta.1 android新增注释交互接口,ios未完成

liuxiaolong 5 päivää sitten
vanhempi
commit
ee936eb088

+ 6 - 6
README.md

@@ -151,7 +151,7 @@ Alternatively you can update the `AndroidManifest.xml` file to use `FlutterFragm
  dependencies:
    flutter:
      sdk: flutter
-+  compdfkit_flutter: ^2.1.3
++  compdfkit_flutter: ^2.2.0
 ```
 
 8. Add the PDF documents you want to display in the project
@@ -197,7 +197,7 @@ cd example
  dependencies:
    flutter:
      sdk: flutter
-+  compdfkit_flutter: ^2.1.3
++  compdfkit_flutter: ^2.2.0
 ```
 
 4. Open your project's Podfile in a text editor:
@@ -220,8 +220,8 @@ open ios/Podfile
    use_modular_headers!`
 
    flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
-+  pod 'ComPDFKit_Tools', podspec:'https://www.compdf.com/download/ios/cocoapods/xcframeworks/compdfkit_tools/2.1.3.podspec'
-+  pod 'ComPDFKit', podspec:'https://www.compdf.com/download/ios/cocoapods/xcframeworks/compdfkit/2.1.3.podspec'
++  pod 'ComPDFKit_Tools', podspec:'https://www.compdf.com/download/ios/cocoapods/xcframeworks/compdfkit_tools/2.2.0.podspec'
++  pod 'ComPDFKit', podspec:'https://www.compdf.com/download/ios/cocoapods/xcframeworks/compdfkit/2.2.0.podspec'
 
  end
 ```
@@ -557,8 +557,8 @@ target 'PDFView_RN' do
     # Pods for testing
   end
 
-+  pod 'ComPDFKit', :git => 'https://github.com/ComPDFKit/compdfkit-pdf-sdk-ios-swift.git', :tag => '2.1.3'
-+  pod 'ComPDFKit_Tools', :git => 'https://github.com/ComPDFKit/compdfkit-pdf-sdk-ios-swift.git', :tag => '2.1.3'
++  pod 'ComPDFKit', :git => 'https://github.com/ComPDFKit/compdfkit-pdf-sdk-ios-swift.git', :tag => '2.2.0'
++  pod 'ComPDFKit_Tools', :git => 'https://github.com/ComPDFKit/compdfkit-pdf-sdk-ios-swift.git', :tag => '2.2.0'
 
   # Enables Flipper.
   #

+ 1 - 1
android/build.gradle

@@ -40,7 +40,7 @@ android {
         implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
 
         // dependencies compdfkit pdf sdk
-        api 'com.compdf:compdfkit-tools:2.1.3'
+        api 'com.compdf:compdfkit-tools:2.2.0-SNAPSHOT'
 
         testImplementation 'junit:junit:4.13.2'
         testImplementation 'org.mockito:mockito-core:5.0.0'

+ 11 - 3
android/src/main/java/com/compdfkit/flutter/compdfkit_flutter/constants/CPDFConstants.java

@@ -11,9 +11,6 @@
 package com.compdfkit.flutter.compdfkit_flutter.constants;
 
 
-import io.flutter.plugin.common.MethodCall;
-import io.flutter.plugin.common.MethodChannel.Result;
-
 public class CPDFConstants {
 
   public static class ChannelMethod {
@@ -39,6 +36,7 @@ public class CPDFConstants {
     public static final String OPEN_DOCUMENT = "open_document";
 
     public static final String GET_TEMP_DIRECTORY = "get_temporary_directory";
+    public static final String REMOVE_SIGN_FILE_LIST = "remove_sign_file_list";
 
     public static final String SAVE = "save";
 
@@ -64,6 +62,8 @@ public class CPDFConstants {
 
     public static final String SET_MARGIN = "set_margin";
 
+    public static final String SET_PAGE_SPACING = "set_page_spacing";
+
     public static final String SET_CONTINUE_MODE = "set_continue_mode";
 
     public static final String IS_CONTINUE_MODE = "is_continue_mode";
@@ -107,6 +107,14 @@ public class CPDFConstants {
     public static final String CLOSE = "close";
 
     public static final String HAS_CHANGE = "has_change";
+
+    public static final String IMPORT_ANNOTATIONS = "import_annotations";
+
+    public static final String EXPORT_ANNOTATIONS = "export_annotations";
+
+    public static final String REMOVE_ALL_ANNOTATIONS = "remove_all_annotations";
+
+    public static final String GET_PAGE_COUNT = "get_page_count";
   }
 
 }

+ 68 - 8
android/src/main/java/com/compdfkit/flutter/compdfkit_flutter/plugin/CPDFDocumentPlugin.java

@@ -14,9 +14,13 @@ package com.compdfkit.flutter.compdfkit_flutter.plugin;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.CHECK_OWNER_UNLOCKED;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.CHECK_PASSWORD;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.CLOSE;
+import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.GET_PAGE_COUNT;
+import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.REMOVE_ALL_ANNOTATIONS;
+import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.EXPORT_ANNOTATIONS;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.GET_FILE_NAME;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.GET_PERMISSIONS;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.HAS_CHANGE;
+import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.IMPORT_ANNOTATIONS;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.IS_ENCRYPTED;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.IS_IMAGE_DOC;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.OPEN_DOCUMENT;
@@ -27,14 +31,16 @@ import android.text.TextUtils;
 import androidx.annotation.NonNull;
 import com.compdfkit.core.document.CPDFDocument;
 import com.compdfkit.core.document.CPDFDocument.PDFDocumentError;
+import com.compdfkit.core.page.CPDFPage;
+import com.compdfkit.tools.common.utils.CFileUtils;
 import com.compdfkit.tools.common.utils.threadpools.CThreadPoolUtils;
 import com.compdfkit.ui.reader.CPDFReaderView;
-import io.flutter.Log;
 import io.flutter.plugin.common.BinaryMessenger;
 import io.flutter.plugin.common.MethodCall;
 import io.flutter.plugin.common.MethodChannel.Result;
+import java.io.File;
 
-public class CPDFDocumentPlugin extends BaseMethodChannelPlugin{
+public class CPDFDocumentPlugin extends BaseMethodChannelPlugin {
 
   private String documentUid;
 
@@ -58,23 +64,23 @@ public class CPDFDocumentPlugin extends BaseMethodChannelPlugin{
 
   @Override
   public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
-    if (readerView == null || readerView.getPDFDocument() == null){
+    if (readerView == null || readerView.getPDFDocument() == null) {
       result.error("-1", "CPDFReaderView isnull or CPDFDocument is null", null);
       return;
     }
     CPDFDocument document = readerView.getPDFDocument();
-    switch (call.method){
+    switch (call.method) {
       case OPEN_DOCUMENT:
         String filePath = call.argument("filePath");
         String fileUri = call.argument("fileUri");
         String openPwd = call.argument("password");
         PDFDocumentError error;
-        if (!TextUtils.isEmpty(filePath)){
+        if (!TextUtils.isEmpty(filePath)) {
           error = document.open(filePath, openPwd);
         } else {
           error = document.open(Uri.parse(fileUri), openPwd);
         }
-        if (error == PDFDocumentError.PDFDocumentErrorSuccess){
+        if (error == PDFDocumentError.PDFDocumentErrorSuccess) {
           readerView.setPDFDocument(document);
         }
         result.success(error.ordinal());
@@ -86,7 +92,7 @@ public class CPDFDocumentPlugin extends BaseMethodChannelPlugin{
         result.success(document.isEncrypted());
         break;
       case IS_IMAGE_DOC:
-        CThreadPoolUtils.getInstance().executeIO(()->{
+        CThreadPoolUtils.getInstance().executeIO(() -> {
           boolean isImageDoc = document.isImageDoc();
           result.success(isImageDoc);
         });
@@ -108,7 +114,61 @@ public class CPDFDocumentPlugin extends BaseMethodChannelPlugin{
       case HAS_CHANGE:
         result.success(document.hasChanges());
         break;
-      default:break;
+      case IMPORT_ANNOTATIONS:
+        try {
+          String xfdfFilePath = (String) call.arguments;
+          File file = new File(xfdfFilePath);
+          if (!file.exists()) {
+            result.success(false);
+            return;
+          }
+          File cacheFile = new File(context.getCacheDir(),
+              CFileUtils.CACHE_FOLDER + File.separator + "importAnnotCache/"
+                  + CFileUtils.getFileNameNoExtension(document.getFileName()));
+          cacheFile.mkdirs();
+          boolean importResult = document.importAnnotations(xfdfFilePath,
+              cacheFile.getAbsolutePath());
+          readerView.reloadPages();
+          result.success(importResult);
+        } catch (Exception e) {
+          e.printStackTrace();
+          result.success(false);
+        }
+        break;
+      case EXPORT_ANNOTATIONS:
+        try {
+          File dirFile = new File(context.getFilesDir(), "compdfkit/annotation/export/");
+          dirFile.mkdirs();
+          String fileName = CFileUtils.getFileNameNoExtension(document.getFileName());
+          File cacheFile = new File(context.getCacheDir(),
+              CFileUtils.CACHE_FOLDER + File.separator + "exportAnnotCache/" + fileName);
+          cacheFile.mkdirs();
+          File saveFile = new File(dirFile, fileName + ".xfdf");
+          saveFile = CFileUtils.renameNameSuffix(saveFile);
+          boolean exportResult = document.exportAnnotations(saveFile.getAbsolutePath(),
+              cacheFile.getAbsolutePath());
+          if (exportResult) {
+            result.success(saveFile.getAbsolutePath());
+          } else {
+            result.success("");
+          }
+        } catch (Exception e) {
+          e.printStackTrace();
+          result.success("");
+        }
+        break;
+      case REMOVE_ALL_ANNOTATIONS:
+        boolean deleteResult = document.removeAllAnnotations();
+        if (deleteResult) {
+          readerView.invalidateAllChildren();
+        }
+        result.success(deleteResult);
+        break;
+      case GET_PAGE_COUNT:
+        result.success(document.getPageCount());
+        break;
+      default:
+        break;
     }
   }
 }

+ 14 - 2
android/src/main/java/com/compdfkit/flutter/compdfkit_flutter/plugin/CPDFViewCtrlPlugin.java

@@ -34,6 +34,7 @@ import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.Ch
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.SET_LINK_HIGHLIGHT;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.SET_PAGE_SAME_WIDTH;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.SET_MARGIN;
+import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.SET_PAGE_SPACING;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.SET_READ_BACKGROUND_COLOR;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.SET_SCALE;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.SET_VERTICAL_MODE;
@@ -91,6 +92,13 @@ public class CPDFViewCtrlPlugin extends BaseMethodChannelPlugin {
           }
         }
       });
+      pdfView.setSaveCallback((s, uri) -> {
+        if (methodChannel != null) {
+          methodChannel.invokeMethod("saveDocument", "");
+        }
+      }, e -> {
+
+      });
     });
   }
 
@@ -160,10 +168,14 @@ public class CPDFViewCtrlPlugin extends BaseMethodChannelPlugin {
         int right = call.argument("right");
         int bottom = call.argument("bottom");
         readerView.setFixReaderViewHorizontalMargin(true);
-        readerView.setReaderViewHorizontalMargin(left);
+        readerView.setReaderViewHorizontalMargin(left, right);
         readerView.setReaderViewTopMargin(top);
         readerView.setReaderViewBottomMargin(bottom);
-        readerView.setPageSpacing(top);
+        readerView.reloadPages();
+        break;
+      case SET_PAGE_SPACING:
+        int pageSpacing = (int) call.arguments;
+        readerView.setPageSpacing(pageSpacing);
         readerView.reloadPages();
         break;
       case SET_VERTICAL_MODE:

+ 10 - 0
android/src/main/java/com/compdfkit/flutter/compdfkit_flutter/plugin/ComPDFKitSDKPlugin.java

@@ -13,6 +13,7 @@ import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.Ch
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.INIT_SDK;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.INIT_SDK_KEYS;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.OPEN_DOCUMENT;
+import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.REMOVE_SIGN_FILE_LIST;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.SDK_BUILD_TAG;
 import static com.compdfkit.flutter.compdfkit_flutter.constants.CPDFConstants.ChannelMethod.SDK_VERSION_CODE;
 
@@ -23,11 +24,15 @@ import android.util.Log;
 import androidx.annotation.NonNull;
 
 import com.compdfkit.core.document.CPDFSdk;
+import com.compdfkit.core.utils.TFileUtils;
+import com.compdfkit.flutter.compdfkit_flutter.utils.FileUtils;
 import com.compdfkit.tools.common.pdf.CPDFConfigurationUtils;
 import com.compdfkit.tools.common.pdf.CPDFDocumentActivity;
 import com.compdfkit.tools.common.pdf.config.CPDFConfiguration;
+import com.compdfkit.tools.common.utils.CFileUtils;
 import com.compdfkit.tools.common.utils.CLog;
 
+import java.io.File;
 import java.util.Map;
 
 import io.flutter.plugin.common.BinaryMessenger;
@@ -83,6 +88,11 @@ public class ComPDFKitSDKPlugin extends BaseMethodChannelPlugin {
             case GET_TEMP_DIRECTORY:
                 result.success(context.getCacheDir().getPath());
                 break;
+            case REMOVE_SIGN_FILE_LIST:
+                File dirFile = new File(context.getFilesDir(), CFileUtils.SIGNATURE_FOLDER);
+                boolean deleteResult = FileUtils.deleteDirectory(dirFile.getAbsolutePath());
+                result.success(deleteResult);
+                break;
             default:
                 break;
         }

+ 89 - 0
android/src/main/java/com/compdfkit/flutter/compdfkit_flutter/utils/FileUtils.java

@@ -0,0 +1,89 @@
+/*
+ * Copyright © 2014-2024 PDF Technologies, Inc. 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 ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ *
+ */
+
+package com.compdfkit.flutter.compdfkit_flutter.utils;
+
+import android.widget.Toast;
+import java.io.File;
+
+
+public class FileUtils {
+  /** 删除文件,可以是文件或文件夹
+   * @param delFile 要删除的文件夹或文件名
+   * @return 删除成功返回true,否则返回false
+   */
+  public static boolean delete(String delFile) {
+    File file = new File(delFile);
+    if (!file.exists()) {
+      return false;
+    } else {
+      if (file.isFile())
+        return deleteSingleFile(delFile);
+      else
+        return deleteDirectory(delFile);
+    }
+  }
+
+  /** 删除单个文件
+   * @param filePath$Name 要删除的文件的文件名
+   * @return 单个文件删除成功返回true,否则返回false
+   */
+  public static  boolean deleteSingleFile(String filePath$Name) {
+    File file = new File(filePath$Name);
+    // 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
+    if (file.exists() && file.isFile()) {
+      if (file.delete()) {
+        return true;
+      } else {
+        return false;
+      }
+    } else {
+      return false;
+    }
+  }
+
+  /** 删除目录及目录下的文件
+   * @param filePath 要删除的目录的文件路径
+   * @return 目录删除成功返回true,否则返回false
+   */
+  public static  boolean deleteDirectory(String filePath) {
+    // 如果dir不以文件分隔符结尾,自动添加文件分隔符
+    if (!filePath.endsWith(File.separator))
+      filePath = filePath + File.separator;
+    File dirFile = new File(filePath);
+    if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
+      return false;
+    }
+    boolean flag = true;
+    File[] files = dirFile.listFiles();
+    for (File file : files) {
+      if (file.isFile()) {
+        flag = deleteSingleFile(file.getAbsolutePath());
+        if (!flag)
+          break;
+      }
+      else if (file.isDirectory()) {
+        flag = deleteDirectory(file
+            .getAbsolutePath());
+        if (!flag)
+          break;
+      }
+    }
+    if (!flag) {
+      return false;
+    }
+    if (dirFile.delete()) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+}

+ 1 - 0
example/android/build.gradle

@@ -2,6 +2,7 @@ allprojects {
     repositories {
         google()
         mavenCentral()
+        mavenLocal()
     }
 }
 apply from: "config.gradle"

+ 39 - 2
example/lib/cpdf_reader_widget_controller_example.dart

@@ -8,11 +8,13 @@
 import 'dart:io';
 import 'dart:math';
 
+import 'package:compdfkit_flutter/compdfkit.dart';
 import 'package:compdfkit_flutter/configuration/cpdf_configuration.dart';
 import 'package:compdfkit_flutter/configuration/cpdf_options.dart';
 import 'package:compdfkit_flutter/util/extension/cpdf_color_extension.dart';
 import 'package:compdfkit_flutter/widgets/cpdf_reader_widget.dart';
 import 'package:compdfkit_flutter/widgets/cpdf_reader_widget_controller.dart';
+import 'package:compdfkit_flutter_example/utils/file_util.dart';
 import 'package:file_picker/file_picker.dart';
 import 'package:flutter/material.dart';
 
@@ -71,6 +73,12 @@ class _CPDFReaderWidgetControllerExampleState
               _controller = controller;
             });
           },
+          onPageChanged: (pageIndex){
+            debugPrint('pageIndex:${pageIndex}');
+          },
+          onSaveCallback: (){
+            debugPrint('CPDFDocument: save success');
+          },
         ));
   }
 
@@ -81,6 +89,9 @@ class _CPDFReaderWidgetControllerExampleState
 
   void handleClick(String value, CPDFReaderWidgetController controller) async {
     switch (value) {
+      case 'save':
+        await controller.save();
+        break;
       case 'setScale':
         controller.setScale(1.5);
         break;
@@ -111,7 +122,10 @@ class _CPDFReaderWidgetControllerExampleState
         final Random random = Random();
         int value = random.nextInt(50);
         debugPrint('ComPDFKit:setMargin:$value');
-        controller.setMargins(const CPDFEdgeInsets.symmetric(horizontal: 100, vertical: 10));
+        controller.setMargins(const CPDFEdgeInsets.only(left: 10, top:10, right: 10, bottom: 10));
+        break;
+      case "setPageSpacing":
+        await controller.setPageSpacing(20);
         break;
       case 'setContinueMode':
         bool isContinueMode = await controller.isContinueMode();
@@ -169,6 +183,7 @@ class _CPDFReaderWidgetControllerExampleState
         debugPrint('ComPDFKit:Document: isEncrypted:${await document.isEncrypted()}');
         debugPrint('ComPDFKit:Document: isImageDoc:${await document.isImageDoc()}');
         debugPrint('ComPDFKit:Document: getPermissions:${await document.getPermissions()}');
+        debugPrint('ComPDFKit:Document: getPageCount:${await document.getPageCount()}');
         break;
       case "openDocument":
         FilePickerResult? result = await FilePicker.platform.pickFiles(
@@ -180,11 +195,28 @@ class _CPDFReaderWidgetControllerExampleState
           document.open(result.files.first.path!, "");
         }
         break;
+      case "importAnnotations":
+        File xfdfFile = await extractAsset(context, 'pdfs/test.xfdf');
+        bool result = await controller.document.importAnnotations(xfdfFile.path);
+        debugPrint('ComPDFKit:Document: importAnnotations:$result');
+        break;
+      case "exportAnnotations":
+        String xfdfPath = await controller.document.exportAnnotations();
+        debugPrint('ComPDFKit:Document: exportAnnotations:$xfdfPath');
+        break;
+      case "removeAllAnnotations":
+        await controller.document.removeAllAnnotations();
+        break;
+      case "removeSignFileList":
+        bool result = await ComPDFKit.removeSignFileList();
+        debugPrint('ComPDFKit:removeSignFileList:${result}');
+        break;
     }
   }
 }
 
 var actions = [
+  'save',
   'setScale',
   'getScale',
   if(Platform.isAndroid) ...[
@@ -193,6 +225,7 @@ var actions = [
     'isPageInScreen',
     'setFixedScroll',
     'setReadBackgroundColor',
+    'setPageSpacing'
   ],
   'setFormHighlight',
   'setLinkHighlight',
@@ -206,7 +239,11 @@ var actions = [
   'setCoverPageMode',
   'isChanged',
   'documentInfo',
-  'openDocument'
+  'openDocument',
+  'importAnnotations',
+  'exportAnnotations',
+  'removeAllAnnotations',
+  'removeSignFileList'
 ];
 
 Color randomColor() {

+ 1 - 1
example/pubspec.lock

@@ -55,7 +55,7 @@ packages:
       path: ".."
       relative: true
     source: path
-    version: "2.1.3"
+    version: "2.2.0"
   cross_file:
     dependency: transitive
     description:

+ 1 - 1
example/pubspec.yaml

@@ -1,6 +1,6 @@
 name: compdfkit_flutter_example
 description: Demonstrates how to use the compdfkit_flutter plugin.
-version: 2.1.3
+version: 2.2.0
 homepage: https://www.compdf.com
 repository: https://github.com/ComPDFKit/compdfkit-pdf-sdk-flutter
 issue_tracker: https://www.compdf.com/support

+ 5 - 0
ios/Classes/reader/CPDFViewCtrlPlugin.swift

@@ -26,6 +26,11 @@ class CPDFViewCtrlPlugin {
 
         var documentPlugin = CPDFDocumentPlugin(pdfViewController: pdfViewController, uid: String(describing: viewId), binaryMessager: messenger)
 
+        // TODO: 返回当前滑动到的页码
+        _methodChannel.invokeMethod("onPageChanged", arguments: 1)
+        
+        // TODO: 监听到执行了保存的回调
+        _methodChannel.invokeMethod("saveDocument", arguments: nil)
     }
     
     

+ 4 - 0
lib/compdfkit.dart

@@ -88,4 +88,8 @@ class ComPDFKit {
     }
     return Directory(path);
   }
+
+  static Future<bool> removeSignFileList() async {
+    return await _methodChannel.invokeMethod('remove_sign_file_list');
+  }
 }

+ 14 - 4
lib/configuration/cpdf_configuration.dart

@@ -7,6 +7,7 @@
 
 
 import 'dart:convert';
+import 'dart:ffi';
 
 import 'package:compdfkit_flutter/configuration/attributes/cpdf_annot_attr.dart';
 
@@ -94,6 +95,7 @@ class CPDFModeConfig {
 
 /// Configuration for top toolbar functionality.
 class CPDFToolbarConfig {
+
   /// Top toolbar actions for Android platform
   ///
   /// Default: thumbnail, search, bota, menu.
@@ -114,6 +116,8 @@ class CPDFToolbarConfig {
   /// Configure the menu options opened in the top toolbar [CPDFToolbarAction.menu]
   final List<CPDFToolbarMenuAction> availableMenus;
 
+  final bool mainToolbarVisible;
+
   const CPDFToolbarConfig(
       {this.androidAvailableActions = const [
         CPDFToolbarAction.thumbnail,
@@ -141,7 +145,8 @@ class CPDFToolbarConfig {
         CPDFToolbarMenuAction.share,
         CPDFToolbarMenuAction.openDocument,
         CPDFToolbarMenuAction.snip
-      ]});
+      ],
+      this.mainToolbarVisible = true});
 
   Map<String, dynamic> toJson() => {
         'androidAvailableActions':
@@ -150,7 +155,8 @@ class CPDFToolbarConfig {
             iosLeftBarAvailableActions.map((e) => e.name).toList(),
         'iosRightBarAvailableActions':
             iosRightBarAvailableActions.map((e) => e.name).toList(),
-        'availableMenus': availableMenus.map((e) => e.name).toList()
+        'availableMenus': availableMenus.map((e) => e.name).toList(),
+        'mainToolbarVisible' : mainToolbarVisible
       };
 }
 
@@ -202,6 +208,8 @@ class CPDFReaderViewConfig {
   /// only android platform
   final bool pageSameWidth;
 
+  final List<int> margins;
+
   const CPDFReaderViewConfig(
       {this.linkHighlight = true,
       this.formFieldHighlight = true,
@@ -214,7 +222,8 @@ class CPDFReaderViewConfig {
       this.enablePageIndicator = true,
       this.pageSpacing = 10,
       this.pageScale = 1.0,
-      this.pageSameWidth = true});
+      this.pageSameWidth = true,
+      this.margins = const [0,0,0,0]});
 
   Map<String, dynamic> toJson() => {
         'linkHighlight': linkHighlight,
@@ -228,7 +237,8 @@ class CPDFReaderViewConfig {
         'enablePageIndicator': enablePageIndicator,
         'pageSpacing': pageSpacing,
         'pageScale': pageScale,
-        'pageSameWidth': pageSameWidth
+        'pageSameWidth': pageSameWidth,
+        'margins' : margins
       };
 }
 

+ 6 - 7
lib/configuration/cpdf_options.dart

@@ -135,16 +135,15 @@ enum CPDFCheckStyle { check, circle, cross, diamond, square, star }
 
 enum CPDFThemeMode { light, dark, system }
 
-/// The [CPDFEdgeInsets] is used to set the padding of the PDF document.
+/// [CPDFEdgeInsets] defines the padding for a PDF document.
 ///
-/// [Android] can only set horizontal margins, [top] and [bottom] margins.
-/// Horizontal spacing cannot be set independently.
-/// The horizontal spacing value is set using the [left] attribute,
-/// the spacing between two pages is the same as the top spacing.
+/// - On **Android**, you can set individual margins for [top], [bottom], [left], and [right].
+///   To adjust the spacing between pages, use the `setPageSpacing()` method.
 ///
-/// The [iOS] platform can set the [top], [bottom], [left] and [right] margins,
-/// and the spacing between two pages is the same as the top spacing.
+/// - On **iOS**, you can also configure [top], [bottom], [left], and [right] margins.
+///   The spacing between pages is equal to the [top] margin.
 class CPDFEdgeInsets {
+
   final int left;
 
   final int top;

+ 51 - 1
lib/document/cpdf_document.dart

@@ -128,6 +128,56 @@ class CPDFDocument {
     _isValid = false;
   }
 
-  Future<void> getInfo() async {}
+  /// Imports annotations from the specified XFDF file into the current PDF document.
+  ///
+  /// **Parameters:**<br/>
+  ///   xfdfFile - Path of the XFDF file to be imported.
+  ///
+  /// **example:**
+  /// ```dart
+  /// bool result = await document.importAnnotations(xxx.xfdf);
+  /// ```
+  ///
+  /// **Returns:**
+  ///   true if the import is successful; otherwise, false.
+  Future<bool> importAnnotations(String xfdfFile) async {
+    return await _channel.invokeMethod('import_annotations', xfdfFile);
+  }
+
+  /// Exports annotations from the current PDF document to an XFDF file.
+  ///
+  /// **example:**
+  /// ```dart
+  /// String xfdfPath = await document.exportAnnotations();
+  /// ```
+  ///
+  /// Returns:
+  ///   The path of the XFDF file if export is successful; an empty string if the export fails.
+  Future<String> exportAnnotations() async {
+    return await _channel.invokeMethod('export_annotations');
+  }
+
+
+  /// Delete all comments in the current document
+  ///
+  /// example:
+  /// ```dart
+  /// bool result = await document.removeAllAnnotations();
+  /// ```
+  Future<bool> removeAllAnnotations() async {
+    return await _channel.invokeMethod('remove_all_annotations');
+  }
+
+  /// Get the total number of pages in the current document
+  ///
+  /// example:
+  /// ```dart
+  /// int pageCount = await document.getPageCount();
+  /// ```
+  Future<int> getPageCount()  async {
+    return await _channel.invokeMethod('get_page_count');
+  }
+
+  // Future<void> getInfo() async {}
 
 }

+ 7 - 2
lib/widgets/cpdf_reader_widget.dart

@@ -21,6 +21,8 @@ typedef CPDFReaderWidgetCreatedCallback = void Function(
 
 typedef CPDFPageChangedCallback = void Function(int pageIndex);
 
+typedef CPDFDocumentSaveCallback = void Function();
+
 
 class CPDFReaderWidget extends StatefulWidget {
   /// pdf file path
@@ -35,6 +37,8 @@ class CPDFReaderWidget extends StatefulWidget {
 
   final CPDFPageChangedCallback? onPageChanged;
 
+  final CPDFDocumentSaveCallback? onSaveCallback;
+
   /// init callback
   const CPDFReaderWidget(
       {Key? key,
@@ -42,7 +46,8 @@ class CPDFReaderWidget extends StatefulWidget {
       this.password = '',
       required this.configuration,
       required this.onCreated,
-      this.onPageChanged})
+      this.onPageChanged,
+      this.onSaveCallback})
       : super(key: key);
 
   @override
@@ -100,6 +105,6 @@ class _CPDFReaderWidgetState extends State<CPDFReaderWidget> {
 
   Future<void> _onPlatformViewCreated(int id) async {
     debugPrint('ComPDFKit-Flutter: CPDFReaderWidget created');
-    widget.onCreated(CPDFReaderWidgetController(id, onPageChanged: widget.onPageChanged));
+    widget.onCreated(CPDFReaderWidgetController(id, onPageChanged: widget.onPageChanged, saveCallback : widget.onSaveCallback));
   }
 }

+ 19 - 2
lib/widgets/cpdf_reader_widget_controller.dart

@@ -5,7 +5,6 @@
 // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
 // This notice may not be removed from this file.
 
-import 'dart:ffi';
 import 'dart:io';
 import 'package:flutter/services.dart';
 
@@ -32,11 +31,14 @@ import 'cpdf_reader_widget.dart';
 ///         ));
 /// ```
 class CPDFReaderWidgetController {
+
   late MethodChannel _channel;
 
   late CPDFDocument _document;
 
-  CPDFReaderWidgetController(int id, {CPDFPageChangedCallback? onPageChanged}) {
+  CPDFReaderWidgetController(int id, {
+    CPDFPageChangedCallback? onPageChanged,
+    CPDFDocumentSaveCallback? saveCallback}) {
     _channel = MethodChannel('com.compdfkit.flutter.ui.pdfviewer.$id');
     _channel.setMethodCallHandler((call) async {
       switch (call.method) {
@@ -44,6 +46,9 @@ class CPDFReaderWidgetController {
           var pageIndex = call.arguments['pageIndex'];
           onPageChanged?.call(pageIndex);
           break;
+        case 'saveDocument':
+          saveCallback?.call();
+          break;
       }
     });
     _document = CPDFDocument.withController(id);
@@ -200,6 +205,17 @@ class CPDFReaderWidgetController {
     await _channel.invokeMethod('set_margin' , edgeInsets.toJson());
   }
 
+  /// Sets the spacing between pages. This method is supported only on the [Android] platform.
+  ///
+  /// - For the [iOS] platform, use the [setMargins] method instead.
+  ///   The spacing between pages is equal to the value of [CPDFEdgeInsets.top].
+  ///
+  /// Parameters:
+  /// [spacing] The space between pages, in pixels.
+  Future<void> setPageSpacing(int spacing) async {
+    await _channel.invokeMethod('set_page_spacing', spacing);
+  }
+
   /// Sets whether it is continuous scroll mode.
   ///
   /// [isContinueMode] Whether it is continuous scroll mode.
@@ -350,6 +366,7 @@ class CPDFReaderWidgetController {
   /// ```dart
   /// bool hasChange = await document.hasChange();
   /// ```
+  @Deprecated("use CPDFDocument().hasChange()")
   Future<bool> hasChange() async {
     return await _document.hasChange();
   }

+ 1 - 1
pubspec.yaml

@@ -1,6 +1,6 @@
 name: compdfkit_flutter
 description: ComPDFKit for Flutter is a comprehensive SDK that allows you to quickly add PDF functionality to Android and iOS Flutter applications.
-version: 2.1.3
+version: 2.2.0
 homepage: https://www.compdf.com
 repository: https://github.com/ComPDFKit/compdfkit-pdf-sdk-flutter
 issue_tracker: https://www.compdf.com/support