Browse Source

PDFTool(Android) - 注释回复列表

liuxiaolong 8 months ago
parent
commit
759a3571a0
19 changed files with 1084 additions and 102 deletions
  1. BIN
      ComPDFKit_Repo/compdfkit-ui/ComPDFKit-UI.aar
  2. BIN
      ComPDFKit_Repo/compdfkit/ComPDFKit.aar
  3. 45 54
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfannotationlist/CPDFAnnotationListFragment.java
  4. 78 10
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfannotationlist/adapter/CPDFAnnotListAdapter.java
  5. 179 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfannotationlist/adapter/CPDFAnnotReplyListAdapter.java
  6. 0 20
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfannotationlist/bean/CPDFAnnotListItem.java
  7. 6 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfannotationlist/data/CPDFAnnotDatas.java
  8. 111 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfannotationlist/dialog/CPDFEditReplyDialogFragment.java
  9. 216 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfannotationlist/dialog/CPDFReplyDetailsDialogFragment.java
  10. 24 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/basic/fragment/CBasicBottomSheetDialogFragment.java
  11. 1 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/pdf/CPDFDocumentFragment.java
  12. 4 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/adapter/CBaseQuickViewHolder.java
  13. 11 5
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfview/CPDFViewCtrl.java
  14. 48 0
      ComPDFKit_Tools/src/main/res/layout/tools_annot_edit_reply_dialog_fragment.xml
  15. 106 0
      ComPDFKit_Tools/src/main/res/layout/tools_annot_reply_details_annot_content.xml
  16. 114 0
      ComPDFKit_Tools/src/main/res/layout/tools_annot_reply_details_dialog_fragment.xml
  17. 119 0
      ComPDFKit_Tools/src/main/res/layout/tools_annot_reply_list_item_content.xml
  18. 8 4
      ComPDFKit_Tools/src/main/res/layout/tools_bota_annotation_list_item_content.xml
  19. 14 7
      ComPDFKit_Tools/src/main/res/values/tools_strings.xml

BIN
ComPDFKit_Repo/compdfkit-ui/ComPDFKit-UI.aar


BIN
ComPDFKit_Repo/compdfkit/ComPDFKit.aar


+ 45 - 54
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfannotationlist/CPDFAnnotationListFragment.java

@@ -33,6 +33,7 @@ import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.compdfkit.core.annotation.CPDFAnnotation;
+import com.compdfkit.core.annotation.CPDFReplyAnnotation;
 import com.compdfkit.core.document.CPDFDocument;
 import com.compdfkit.core.page.CPDFPage;
 import com.compdfkit.tools.R;
@@ -41,6 +42,8 @@ import com.compdfkit.tools.annotation.pdfannotationlist.adapter.CPDFAnnotListAda
 import com.compdfkit.tools.annotation.pdfannotationlist.bean.CPDFAnnotListItem;
 import com.compdfkit.tools.annotation.pdfannotationlist.data.CPDFAnnotDatas;
 import com.compdfkit.tools.annotation.pdfannotationlist.dialog.CMarkedTipsWindow;
+import com.compdfkit.tools.annotation.pdfannotationlist.dialog.CPDFEditReplyDialogFragment;
+import com.compdfkit.tools.annotation.pdfannotationlist.dialog.CPDFReplyDetailsDialogFragment;
 import com.compdfkit.tools.common.interfaces.COnSetPDFDisplayPageIndexListener;
 import com.compdfkit.tools.common.utils.CFileUtils;
 import com.compdfkit.tools.common.utils.CLog;
@@ -51,11 +54,9 @@ import com.compdfkit.tools.common.utils.viewutils.CDimensUtils;
 import com.compdfkit.tools.common.utils.window.CPopupMenuWindow;
 import com.compdfkit.tools.common.views.directory.CFileDirectoryDialog;
 import com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl;
-import com.compdfkit.ui.reader.CPDFPageView;
 
 import java.io.File;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 
@@ -77,7 +78,12 @@ public class CPDFAnnotationListFragment extends Fragment {
         return new CPDFAnnotationListFragment();
     }
 
-
+    /**
+     * Used to select `xfdf` format annotation files from the system file manager
+     * and import them into PDF documents
+     * sample:<br/><br/>
+     * importAnnotFileLauncher.launch(CFileUtils.getIntent("application/octet-stream")
+     */
     private ActivityResultLauncher<Intent> importAnnotFileLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
         if (result.getResultCode() == Activity.RESULT_OK) {
             Uri uri = result.getData().getData();
@@ -130,19 +136,19 @@ public class CPDFAnnotationListFragment extends Fragment {
             CPDFAnnotListItem item = adapter.list.get(position);
             if (view1.getId() == R.id.cl_root) {
                 if (!item.isHeader()) {
+                    // Close the dialog and jump to the corresponding page number
                     if (displayPageIndexListener != null) {
                         displayPageIndexListener.displayPage(item.getPage());
                     }
                 }
             } else if(view1.getId() == R.id.iv_review_status){
-                showReviewStatusMenu(item,position, view1);
+                listAdapter.showReviewStatusMenu(getContext(), position, view1);
             } else if(view1.getId() == R.id.cb_marked_status){
-                showMarkedStatusMenu(position, view1);
+                listAdapter.showMarkedStatusMenu(getContext(), position, view1);
             } else if(view1.getId() == R.id.iv_more){
                 showAnnotationMoreMenu(item, position, view1);
             }
         },R.id.iv_review_status, R.id.cb_marked_status, R.id.iv_more, R.id.cl_root);
-
         rvAnnotation.setLayoutManager(new LinearLayoutManager(getContext()));
         rvAnnotation.setAdapter(listAdapter);
     }
@@ -152,6 +158,10 @@ public class CPDFAnnotationListFragment extends Fragment {
         updateAnnotationList(true);
     }
 
+    /**
+     * Reload the annotation list data
+     * @param showProgressBar Whether to display the loading status when loading
+     */
     public void updateAnnotationList(boolean showProgressBar) {
         if (showProgressBar){
             progressBar.setVisibility(View.VISIBLE);
@@ -172,7 +182,6 @@ public class CPDFAnnotationListFragment extends Fragment {
         });
     }
 
-
     /**
      * show toolbar annotation menu, in CPDFBOTAFragment
      * @param anchorView
@@ -183,6 +192,7 @@ public class CPDFAnnotationListFragment extends Fragment {
             importAnnotFileLauncher.launch(CFileUtils.getIntent("application/octet-stream"));
         });
         menuWindow.addItem(R.string.tools_export_annotations, v -> {
+            // Select the directory to export the annotation files
             String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath();
             CFileDirectoryDialog directoryDialog = CFileDirectoryDialog.newInstance(dirPath, getString(R.string.tools_saving_path), getString(R.string.tools_okay));
             directoryDialog.setSelectFolderListener(dir -> {
@@ -217,58 +227,39 @@ public class CPDFAnnotationListFragment extends Fragment {
         }
     }
 
-    private void showReviewStatusMenu(CPDFAnnotListItem item,int position, View anchorView){
-        anchorView.setSelected(true);
-        reviewStatusMenuWindow = new CPopupMenuWindow(getContext());
-        reviewStatusMenuWindow.setOutsideTouchable(false);
-        reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_accepted, R.string.tools_accepted, v -> {
-            listAdapter.setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_ACCEPTED);
-        });
-        reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_rejected, R.string.tools_rejected, v -> {
-            listAdapter.setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_REJECTED);
-        });
-        reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_cancelled, R.string.tools_cancelled, v -> {
-            listAdapter.setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_CANCELLED);
-
-        });
-        reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_completed, R.string.tools_completed, v -> {
-            listAdapter.setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_COMPLETED);
-        });
-        reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_none, R.string.tools_none, v -> {
-            listAdapter.setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_NONE);
-        });
-        reviewStatusMenuWindow.setOnDismissListener(() -> anchorView.setSelected(false));
-        int[] windowPos = CDimensUtils.calculatePopWindowPos(anchorView, reviewStatusMenuWindow.getContentView());
-        windowPos[0] -= reviewStatusMenuWindow.getContentView().getMeasuredWidth() /2;
-
-        windowPos[1] -= anchorView.getMeasuredHeight() / 2;
-        windowPos[1] -= anchorView.getMeasuredHeight();
-        reviewStatusMenuWindow.setAnimationStyle(R.style.PopupAnimation);
-        reviewStatusMenuWindow.showAtLocation(anchorView, Gravity.START | Gravity.TOP, windowPos[0], windowPos[1]);
-    }
-
-    private void showMarkedStatusMenu( int position,View anchorView){
-        listAdapter.checkedMarkedStatus(position);
-        CMarkedTipsWindow tipsWindow = new CMarkedTipsWindow(getContext());
-        tipsWindow.setMarkState(listAdapter.list.get(position).getMarkState());
-
-        tipsWindow.getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
-        int winWidth = tipsWindow.getContentView().getMeasuredWidth();
-        int winHeight = tipsWindow.getContentView().getMeasuredHeight();
-        int anchorViewWidth = anchorView.getWidth();
-        int anchorViewHeight = anchorView.getHeight();
-        int offsetX = (anchorViewWidth - winWidth) / 2;
-        int offsetY = anchorViewHeight + winHeight;
-        tipsWindow.showAsDropDown(anchorView, offsetX, -offsetY);
-    }
-
+    /**
+     * Displays the more options menu for the selected annotation, including:
+     * adding an annotation reply, showing the annotation reply list, and deleting the annotation.
+     * @param item The annotation data currently selected from the list
+     * @param position The position of the selected item in the list
+     * @param anchorView The view to anchor the menu to
+     */
     private void showAnnotationMoreMenu(CPDFAnnotListItem item, int position, View anchorView){
         CPopupMenuWindow moreMenu = new CPopupMenuWindow(getContext());
         moreMenu.addItem(R.string.tools_add_a_new_reply,v -> {
-
+            CPDFEditReplyDialogFragment editReplyDialogFragment = CPDFEditReplyDialogFragment.addReply();
+            editReplyDialogFragment.setReplyContentListener(content -> {
+                CPDFReplyAnnotation replyAnnotation = item.getAttr().createReplyAnnotation();
+                replyAnnotation.setTitle(pdfView.getCPDFConfiguration().globalConfig.annotationAuthor);
+                replyAnnotation.setContent(content);
+            });
+            editReplyDialogFragment.show(getChildFragmentManager(), "addReplyDialogFragment");
         });
         moreMenu.addItem(R.string.tools_view_replies, v -> {
-
+            CPDFReplyDetailsDialogFragment replyDetailsDialogFragment = CPDFReplyDetailsDialogFragment.newInstance();
+            replyDetailsDialogFragment.setItem(item);
+            replyDetailsDialogFragment.setAnnotAuthor(pdfView.getCPDFConfiguration().globalConfig.annotationAuthor);
+            replyDetailsDialogFragment.setUpdateAnnotationListListener(()->{
+                listAdapter.remove(position);
+                ArrayList<Integer> pages = new ArrayList<>();
+                pages.add(item.getPage());
+                pdfView.getCPdfReaderView().reloadPages(pages);
+                pdfView.getCPdfReaderView().postDelayed(()-> updateAnnotationList(false), 450);
+            });
+            replyDetailsDialogFragment.setDismissListener(()->{
+                listAdapter.notifyItemChanged(position);
+            });
+            replyDetailsDialogFragment.show(getChildFragmentManager(), "replyDetailsDialogFragment");
         });
         moreMenu.addItem(R.string.tools_delete_annotation, v -> {
             boolean result = item.getAttr().removeFromPage();

+ 78 - 10
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfannotationlist/adapter/CPDFAnnotListAdapter.java

@@ -13,6 +13,8 @@ import android.content.Context;
 import android.content.res.ColorStateList;
 import android.graphics.Color;
 import android.text.TextUtils;
+import android.view.Gravity;
+import android.view.View;
 import android.view.ViewGroup;
 
 import androidx.annotation.NonNull;
@@ -25,9 +27,12 @@ import com.compdfkit.core.annotation.CPDFReplyAnnotation;
 import com.compdfkit.tools.R;
 import com.compdfkit.tools.annotation.pdfannotationbar.bean.CAnnotToolBean;
 import com.compdfkit.tools.annotation.pdfannotationlist.bean.CPDFAnnotListItem;
+import com.compdfkit.tools.annotation.pdfannotationlist.dialog.CMarkedTipsWindow;
 import com.compdfkit.tools.common.utils.adapter.CBaseQuickAdapter;
 import com.compdfkit.tools.common.utils.adapter.CBaseQuickViewHolder;
+import com.compdfkit.tools.common.utils.viewutils.CDimensUtils;
 import com.compdfkit.tools.common.utils.viewutils.CViewUtils;
+import com.compdfkit.tools.common.utils.window.CPopupMenuWindow;
 import com.google.android.material.color.MaterialColors;
 
 import java.util.HashMap;
@@ -47,6 +52,8 @@ public class CPDFAnnotListAdapter  extends CBaseQuickAdapter<CPDFAnnotListItem,
     private static final HashMap<CPDFAnnotation.Type, Integer> ICON_RES_IDS = new HashMap<>();
     private static final HashMap<CPDFAnnotation.Type, Integer> ICON_RES_IDS_DARK = new HashMap<>();
 
+    private boolean showMoreMenu = true;
+
     static {
         ICON_RES_IDS.put(CPDFAnnotation.Type.TEXT, R.drawable.tools_ic_annotation_note);
         ICON_RES_IDS.put(CPDFAnnotation.Type.HIGHLIGHT, R.drawable.tools_ic_annotation_highlight_normal);
@@ -148,8 +155,9 @@ public class CPDFAnnotListAdapter  extends CBaseQuickAdapter<CPDFAnnotListItem,
             holder.setText(R.id.tv_annot_content, item.getContent());
             holder.setText(R.id.tv_annot_date, item.getModifyDate());
             holder.setText(R.id.tv_author, item.getAttr().getTitle());
-            refreshReviewStatus(holder, item, item.getReviewState());
-            refreshMarkedStatus(holder, item.getMarkState());
+            holder.setVisible(R.id.iv_more, showMoreMenu);
+            refreshReviewStatus(holder, item.getAttr().getReviewAnnotState());
+            refreshMarkedStatus(holder, item.getAttr().getMarkedAnnotState());
         }
     }
 
@@ -158,18 +166,18 @@ public class CPDFAnnotListAdapter  extends CBaseQuickAdapter<CPDFAnnotListItem,
         if (payloads.isEmpty()){
             super.onBindViewHolder(holder, position, payloads);
         }else {
+            CPDFAnnotListItem item = list.get(position);
             for (Object payload : payloads) {
                 if(payload == REFRESH_REVIEW_STATUS){
-                    refreshReviewStatus((CBaseQuickViewHolder) holder, list.get(holder.getAdapterPosition()), list.get(holder.getAdapterPosition()).getReviewState());
+          refreshReviewStatus((CBaseQuickViewHolder) holder, item.getAttr().getReviewAnnotState());
                 } else if(payload == REFRESH_MARKED_STATUS){
-                    refreshMarkedStatus((CBaseQuickViewHolder) holder, list.get(holder.getAdapterPosition()).getMarkState());
+          refreshMarkedStatus((CBaseQuickViewHolder) holder, item.getAttr().getMarkedAnnotState());
                 }
             }
         }
     }
 
-    private void refreshReviewStatus(CBaseQuickViewHolder adapter, CPDFAnnotListItem item, CPDFAnnotation.ReviewState reviewState){
-//        CPDFReplyAnnotation replyAnnotation =
+    private void refreshReviewStatus(CBaseQuickViewHolder adapter, CPDFAnnotation.ReviewState reviewState){
         switch (reviewState){
             case REVIEW_NONE:
                 adapter.setImageResource(R.id.iv_review_status, R.drawable.tools_annot_review_status_none);
@@ -201,23 +209,83 @@ public class CPDFAnnotListAdapter  extends CBaseQuickAdapter<CPDFAnnotListItem,
     }
 
     public void setReviewStatus(int position, CPDFAnnotation.ReviewState reviewState){
-        list.get(position).setReviewState(reviewState);
+        CPDFAnnotation annotation = list.get(position).getAttr();
+        annotation.setReviewAnnotState(reviewState);
+        annotation.updateAp();
         notifyItemChanged(position, REFRESH_REVIEW_STATUS);
     }
 
     public void checkedMarkedStatus(int position){
         CPDFAnnotListItem item = list.get(position);
-        if (item.getMarkState() == CPDFAnnotation.MarkState.MARKED) {
-            item.setMarkState(CPDFAnnotation.MarkState.UNMARKED);
+        if (item.getAttr().getMarkedAnnotState() == CPDFAnnotation.MarkState.MARKED) {
+            item.getAttr().setMarkedAnnotState(CPDFAnnotation.MarkState.UNMARKED);
         }else {
-            item.setMarkState(CPDFAnnotation.MarkState.MARKED);
+            item.getAttr().setMarkedAnnotState(CPDFAnnotation.MarkState.MARKED);
         }
+        item.getAttr().updateAp();
         notifyItemChanged(position, REFRESH_MARKED_STATUS);
     }
 
+    public void setShowMoreMenu(boolean showMoreMenu) {
+        this.showMoreMenu = showMoreMenu;
+    }
+
     @Override
     public int getItemViewType(int position) {
        return list.get(position).isHeader() ? ITEM_HEADER : ITEM_CONTENT;
     }
 
+    /**
+     * Display the comment reply status menu
+     * @param position The subscript of the selected annotation in the list
+     * @param anchorView The position anchor view to be popped up, displayed above or below it
+     */
+    public void showReviewStatusMenu(Context context, int position, View anchorView){
+        anchorView.setSelected(true);
+        CPopupMenuWindow reviewStatusMenuWindow = new CPopupMenuWindow(context);
+        reviewStatusMenuWindow.setOutsideTouchable(false);
+        reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_accepted, R.string.tools_accepted, v -> {
+            setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_ACCEPTED);
+        });
+        reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_rejected, R.string.tools_rejected, v -> {
+            setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_REJECTED);
+        });
+        reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_cancelled, R.string.tools_cancelled, v -> {
+            setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_CANCELLED);
+        });
+        reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_completed, R.string.tools_completed, v -> {
+            setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_COMPLETED);
+        });
+        reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_none, R.string.tools_none, v -> {
+            setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_NONE);
+        });
+        reviewStatusMenuWindow.setOnDismissListener(() -> anchorView.setSelected(false));
+        //Calculate the position of the pop-up.
+        // If there is enough space at the bottom,
+        // it will be displayed below the anchor view. If not, it will be displayed above it.
+        int[] windowPos = CDimensUtils.calculatePopWindowPos(anchorView, reviewStatusMenuWindow.getContentView());
+        windowPos[0] -= reviewStatusMenuWindow.getContentView().getMeasuredWidth() /2;
+        windowPos[1] -= anchorView.getMeasuredHeight() / 2;
+        windowPos[1] -= anchorView.getMeasuredHeight();
+        reviewStatusMenuWindow.setAnimationStyle(R.style.PopupAnimation);
+        reviewStatusMenuWindow.showAtLocation(anchorView, Gravity.START | Gravity.TOP, windowPos[0], windowPos[1]);
+    }
+
+    /**
+     * Show annotation markup status menu
+     * @param position The subscript of the selected annotation in the list
+     * @param anchorView The position anchor view to be popped up, displayed above or below it
+     */
+    public void showMarkedStatusMenu(Context context, int position, View anchorView){
+        checkedMarkedStatus(position);
+        CMarkedTipsWindow tipsWindow = new CMarkedTipsWindow(context);
+        tipsWindow.setMarkState(list.get(position).getAttr().getMarkedAnnotState());
+        tipsWindow.getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+        int winWidth = tipsWindow.getContentView().getMeasuredWidth();
+        int winHeight = tipsWindow.getContentView().getMeasuredHeight();
+        int offsetX = (anchorView.getWidth() - winWidth) / 2;
+        int offsetY =  anchorView.getHeight() + winHeight;
+        tipsWindow.showAsDropDown(anchorView, offsetX, -offsetY);
+    }
+
 }

+ 179 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfannotationlist/adapter/CPDFAnnotReplyListAdapter.java

@@ -0,0 +1,179 @@
+/**
+ * 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.tools.annotation.pdfannotationlist.adapter;
+
+import android.content.Context;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.compdfkit.core.annotation.CPDFAnnotation;
+import com.compdfkit.core.annotation.CPDFReplyAnnotation;
+import com.compdfkit.core.common.CPDFDate;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.annotation.pdfannotationlist.bean.CPDFAnnotListItem;
+import com.compdfkit.tools.annotation.pdfannotationlist.dialog.CMarkedTipsWindow;
+import com.compdfkit.tools.common.utils.adapter.CBaseQuickAdapter;
+import com.compdfkit.tools.common.utils.adapter.CBaseQuickViewHolder;
+import com.compdfkit.tools.common.utils.date.CDateUtil;
+import com.compdfkit.tools.common.utils.viewutils.CDimensUtils;
+import com.compdfkit.tools.common.utils.window.CPopupMenuWindow;
+
+import java.util.List;
+
+public class CPDFAnnotReplyListAdapter extends CBaseQuickAdapter<CPDFReplyAnnotation, CBaseQuickViewHolder> {
+
+  private static final String REFRESH_MARKED_STATUS = "refresh_marked_status";
+
+  public static final String REFRESH_REVIEW_STATUS = "refresh_review_status";
+
+  @Override
+  protected CBaseQuickViewHolder onCreateViewHolder(
+      Context context, ViewGroup parent, int viewType) {
+    return new CBaseQuickViewHolder(R.layout.tools_annot_reply_list_item_content, parent);
+  }
+
+  @Override
+  protected void onBindViewHolder(CBaseQuickViewHolder holder, int position, CPDFReplyAnnotation item) {
+    holder.setText(R.id.tv_author, item.getTitle());
+    String date = "";
+    if (item.getRecentlyModifyDate() != null){
+      date = CPDFDate.toStandardDate(item.getRecentlyModifyDate());
+    }
+    holder.setText(R.id.tv_annot_date, CDateUtil.transformPDFDate(date));
+    refreshMarkedStatus(holder, item.getMarkedAnnotState());
+    refreshReviewStatus(holder, item.getReviewAnnotState());
+    holder.setText(R.id.tv_annot_content, item.getContent());
+  }
+
+  @Override
+  public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads) {
+    if (payloads.isEmpty()){
+      super.onBindViewHolder(holder, position, payloads);
+    }else {
+      CPDFReplyAnnotation item = list.get(position);
+      for (Object payload : payloads) {
+        if(payload == REFRESH_REVIEW_STATUS){
+          refreshReviewStatus((CBaseQuickViewHolder) holder, item.getReviewAnnotState());
+        } else if(payload == REFRESH_MARKED_STATUS){
+          refreshMarkedStatus((CBaseQuickViewHolder) holder, item.getMarkedAnnotState());
+        }
+      }
+    }
+  }
+
+
+  private void refreshReviewStatus(CBaseQuickViewHolder adapter, CPDFAnnotation.ReviewState reviewState){
+    switch (reviewState){
+      case REVIEW_NONE:
+        adapter.setImageResource(R.id.iv_review_status, R.drawable.tools_annot_review_status_none);
+        break;
+      case REVIEW_ACCEPTED:
+        adapter.setImageResource(R.id.iv_review_status, R.drawable.tools_annot_review_status_accepted);
+
+        break;
+      case REVIEW_REJECTED:
+        adapter.setImageResource(R.id.iv_review_status, R.drawable.tools_annot_review_status_rejected);
+
+        break;
+      case REVIEW_COMPLETED:
+        adapter.setImageResource(R.id.iv_review_status, R.drawable.tools_annot_review_status_completed);
+
+        break;
+      case REVIEW_CANCELLED:
+        adapter.setImageResource(R.id.iv_review_status, R.drawable.tools_annot_review_status_cancelled);
+        break;
+      case REVIEW_ERROR:
+        adapter.setImageResource(R.id.iv_review_status, R.drawable.tools_annot_review_status_none);
+        break;
+      default:break;
+    }
+  }
+
+  private void refreshMarkedStatus(CBaseQuickViewHolder adapter, CPDFAnnotation.MarkState markState){
+    adapter.setChecked(R.id.cb_marked_status, markState == CPDFAnnotation.MarkState.MARKED);
+  }
+
+
+  public void setReviewStatus(int position, CPDFAnnotation.ReviewState reviewState){
+    CPDFReplyAnnotation replyAnnotation = list.get(position);
+    replyAnnotation.setReviewAnnotState(reviewState);
+    replyAnnotation.updateAp();
+    notifyItemChanged(position, REFRESH_REVIEW_STATUS);
+  }
+
+  public void checkedMarkedStatus(int position){
+    CPDFReplyAnnotation replyAnnotation = list.get(position);
+    if (replyAnnotation.getMarkedAnnotState() == CPDFAnnotation.MarkState.MARKED) {
+      replyAnnotation.setMarkedAnnotState(CPDFAnnotation.MarkState.UNMARKED);
+    }else {
+      replyAnnotation.setMarkedAnnotState(CPDFAnnotation.MarkState.MARKED);
+    }
+    replyAnnotation.updateAp();
+    notifyItemChanged(position, REFRESH_MARKED_STATUS);
+  }
+
+
+  /**
+   * Display the comment reply status menu
+   * @param position The subscript of the selected annotation in the list
+   * @param anchorView The position anchor view to be popped up, displayed above or below it
+   */
+  public void showReviewStatusMenu(Context context, int position, View anchorView){
+    anchorView.setSelected(true);
+    CPopupMenuWindow reviewStatusMenuWindow = new CPopupMenuWindow(context);
+    reviewStatusMenuWindow.setOutsideTouchable(false);
+    reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_accepted, R.string.tools_accepted, v -> {
+      setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_ACCEPTED);
+    });
+    reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_rejected, R.string.tools_rejected, v -> {
+      setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_REJECTED);
+    });
+    reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_cancelled, R.string.tools_cancelled, v -> {
+      setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_CANCELLED);
+    });
+    reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_completed, R.string.tools_completed, v -> {
+      setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_COMPLETED);
+    });
+    reviewStatusMenuWindow.addItem(R.drawable.tools_annot_review_status_none, R.string.tools_none, v -> {
+      setReviewStatus(position, CPDFAnnotation.ReviewState.REVIEW_NONE);
+    });
+    reviewStatusMenuWindow.setOnDismissListener(() -> anchorView.setSelected(false));
+    //Calculate the position of the pop-up.
+    // If there is enough space at the bottom,
+    // it will be displayed below the anchor view. If not, it will be displayed above it.
+    int[] windowPos = CDimensUtils.calculatePopWindowPos(anchorView, reviewStatusMenuWindow.getContentView());
+    windowPos[0] -= reviewStatusMenuWindow.getContentView().getMeasuredWidth() /2;
+    windowPos[1] -= anchorView.getMeasuredHeight() / 2;
+    windowPos[1] -= anchorView.getMeasuredHeight();
+    reviewStatusMenuWindow.setAnimationStyle(R.style.PopupAnimation);
+    reviewStatusMenuWindow.showAtLocation(anchorView, Gravity.START | Gravity.TOP, windowPos[0], windowPos[1]);
+  }
+
+  /**
+   * Show annotation markup status menu
+   * @param position The subscript of the selected annotation in the list
+   * @param anchorView The position anchor view to be popped up, displayed above or below it
+   */
+  public void showMarkedStatusMenu(Context context, int position, View anchorView){
+    checkedMarkedStatus(position);
+    CMarkedTipsWindow tipsWindow = new CMarkedTipsWindow(context);
+    tipsWindow.setMarkState(list.get(position).getMarkedAnnotState());
+    tipsWindow.getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+    int winWidth = tipsWindow.getContentView().getMeasuredWidth();
+    int winHeight = tipsWindow.getContentView().getMeasuredHeight();
+    int offsetX = (anchorView.getWidth() - winWidth) / 2;
+    int offsetY =  anchorView.getHeight() + winHeight;
+    tipsWindow.showAsDropDown(anchorView, offsetX, -offsetY);
+  }
+
+}

+ 0 - 20
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfannotationlist/bean/CPDFAnnotListItem.java

@@ -34,26 +34,6 @@ public class CPDFAnnotListItem {
 
     private CPDFAnnotation attr;
 
-    private CPDFAnnotation.ReviewState reviewState = CPDFAnnotation.ReviewState.REVIEW_NONE;
-
-    private CPDFAnnotation.MarkState markState = CPDFAnnotation.MarkState.UNMARKED;
-
-    public CPDFAnnotation.ReviewState getReviewState() {
-        return reviewState;
-    }
-
-    public void setReviewState(CPDFAnnotation.ReviewState reviewState) {
-        this.reviewState = reviewState;
-    }
-
-    public CPDFAnnotation.MarkState getMarkState() {
-        return markState;
-    }
-
-    public void setMarkState(CPDFAnnotation.MarkState markState) {
-        this.markState = markState;
-    }
-
     public CPDFAnnotation.Type getAnnotType() {
         return annotType;
     }

+ 6 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfannotationlist/data/CPDFAnnotDatas.java

@@ -212,7 +212,12 @@ public class CPDFAnnotDatas {
             List<CPDFAnnotation> annotations = page.getAnnotations();
             if (annotations != null) {
                 for (CPDFAnnotation annotation : annotations) {
-                    annotation.removeFromPageIncludeReplyAnnot();
+                    CPDFReplyAnnotation[] replyAnnotations = annotation.getAllReplyAnnotations();
+                    if (replyAnnotations != null && replyAnnotations.length >0){
+                        for (CPDFReplyAnnotation replyAnnotation : replyAnnotations) {
+                            replyAnnotation.removeFromPageIncludeReplyAnnot();
+                        }
+                    }
                 }
             }
         }

+ 111 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfannotationlist/dialog/CPDFEditReplyDialogFragment.java

@@ -0,0 +1,111 @@
+/**
+ * Copyright © 2014-2023 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.tools.annotation.pdfannotationlist.dialog;
+
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+
+import androidx.appcompat.widget.AppCompatButton;
+import androidx.appcompat.widget.AppCompatEditText;
+
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.basic.fragment.CBasicBottomSheetDialogFragment;
+import com.compdfkit.tools.common.utils.viewutils.CViewUtils;
+import com.compdfkit.tools.common.views.CToolBar;
+
+
+public class CPDFEditReplyDialogFragment extends CBasicBottomSheetDialogFragment {
+
+  public static final String EXTRA_TITLE = "extra_title_res_id";
+
+  public static final String EXTRA_CONTENT = "extra_content";
+
+  private CToolBar toolBar;
+
+  private AppCompatEditText editText;
+
+  private AppCompatButton btnDone;
+
+  private CEditReplyContentListener replyContentListener;
+
+  public static CPDFEditReplyDialogFragment addReply() {
+    Bundle args = new Bundle();
+    args.putInt(EXTRA_TITLE, R.string.tools_add_a_new_reply);
+    CPDFEditReplyDialogFragment fragment = new CPDFEditReplyDialogFragment();
+    fragment.setArguments(args);
+    return fragment;
+  }
+
+  public static CPDFEditReplyDialogFragment editReply(String replyContent) {
+    Bundle args = new Bundle();
+    args.putInt(EXTRA_TITLE, R.string.tools_edit_reply);
+    args.putString(EXTRA_CONTENT, replyContent);
+    CPDFEditReplyDialogFragment fragment = new CPDFEditReplyDialogFragment();
+    fragment.setArguments(args);
+    return fragment;
+  }
+
+  @Override
+  protected boolean fullScreen() {
+    return true;
+  }
+
+  @Override
+  protected float dimAmount() {
+    return CViewUtils.isLandScape(getContext()) ? 0.2F : 0F;
+  }
+
+  @Override
+  protected int layoutId() {
+    return R.layout.tools_annot_edit_reply_dialog_fragment;
+  }
+
+  @Override
+  protected void onCreateView(View rootView) {
+    toolBar = rootView.findViewById(R.id.tool_bar);
+    editText = rootView.findViewById(R.id.tv_reply_content);
+    btnDone = rootView.findViewById(R.id.btn_save);
+    toolBar.setBackBtnClickListener(v -> dismiss());
+    btnDone.setOnClickListener(v -> {
+      if (replyContentListener != null) {
+        String content = TextUtils.isEmpty(editText.getText()) ? "" : editText.getText().toString();
+        replyContentListener.reply(content);
+      }
+      dismiss();
+    });
+  }
+
+  @Override
+  protected void onViewCreate() {
+    if (getArguments() != null) {
+      int titleResId = getArguments().getInt(EXTRA_TITLE, -1);
+      if (titleResId != -1) {
+        toolBar.setTitle(titleResId);
+      } else {
+        toolBar.setTitle("");
+      }
+      String replyContent = getArguments().getString(EXTRA_CONTENT);
+      if (!TextUtils.isEmpty(replyContent)){
+        editText.setText(replyContent);
+        editText.setSelection(replyContent.length());
+      }
+      CViewUtils.showKeyboard(editText);
+    }
+  }
+
+  public void setReplyContentListener(CEditReplyContentListener replyContentListener) {
+    this.replyContentListener = replyContentListener;
+  }
+
+  public interface CEditReplyContentListener{
+    void reply(String content);
+  }
+}

+ 216 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfannotationlist/dialog/CPDFReplyDetailsDialogFragment.java

@@ -0,0 +1,216 @@
+/**
+ * Copyright © 2014-2024 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * <p>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.tools.annotation.pdfannotationlist.dialog;
+
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+
+import androidx.appcompat.widget.AppCompatTextView;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.compdfkit.core.annotation.CPDFReplyAnnotation;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.annotation.pdfannotationlist.adapter.CPDFAnnotListAdapter;
+import com.compdfkit.tools.annotation.pdfannotationlist.adapter.CPDFAnnotReplyListAdapter;
+import com.compdfkit.tools.annotation.pdfannotationlist.bean.CPDFAnnotListItem;
+import com.compdfkit.tools.common.basic.fragment.CBasicBottomSheetDialogFragment;
+import com.compdfkit.tools.common.utils.viewutils.CDimensUtils;
+import com.compdfkit.tools.common.utils.viewutils.CViewUtils;
+import com.compdfkit.tools.common.utils.window.CPopupMenuWindow;
+import com.compdfkit.tools.common.views.CToolBar;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class CPDFReplyDetailsDialogFragment extends CBasicBottomSheetDialogFragment {
+
+  private CToolBar toolBar;
+
+  private RecyclerView rvAnnot;
+
+  private RecyclerView rvReplyList;
+
+  private AppCompatTextView tvTotal;
+
+  private AppCompatTextView tvDeleteAnnotation;
+
+  private AppCompatTextView tvAddNewReply;
+
+  private CPDFAnnotListAdapter annotListAdapter;
+
+  private CPDFAnnotReplyListAdapter annotReplyListAdapter;
+
+  private CPDFAnnotListItem item;
+
+  private String annotAuthor;
+
+  private CUpdateAnnotationListListener updateAnnotationListListener;
+
+  @Override
+  protected float dimAmount() {
+    return CViewUtils.isLandScape(getContext()) ? 0.2F : 0F;
+  }
+
+  @Override
+  protected boolean draggable() {
+    return false;
+  }
+
+  public static CPDFReplyDetailsDialogFragment newInstance() {
+    Bundle args = new Bundle();
+    CPDFReplyDetailsDialogFragment fragment = new CPDFReplyDetailsDialogFragment();
+    fragment.setArguments(args);
+    return fragment;
+  }
+
+  public void setItem(CPDFAnnotListItem item) {
+    this.item = item;
+  }
+
+  public void setAnnotAuthor(String annotAuthor) {
+    this.annotAuthor = annotAuthor;
+  }
+
+  @Override
+  protected boolean fullScreen() {
+    return true;
+  }
+
+  @Override
+  protected int layoutId() {
+    return R.layout.tools_annot_reply_details_dialog_fragment;
+  }
+
+  @Override
+  protected void onCreateView(View rootView) {
+    toolBar = rootView.findViewById(R.id.tool_bar);
+    rvAnnot = rootView.findViewById(R.id.rv_annotation);
+    rvReplyList = rootView.findViewById(R.id.rv_reply);
+    tvTotal = rootView.findViewById(R.id.tv_total);
+    tvDeleteAnnotation = rootView.findViewById(R.id.tv_delete_annotation);
+    tvAddNewReply = rootView.findViewById(R.id.tv_add_reply);
+    toolBar.setBackBtnClickListener(v -> dismiss());
+    tvDeleteAnnotation.setOnClickListener(v -> {
+        boolean result = item.getAttr().removeFromPage();
+        if (result){
+          if (updateAnnotationListListener != null) {
+            updateAnnotationListListener.delete();
+          }
+          dismiss();
+        }
+    });
+    tvAddNewReply.setOnClickListener(v -> {
+      CPDFEditReplyDialogFragment addReplyDialog = CPDFEditReplyDialogFragment.addReply();
+      addReplyDialog.setReplyContentListener(content -> {
+        if (item != null) {
+          CPDFReplyAnnotation replyAnnotation = item.getAttr().createReplyAnnotation();
+          replyAnnotation.setContent(content);
+          replyAnnotation.setTitle(annotAuthor);
+        }
+        updateReplyList();
+      });
+      addReplyDialog.show(getChildFragmentManager(), "addReplyDialogFragment");
+    });
+  }
+
+  @Override
+  protected void onViewCreate() {
+    initAnnotItem();
+    initReplyList();
+  }
+
+  private void initAnnotItem(){
+    if (item != null) {
+      annotListAdapter = new CPDFAnnotListAdapter();
+      annotListAdapter.setShowMoreMenu(false);
+      annotListAdapter.setList(Arrays.asList(item));
+      rvAnnot.setLayoutManager(new LinearLayoutManager(getContext()));
+      rvAnnot.setAdapter(annotListAdapter);
+
+      annotListAdapter.addOnItemChildClickListener((adapter,view,position) -> {
+        if (view.getId() == R.id.iv_review_status){
+          annotListAdapter.showReviewStatusMenu(getContext(), position, view);
+        }else if(view.getId() == R.id.cb_marked_status){
+          annotListAdapter.showMarkedStatusMenu(getContext(), position, view);
+        }
+      }, R.id.iv_review_status, R.id.cb_marked_status);
+    }
+  }
+
+  private void initReplyList(){
+    if (item == null) {
+      return;
+    }
+    updateTotalCount();
+    CPDFReplyAnnotation[] replyAnnotations = item.getAttr().getAllReplyAnnotations();
+    annotReplyListAdapter = new CPDFAnnotReplyListAdapter();
+    annotReplyListAdapter.setList(new ArrayList<>(Arrays.asList(replyAnnotations)));
+    rvReplyList.setLayoutManager(new LinearLayoutManager(getContext()));
+    rvReplyList.setAdapter(annotReplyListAdapter);
+    annotReplyListAdapter.setOnItemClickListener((adapter,view,position) -> {});
+    annotReplyListAdapter.addOnItemChildClickListener((adapter,view,position) -> {
+      if (view.getId() == R.id.iv_review_status){
+        annotReplyListAdapter.showReviewStatusMenu(getContext(), position, view);
+      } else if(view.getId() == R.id.cb_marked_status){
+        annotReplyListAdapter.showMarkedStatusMenu(getContext(), position, view);
+      } else if (view.getId() == R.id.iv_more){
+        CPopupMenuWindow moreMenu = new CPopupMenuWindow(getContext());
+        moreMenu.addItem(R.string.tools_edit, v -> {
+          CPDFReplyAnnotation replyAnnotation = adapter.list.get(position);
+          CPDFEditReplyDialogFragment replyDialogFragment = CPDFEditReplyDialogFragment.editReply(replyAnnotation.getContent());
+          replyDialogFragment.setReplyContentListener(content -> {
+            replyAnnotation.setContent(content);
+            replyAnnotation.updateAp();
+            annotReplyListAdapter.notifyDataSetChanged();
+          });
+          replyDialogFragment.show(getChildFragmentManager(), "replyDialogFragment");
+        });
+        moreMenu.addItem(R.string.tools_delete,v -> {
+          CPDFReplyAnnotation replyAnnotation = adapter.list.get(position);
+          boolean result = replyAnnotation.removeFromPageIncludeReplyAnnot();
+          if (result){
+            annotReplyListAdapter.remove(position);
+            updateTotalCount();
+          }
+        });
+        //Calculate the position of the pop-up.
+        // If there is enough space at the bottom,
+        // it will be displayed below the anchor view. If not, it will be displayed above it.
+        int[] windowPos = CDimensUtils.calculatePopWindowPos(view, moreMenu.getContentView());
+        windowPos[0] -= view.getMeasuredWidth() /2;
+        windowPos[1] -= view.getMeasuredHeight();
+        moreMenu.setAnimationStyle(R.style.PopupAnimation);
+        moreMenu.showAtLocation(view, Gravity.START | Gravity.TOP, windowPos[0], windowPos[1]);
+      }
+    }, R.id.iv_review_status, R.id.cb_marked_status, R.id.iv_more);
+  }
+
+  private void updateReplyList(){
+    CPDFReplyAnnotation[] replyAnnotations = item.getAttr().getAllReplyAnnotations();
+    annotReplyListAdapter.setList(new ArrayList<>(Arrays.asList(replyAnnotations)));
+    updateTotalCount();
+  }
+
+  private void updateTotalCount(){
+    CPDFReplyAnnotation[] replyAnnotations = item.getAttr().getAllReplyAnnotations();
+    tvTotal.setVisibility(replyAnnotations.length >0 ? View.VISIBLE : View.INVISIBLE);
+    tvTotal.setText(getString(R.string.tools_total, replyAnnotations.length));
+  }
+
+  public void setUpdateAnnotationListListener(CUpdateAnnotationListListener updateAnnotationListListener) {
+    this.updateAnnotationListListener = updateAnnotationListListener;
+  }
+
+  public interface CUpdateAnnotationListListener{
+    void delete();
+  }
+
+}

+ 24 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/basic/fragment/CBasicBottomSheetDialogFragment.java

@@ -10,6 +10,7 @@
 package com.compdfkit.tools.common.basic.fragment;
 
 
+import android.content.DialogInterface;
 import android.content.res.Configuration;
 import android.os.Bundle;
 import android.view.LayoutInflater;
@@ -21,6 +22,7 @@ import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.interfaces.COnDialogDismissListener;
 import com.compdfkit.tools.common.utils.dialog.CDialogFragmentUtil;
 import com.compdfkit.tools.common.utils.viewutils.CViewUtils;
 import com.google.android.material.bottomsheet.BottomSheetBehavior;
@@ -28,6 +30,8 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
 
 public abstract class CBasicBottomSheetDialogFragment extends BottomSheetDialogFragment {
 
+    protected COnDialogDismissListener dismissListener;
+
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -93,4 +97,24 @@ public abstract class CBasicBottomSheetDialogFragment extends BottomSheetDialogF
         super.onConfigurationChanged(newConfig);
         CDialogFragmentUtil.setDimAmount(getDialog(), dimAmount());
     }
+
+    @Override
+    public void onCancel(@NonNull DialogInterface dialog) {
+        super.onCancel(dialog);
+        if (dismissListener != null) {
+            dismissListener.dismiss();
+        }
+    }
+
+    @Override
+    public void onDismiss(@NonNull DialogInterface dialog) {
+        super.onDismiss(dialog);
+        if (dismissListener != null){
+            dismissListener.dismiss();
+        }
+    }
+
+    public void setDismissListener(COnDialogDismissListener dismissListener) {
+        this.dismissListener = dismissListener;
+    }
 }

+ 1 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/pdf/CPDFDocumentFragment.java

@@ -267,7 +267,6 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
         Paint paint = new Paint();
         paint.setStyle(Paint.Style.FILL);
         paint.setColor(ContextCompat.getColor(getContext(), R.color.tools_color_accent_50));
-        pdfView.setSaveFileExtraFontSubset(cpdfConfiguration.globalConfig.fileSaveExtraFontSubset);
         pdfView.getCPdfReaderView().setFormPreviewPaint(paint);
         pdfView.addOnPDFFocusedTypeChangeListener(type -> {
             if (type != CPDFAnnotation.Type.INK) {
@@ -798,6 +797,7 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
 
     private void applyConfiguration() {
         CPDFApplyConfigUtil.getInstance().applyConfiguration(this, cpdfConfiguration);
+        pdfView.setCPDFConfiguration(cpdfConfiguration);
     }
 
     @Override

+ 4 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/adapter/CBaseQuickViewHolder.java

@@ -32,6 +32,10 @@ public class CBaseQuickViewHolder extends RecyclerView.ViewHolder {
         super(LayoutInflater.from(parent.getContext()).inflate(layoutResId, parent, false));
     }
 
+    public CBaseQuickViewHolder(View rootView){
+        super(rootView);
+    }
+
 
     public <T extends View> T getView(@IdRes int viewId) {
         if (views.get(viewId) != null) {

+ 11 - 5
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfview/CPDFViewCtrl.java

@@ -37,6 +37,7 @@ import com.compdfkit.core.document.CPDFDocument;
 import com.compdfkit.core.edit.CPDFEditManager;
 import com.compdfkit.tools.BuildConfig;
 import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.pdf.config.CPDFConfiguration;
 import com.compdfkit.tools.common.utils.CFileUtils;
 import com.compdfkit.tools.common.utils.CLog;
 import com.compdfkit.tools.common.utils.CToastUtil;
@@ -143,7 +144,7 @@ public class CPDFViewCtrl extends ConstraintLayout implements IReaderViewCallbac
 
     private List<OnFocusedTypeChangedListener> pdfViewFocusedListenerList = new ArrayList<>();
 
-    private boolean saveFileExtraFontSubset = false;
+    private CPDFConfiguration cpdfConfiguration;
 
     private Runnable hideIndicatorRunnable = () -> {
         if (pageIndicatorAnimator != null) {
@@ -390,6 +391,7 @@ public class CPDFViewCtrl extends ConstraintLayout implements IReaderViewCallbac
             exitEditMode();
             if (document.hasChanges()) {
                 try {
+                    boolean saveFileExtraFontSubset = cpdfConfiguration.globalConfig.fileSaveExtraFontSubset;
                     boolean success = document.save(CPDFDocument.PDFDocumentSaveType.PDFDocumentSaveIncremental, saveFileExtraFontSubset);
                     if (!success) {
                         document.save(CPDFDocument.PDFDocumentSaveType.PDFDocumentSaveNoIncremental, saveFileExtraFontSubset);
@@ -619,12 +621,16 @@ public class CPDFViewCtrl extends ConstraintLayout implements IReaderViewCallbac
         initCPDFSliderBar();
     }
 
-    public void setSaveFileExtraFontSubset(boolean saveFileExtraFontSubset) {
-        this.saveFileExtraFontSubset = saveFileExtraFontSubset;
+    public boolean isSaveFileExtraFontSubset() {
+        return cpdfConfiguration.globalConfig.fileSaveExtraFontSubset;
     }
 
-    public boolean isSaveFileExtraFontSubset() {
-        return saveFileExtraFontSubset;
+    public void setCPDFConfiguration(CPDFConfiguration cpdfConfiguration) {
+        this.cpdfConfiguration = cpdfConfiguration;
+    }
+
+    public CPDFConfiguration getCPDFConfiguration() {
+        return cpdfConfiguration;
     }
 
     public interface OnTapMainDocAreaCallback {

+ 48 - 0
ComPDFKit_Tools/src/main/res/layout/tools_annot_edit_reply_dialog_fragment.xml

@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <com.compdfkit.tools.common.views.CToolBar
+        android:id="@+id/tool_bar"
+        android:layout_width="match_parent"
+        android:layout_height="?android:attr/actionBarSize"
+        android:elevation="4dp"
+        android:title="@string/tools_add_a_new_reply"
+        android:textSize="18sp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <androidx.appcompat.widget.AppCompatButton
+            android:id="@+id/btn_save"
+            android:layout_width="wrap_content"
+            android:layout_height="32dp"
+            android:layout_gravity="end|center_vertical"
+            android:layout_marginEnd="16dp"
+            android:background="@drawable/tools_properties_signature_add_sign"
+            android:minWidth="70dp"
+            android:text="@string/tools_page_edit_toolbar_done"
+            android:textColor="?attr/colorAccent"
+            android:textSize="16sp" />
+
+    </com.compdfkit.tools.common.views.CToolBar>
+
+    <androidx.appcompat.widget.AppCompatEditText
+        android:id="@+id/tv_reply_content"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:background="?android:attr/colorBackground"
+        android:gravity="top|start"
+        android:hint="@string/tools_reply_or_add_thoughts"
+        android:padding="16dp"
+        android:textColor="?android:attr/textColorPrimary"
+        android:textSize="14sp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tool_bar" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 106 - 0
ComPDFKit_Tools/src/main/res/layout/tools_annot_reply_details_annot_content.xml

@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/cl_root"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="@drawable/tools_common_btn_rectangle_ripple"
+    android:paddingHorizontal="16dp"
+    android:paddingVertical="24dp">
+
+    <FrameLayout
+        android:id="@+id/fl_annot_icon"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        app:layout_constraintBottom_toBottomOf="@id/tv_annot_date"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="@id/tv_author">
+
+        <View
+            android:id="@+id/view_icon_bg"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@color/tools_color_background" />
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_annot_icon"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            app:srcCompat="@drawable/tools_ic_annotation_highlight_normal" />
+
+    </FrameLayout>
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_author"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="8dp"
+        android:ellipsize="end"
+        android:maxLines="1"
+        android:textColor="?android:attr/textColorPrimary"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintBottom_toTopOf="@id/tv_annot_date"
+        app:layout_constraintEnd_toStartOf="@id/iv_review_status"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toEndOf="@id/fl_annot_icon"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="@tools:sample/full_names" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_annot_date"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textColor="?android:attr/textColorSecondary"
+        android:textSize="11sp"
+        app:layout_constraintBottom_toBottomOf="@id/fl_annot_icon"
+        app:layout_constraintStart_toStartOf="@id/tv_author"
+        app:layout_constraintTop_toBottomOf="@id/tv_author"
+        tools:text="@tools:sample/date/ddmmyy" />
+
+    <CheckBox
+        android:id="@+id/cb_marked_status"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:layout_marginEnd="8dp"
+        android:button="@drawable/tools_annot_replies_checkbox_btn"
+        android:buttonTint="?attr/colorOnPrimary"
+        app:layout_constraintBottom_toBottomOf="@id/iv_more"
+        app:layout_constraintEnd_toEndOf="parent"
+        tools:checked="false" />
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_review_status"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:layout_marginEnd="8dp"
+        android:background="@drawable/tools_common_btn_corner_ripple"
+        app:layout_constraintBottom_toBottomOf="@id/iv_more"
+        app:layout_constraintEnd_toStartOf="@id/cb_marked_status"
+        app:srcCompat="@drawable/tools_annot_review_status_none"
+        app:tint="@color/tools_icon_status_color" />
+
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_annot_content"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="4dp"
+        android:ellipsize="end"
+        android:maxLines="3"
+        android:textColor="?android:attr/textColorSecondary"
+        android:textSize="14sp"
+        android:visibility="visible"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tv_annot_date"
+        tools:text="@tools:sample/lorem/random" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>
+
+
+

+ 114 - 0
ComPDFKit_Tools/src/main/res/layout/tools_annot_reply_details_dialog_fragment.xml

@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+
+    <com.compdfkit.tools.common.views.CToolBar
+        android:id="@+id/tool_bar"
+        android:layout_width="match_parent"
+        android:layout_height="?android:attr/actionBarSize"
+        android:elevation="4dp"
+        android:textSize="18sp"
+        android:title="@string/tools_replies_of_annotation"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+
+    </com.compdfkit.tools.common.views.CToolBar>
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/rv_annotation"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:layout_constraintTop_toBottomOf="@id/tool_bar"
+        tools:itemCount="1"
+        android:paddingVertical="8dp"
+        tools:listitem="@layout/tools_bota_annotation_list_item_content" />
+
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:orientation="vertical"
+        app:layout_constraintBottom_toTopOf="@id/cl_menu"
+        app:layout_constraintTop_toBottomOf="@id/rv_annotation">
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="18dp"
+            android:background="?attr/compdfkit_HeadItem_BackgroundColor" />
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:id="@+id/tv_total"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:paddingHorizontal="16dp"
+            android:layout_marginBottom="8dp"
+            android:text="@string/tools_total"
+            android:textColor="?android:attr/textColorPrimary"
+            android:textStyle="bold"
+            android:visibility="invisible"
+            tools:text="Total:23"
+            tools:visibility="visible" />
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/rv_reply"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            tools:listitem="@layout/tools_annot_reply_list_item_content" />
+
+    </LinearLayout>
+
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        android:id="@+id/cl_menu"
+        android:layout_width="match_parent"
+        android:elevation="2dp"
+        android:layout_height="56dp"
+        android:layout_gravity="bottom"
+        android:background="?attr/colorPrimary">
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:id="@+id/tv_delete_annotation"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@drawable/tools_signature_toolbar_btn_corner_status_bg"
+            android:foreground="@drawable/tools_common_btn_corner_ripple_in_widget"
+            android:padding="8dp"
+            android:text="@string/tools_delete_annotation"
+            android:textColor="?android:attr/textColorPrimary"
+            android:textSize="16dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/tv_add_reply"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:id="@+id/tv_add_reply"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@drawable/tools_signature_toolbar_btn_corner_status_bg"
+            android:foreground="@drawable/tools_common_btn_corner_ripple_in_widget"
+            android:padding="8dp"
+            android:text="@string/tools_add_new_reply"
+            android:textColor="?android:attr/textColorPrimary"
+            android:textSize="16dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toEndOf="@id/tv_delete_annotation"
+            app:layout_constraintTop_toTopOf="parent" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
+
+

+ 119 - 0
ComPDFKit_Tools/src/main/res/layout/tools_annot_reply_list_item_content.xml

@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/cl_root"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:foreground="@drawable/tools_common_btn_rectangle_ripple"
+    android:paddingHorizontal="16dp"
+    android:paddingVertical="12dp">
+
+    <FrameLayout
+        android:id="@+id/fl_annot_icon"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:visibility="invisible"
+        app:layout_constraintBottom_toBottomOf="@id/tv_annot_date"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="@id/tv_author">
+
+        <View
+            android:id="@+id/view_icon_bg"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@color/tools_color_background" />
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_annot_icon"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            app:srcCompat="@drawable/tools_ic_annotation_highlight_normal" />
+
+    </FrameLayout>
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_author"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textStyle="bold"
+        android:layout_marginStart="8dp"
+        android:textColor="?android:attr/textColorPrimary"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintBottom_toTopOf="@id/tv_annot_date"
+        app:layout_constraintEnd_toStartOf="@id/iv_review_status"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toEndOf="@id/fl_annot_icon"
+        app:layout_constraintTop_toTopOf="parent"
+        android:maxLines="1"
+        android:ellipsize="end"
+        tools:text="@tools:sample/full_names" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_annot_date"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textColor="?android:attr/textColorSecondary"
+        android:textSize="11sp"
+        app:layout_constraintBottom_toBottomOf="@id/fl_annot_icon"
+        app:layout_constraintStart_toStartOf="@id/tv_author"
+        app:layout_constraintTop_toBottomOf="@id/tv_author"
+        tools:text="@tools:sample/date/ddmmyy" />
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_more"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        app:tint="?attr/colorOnPrimary"
+        android:background="@drawable/tools_common_btn_corner_ripple"
+        app:layout_constraintBottom_toBottomOf="@id/fl_annot_icon"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="@id/fl_annot_icon"
+        app:srcCompat="@drawable/tools_ic_more_vertical" />
+
+    <CheckBox
+        android:id="@+id/cb_marked_status"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:layout_marginEnd="8dp"
+        android:buttonTint="?attr/colorOnPrimary"
+        android:button="@drawable/tools_annot_replies_checkbox_btn"
+        app:layout_constraintBottom_toBottomOf="@id/iv_more"
+        app:layout_constraintEnd_toStartOf="@id/iv_more"
+        tools:checked="false" />
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_review_status"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:layout_marginEnd="8dp"
+        app:tint="@color/tools_icon_status_color"
+        android:background="@drawable/tools_common_btn_corner_ripple"
+        app:layout_constraintBottom_toBottomOf="@id/iv_more"
+        app:layout_constraintEnd_toStartOf="@id/cb_marked_status"
+        app:srcCompat="@drawable/tools_annot_review_status_none" />
+
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_annot_content"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="4dp"
+        android:ellipsize="end"
+        android:maxLines="3"
+        android:textColor="?android:attr/textColorSecondary"
+        android:textSize="14sp"
+        android:visibility="visible"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toStartOf="@id/tv_author"
+        app:layout_constraintTop_toBottomOf="@id/tv_annot_date"
+        tools:text="@tools:sample/lorem/random" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>
+
+
+

+ 8 - 4
ComPDFKit_Tools/src/main/res/layout/tools_bota_annotation_list_item_content.xml

@@ -35,6 +35,7 @@
         android:id="@+id/tv_author"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:textStyle="bold"
         android:layout_marginStart="8dp"
         android:textColor="?android:attr/textColorPrimary"
         app:layout_constrainedWidth="true"
@@ -63,9 +64,10 @@
         android:layout_width="24dp"
         android:layout_height="24dp"
         app:tint="?attr/colorOnPrimary"
+        android:visibility="gone"
         android:background="@drawable/tools_common_btn_corner_ripple"
-        app:layout_constraintBottom_toBottomOf="@id/fl_annot_icon"
         app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintBottom_toBottomOf="@id/fl_annot_icon"
         app:layout_constraintTop_toTopOf="@id/fl_annot_icon"
         app:srcCompat="@drawable/tools_ic_more_vertical" />
 
@@ -76,7 +78,8 @@
         android:layout_marginEnd="8dp"
         android:buttonTint="?attr/colorOnPrimary"
         android:button="@drawable/tools_annot_replies_checkbox_btn"
-        app:layout_constraintBottom_toBottomOf="@id/iv_more"
+        app:layout_constraintBottom_toBottomOf="@id/fl_annot_icon"
+        app:layout_constraintTop_toTopOf="@id/fl_annot_icon"
         app:layout_constraintEnd_toStartOf="@id/iv_more"
         tools:checked="false" />
 
@@ -87,7 +90,8 @@
         android:layout_marginEnd="8dp"
         app:tint="@color/tools_icon_status_color"
         android:background="@drawable/tools_common_btn_corner_ripple"
-        app:layout_constraintBottom_toBottomOf="@id/iv_more"
+        app:layout_constraintBottom_toBottomOf="@id/fl_annot_icon"
+        app:layout_constraintTop_toTopOf="@id/fl_annot_icon"
         app:layout_constraintEnd_toStartOf="@id/cb_marked_status"
         app:srcCompat="@drawable/tools_annot_review_status_none" />
 
@@ -98,7 +102,7 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="4dp"
         android:ellipsize="end"
-        android:maxLines="2"
+        android:maxLines="3"
         android:textColor="?android:attr/textColorSecondary"
         android:textSize="14sp"
         android:visibility="visible"

+ 14 - 7
ComPDFKit_Tools/src/main/res/values/tools_strings.xml

@@ -499,19 +499,26 @@
 <!--    v2.1.0-->
     <string name="tools_import_annotations">Import Annotations</string>
     <string name="tools_export_annotations">Export Annotations</string>
-    <string name="tools_delete_all_annotations">Delete All Annotations</string>
-    <string name="tools_delete_all_replies">Delete All Replies</string>
+    <string name="tools_delete_all_annotations">Delete all annotations</string>
+    <string name="tools_delete_all_replies">Delete all replies</string>
     <string name="tools_import_success">Import successful</string>
     <string name="tools_please_select_xfdf_format_file">Please select xfdf format file</string>
-    
+
+    <string name="tools_marked">Marked</string>
+    <string name="tools_unmarked">UnMarked</string>
     <string name="tools_accepted">Accepted</string>
     <string name="tools_rejected">Rejected</string>
     <string name="tools_cancelled">Cancelled</string>
     <string name="tools_completed">Completed</string>
 
-    <string name="tools_marked">Marked</string>
-    <string name="tools_unmarked">UnMarked</string>
     <string name="tools_add_a_new_reply">Add a new Reply</string>
-    <string name="tools_view_replies">View Replies</string>
-    <string name="tools_delete_annotation">Delete Annotation</string>
+    <string name="tools_add_new_reply">Add New Reply</string>
+    <string name="tools_edit_reply">Edit Reply</string>
+    <string name="tools_view_replies">View replies</string>
+    <string name="tools_delete_annotation">Delete annotation</string>
+    <string name="tools_reply_or_add_thoughts">Reply or add thoughts</string>
+    <string name="tools_replies_of_annotation">Replies of Annotation</string>
+    <string name="tools_total">Total: %d</string>
+
+
 </resources>