@amafil/react-native-pdf-toolkit 1.0.11 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/org/wonday/pdf/PdfManager.java +32 -0
- package/android/src/main/java/org/wonday/pdf/PdfView.java +1161 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNPDFPdfViewManagerDelegate.java +18 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNPDFPdfViewManagerInterface.java +6 -0
- package/fabric/RNPDFPdfNativeComponent.js +9 -1
- package/index.d.ts +68 -1
- package/index.js +89 -0
- package/index.js.flow +68 -0
- package/ios/RNPDFPdf/RNPDFPdfView.h +7 -0
- package/ios/RNPDFPdf/RNPDFPdfView.mm +1196 -0
- package/ios/RNPDFPdf/RNPDFPdfViewManager.mm +9 -16
- package/package.json +1 -1
package/android/src/paper/java/com/facebook/react/viewmanagers/RNPDFPdfViewManagerDelegate.java
CHANGED
|
@@ -62,6 +62,21 @@ public class RNPDFPdfViewManagerDelegate<T extends View, U extends BaseViewManag
|
|
|
62
62
|
case "enableDoubleTapZoom":
|
|
63
63
|
mViewManager.setEnableDoubleTapZoom(view, value == null ? false : (boolean) value);
|
|
64
64
|
break;
|
|
65
|
+
case "annotations":
|
|
66
|
+
mViewManager.setAnnotations(view, value == null ? null : (String) value);
|
|
67
|
+
break;
|
|
68
|
+
case "annotationMode":
|
|
69
|
+
mViewManager.setAnnotationMode(view, value == null ? false : (boolean) value);
|
|
70
|
+
break;
|
|
71
|
+
case "annotationTool":
|
|
72
|
+
mViewManager.setAnnotationTool(view, value == null ? null : (String) value);
|
|
73
|
+
break;
|
|
74
|
+
case "annotationEditable":
|
|
75
|
+
mViewManager.setAnnotationEditable(view, value == null ? false : (boolean) value);
|
|
76
|
+
break;
|
|
77
|
+
case "annotationIdMode":
|
|
78
|
+
mViewManager.setAnnotationIdMode(view, value == null ? null : (String) value);
|
|
79
|
+
break;
|
|
65
80
|
case "enableAntialiasing":
|
|
66
81
|
mViewManager.setEnableAntialiasing(view, value == null ? false : (boolean) value);
|
|
67
82
|
break;
|
|
@@ -87,6 +102,9 @@ public class RNPDFPdfViewManagerDelegate<T extends View, U extends BaseViewManag
|
|
|
87
102
|
case "setNativePage":
|
|
88
103
|
mViewManager.setNativePage(view, args.getInt(0));
|
|
89
104
|
break;
|
|
105
|
+
case "saveAnnotations":
|
|
106
|
+
mViewManager.saveAnnotations(view);
|
|
107
|
+
break;
|
|
90
108
|
}
|
|
91
109
|
}
|
|
92
110
|
}
|
package/android/src/paper/java/com/facebook/react/viewmanagers/RNPDFPdfViewManagerInterface.java
CHANGED
|
@@ -26,10 +26,16 @@ public interface RNPDFPdfViewManagerInterface<T extends View> {
|
|
|
26
26
|
void setEnableRTL(T view, boolean value);
|
|
27
27
|
void setEnableAnnotationRendering(T view, boolean value);
|
|
28
28
|
void setEnableDoubleTapZoom(T view, boolean value);
|
|
29
|
+
void setAnnotations(T view, @Nullable String value);
|
|
30
|
+
void setAnnotationMode(T view, boolean value);
|
|
31
|
+
void setAnnotationTool(T view, @Nullable String value);
|
|
32
|
+
void setAnnotationEditable(T view, boolean value);
|
|
33
|
+
void setAnnotationIdMode(T view, @Nullable String value);
|
|
29
34
|
void setEnableAntialiasing(T view, boolean value);
|
|
30
35
|
void setFitPolicy(T view, int value);
|
|
31
36
|
void setSpacing(T view, int value);
|
|
32
37
|
void setPassword(T view, @Nullable String value);
|
|
33
38
|
void setSinglePage(T view, boolean value);
|
|
34
39
|
void setNativePage(T view, int page);
|
|
40
|
+
void saveAnnotations(T view);
|
|
35
41
|
}
|
|
@@ -30,6 +30,11 @@
|
|
|
30
30
|
fitPolicy: ?Int32,
|
|
31
31
|
spacing: ?Int32,
|
|
32
32
|
password: ?string,
|
|
33
|
+
annotations: ?string,
|
|
34
|
+
annotationMode: ?boolean,
|
|
35
|
+
annotationTool: ?string,
|
|
36
|
+
annotationEditable: ?boolean,
|
|
37
|
+
annotationIdMode: ?string,
|
|
33
38
|
onChange: ?BubblingEventHandler<ChangeEvent>,
|
|
34
39
|
singlePage: ?boolean,
|
|
35
40
|
|}>;
|
|
@@ -47,10 +52,13 @@
|
|
|
47
52
|
+stopNativeAutoScroll: (
|
|
48
53
|
viewRef: React.ElementRef<ComponentType>,
|
|
49
54
|
) => void;
|
|
55
|
+
+saveAnnotations: (
|
|
56
|
+
viewRef: React.ElementRef<ComponentType>,
|
|
57
|
+
) => void;
|
|
50
58
|
}
|
|
51
59
|
|
|
52
60
|
export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
|
|
53
|
-
supportedCommands: ['setNativePage', 'startNativeAutoScroll', 'stopNativeAutoScroll'],
|
|
61
|
+
supportedCommands: ['setNativePage', 'startNativeAutoScroll', 'stopNativeAutoScroll', 'saveAnnotations'],
|
|
54
62
|
});
|
|
55
63
|
|
|
56
64
|
export default codegenNativeComponent<NativeProps>('RNPDFPdfView');
|
package/index.d.ts
CHANGED
|
@@ -27,6 +27,68 @@ export type Source = {
|
|
|
27
27
|
method?: string;
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
+
export type AnnotationRotation = 0 | 90 | 180 | 270;
|
|
31
|
+
export type AnnotationIdMode = 'auto' | 'manual';
|
|
32
|
+
export type AnnotationTool = 'select' | 'ink' | 'text' | 'highlight' | 'underline' | 'strikeout';
|
|
33
|
+
export type AnnotationTextAlign = 'left' | 'center' | 'right';
|
|
34
|
+
|
|
35
|
+
export type AnnotationPoint = {
|
|
36
|
+
x: number,
|
|
37
|
+
y: number,
|
|
38
|
+
pressure?: number,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export type AnnotationBounds = {
|
|
42
|
+
x: number,
|
|
43
|
+
y: number,
|
|
44
|
+
width: number,
|
|
45
|
+
height: number,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export type AnnotationStyle = {
|
|
49
|
+
color?: string,
|
|
50
|
+
thickness?: number,
|
|
51
|
+
fontFamily?: string,
|
|
52
|
+
fontSize?: number,
|
|
53
|
+
textAlign?: AnnotationTextAlign,
|
|
54
|
+
rotation?: AnnotationRotation,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export type AnnotationBase = {
|
|
58
|
+
id: string,
|
|
59
|
+
page: number,
|
|
60
|
+
locked?: boolean,
|
|
61
|
+
createdAt?: number,
|
|
62
|
+
updatedAt?: number,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export type InkAnnotation = AnnotationBase & {
|
|
66
|
+
type: 'ink',
|
|
67
|
+
points: AnnotationPoint[],
|
|
68
|
+
style?: AnnotationStyle,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export type TextAnnotation = AnnotationBase & {
|
|
72
|
+
type: 'text',
|
|
73
|
+
bounds: AnnotationBounds,
|
|
74
|
+
text: string,
|
|
75
|
+
style?: AnnotationStyle,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export type MarkupAnnotation = AnnotationBase & {
|
|
79
|
+
type: 'highlight' | 'underline' | 'strikeout',
|
|
80
|
+
bounds: AnnotationBounds,
|
|
81
|
+
style?: AnnotationStyle,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export type Annotation = InkAnnotation | TextAnnotation | MarkupAnnotation;
|
|
85
|
+
|
|
86
|
+
export type AnnotationDocument = {
|
|
87
|
+
editable?: boolean,
|
|
88
|
+
idMode?: AnnotationIdMode,
|
|
89
|
+
annotations: Annotation[],
|
|
90
|
+
};
|
|
91
|
+
|
|
30
92
|
export type TextSelectionChangeEvent = {
|
|
31
93
|
nativeEvent:
|
|
32
94
|
| {
|
|
@@ -58,6 +120,11 @@ export interface PdfProps {
|
|
|
58
120
|
enableRTL?: boolean,
|
|
59
121
|
enableAnnotationRendering?: boolean,
|
|
60
122
|
enableDoubleTapZoom?: boolean;
|
|
123
|
+
annotations?: AnnotationDocument,
|
|
124
|
+
annotationMode?: boolean,
|
|
125
|
+
annotationTool?: AnnotationTool,
|
|
126
|
+
annotationEditable?: boolean,
|
|
127
|
+
annotationIdMode?: AnnotationIdMode,
|
|
61
128
|
/**
|
|
62
129
|
* Only works on iOS. Defaults to `true`.
|
|
63
130
|
*/
|
|
@@ -80,11 +147,11 @@ export interface PdfProps {
|
|
|
80
147
|
onPressLink?: (url: string) => void,
|
|
81
148
|
onAutoScrollEnd?: () => void,
|
|
82
149
|
onTextSelectionChange?: (event: TextSelectionChangeEvent) => void,
|
|
83
|
-
onAutoScrollEnd?: () => void,
|
|
84
150
|
}
|
|
85
151
|
|
|
86
152
|
export interface PdfRef {
|
|
87
153
|
setPage(pageNumber: number): void
|
|
154
|
+
saveAnnotations(): Promise<AnnotationDocument>
|
|
88
155
|
/**
|
|
89
156
|
* Start smooth automatic vertical scrolling using the display refresh rate.
|
|
90
157
|
* @param dpPerSecond - Scroll speed in density-independent pixels (dp) per second (default: 15). Produces consistent physical speed across screen densities.
|
package/index.js
CHANGED
|
@@ -57,6 +57,11 @@ export default class Pdf extends Component {
|
|
|
57
57
|
fitPolicy: PropTypes.number,
|
|
58
58
|
trustAllCerts: PropTypes.bool,
|
|
59
59
|
singlePage: PropTypes.bool,
|
|
60
|
+
annotations: PropTypes.object,
|
|
61
|
+
annotationMode: PropTypes.bool,
|
|
62
|
+
annotationTool: PropTypes.oneOf(['select', 'ink', 'text', 'highlight', 'underline', 'strikeout']),
|
|
63
|
+
annotationEditable: PropTypes.bool,
|
|
64
|
+
annotationIdMode: PropTypes.oneOf(['auto', 'manual']),
|
|
60
65
|
onLoadComplete: PropTypes.func,
|
|
61
66
|
onPageChanged: PropTypes.func,
|
|
62
67
|
onError: PropTypes.func,
|
|
@@ -96,6 +101,11 @@ export default class Pdf extends Component {
|
|
|
96
101
|
trustAllCerts: true,
|
|
97
102
|
usePDFKit: true,
|
|
98
103
|
singlePage: false,
|
|
104
|
+
annotations: null,
|
|
105
|
+
annotationMode: false,
|
|
106
|
+
annotationTool: 'select',
|
|
107
|
+
annotationEditable: true,
|
|
108
|
+
annotationIdMode: 'auto',
|
|
99
109
|
onLoadProgress: (percent) => {
|
|
100
110
|
},
|
|
101
111
|
onLoadComplete: (numberOfPages, path) => {
|
|
@@ -127,6 +137,7 @@ export default class Pdf extends Component {
|
|
|
127
137
|
};
|
|
128
138
|
|
|
129
139
|
this.lastRNBFTask = null;
|
|
140
|
+
this._annotationSavePromise = null;
|
|
130
141
|
|
|
131
142
|
}
|
|
132
143
|
|
|
@@ -156,6 +167,10 @@ export default class Pdf extends Component {
|
|
|
156
167
|
componentWillUnmount() {
|
|
157
168
|
this._mounted = false;
|
|
158
169
|
this.stopAutoScroll();
|
|
170
|
+
if (this._annotationSavePromise) {
|
|
171
|
+
this._annotationSavePromise.reject(new Error('Pdf unmounted before annotation save completed'));
|
|
172
|
+
this._annotationSavePromise = null;
|
|
173
|
+
}
|
|
159
174
|
if (this.lastRNBFTask) {
|
|
160
175
|
// this.lastRNBFTask.cancel(err => {
|
|
161
176
|
// });
|
|
@@ -372,6 +387,42 @@ export default class Pdf extends Component {
|
|
|
372
387
|
|
|
373
388
|
}
|
|
374
389
|
|
|
390
|
+
saveAnnotations() {
|
|
391
|
+
if (this._annotationSavePromise) {
|
|
392
|
+
return Promise.reject(new Error('An annotation save is already in progress'));
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return new Promise((resolve, reject) => {
|
|
396
|
+
if (!this._root) {
|
|
397
|
+
reject(new Error('Pdf is not mounted'));
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
this._annotationSavePromise = {resolve, reject};
|
|
402
|
+
|
|
403
|
+
if (!!global?.nativeFabricUIManager) {
|
|
404
|
+
if (PdfViewCommands.saveAnnotations) {
|
|
405
|
+
PdfViewCommands.saveAnnotations(this._root);
|
|
406
|
+
} else {
|
|
407
|
+
this._annotationSavePromise = null;
|
|
408
|
+
reject(new Error('Annotation save command is not available'));
|
|
409
|
+
}
|
|
410
|
+
} else {
|
|
411
|
+
const ReactNative = require('react-native');
|
|
412
|
+
try {
|
|
413
|
+
ReactNative.UIManager.dispatchViewManagerCommand(
|
|
414
|
+
ReactNative.findNodeHandle(this._root),
|
|
415
|
+
'saveAnnotations',
|
|
416
|
+
[],
|
|
417
|
+
);
|
|
418
|
+
} catch (error) {
|
|
419
|
+
this._annotationSavePromise = null;
|
|
420
|
+
reject(error);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
|
|
375
426
|
startAutoScroll( dpPerSecond = 15, resumeDelay = 3000 ) {
|
|
376
427
|
this._isAutoScrollActive = true;
|
|
377
428
|
if (!!global?.nativeFabricUIManager) {
|
|
@@ -465,6 +516,27 @@ export default class Pdf extends Component {
|
|
|
465
516
|
} else if (message[0] === 'autoScrollEnd') {
|
|
466
517
|
this._isAutoScrollActive = false;
|
|
467
518
|
this.props.onAutoScrollEnd && this.props.onAutoScrollEnd();
|
|
519
|
+
} else if (message[0] === 'annotationSaveComplete') {
|
|
520
|
+
message[1] = message.slice(1).join('|');
|
|
521
|
+
|
|
522
|
+
let annotationDocument;
|
|
523
|
+
try {
|
|
524
|
+
annotationDocument = message[1] ? JSON.parse(message[1]) : null;
|
|
525
|
+
} catch (e) {
|
|
526
|
+
annotationDocument = message[1];
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (this._annotationSavePromise) {
|
|
530
|
+
this._annotationSavePromise.resolve(annotationDocument);
|
|
531
|
+
this._annotationSavePromise = null;
|
|
532
|
+
}
|
|
533
|
+
} else if (message[0] === 'annotationSaveError') {
|
|
534
|
+
message[1] = message.slice(1).join('|');
|
|
535
|
+
|
|
536
|
+
if (this._annotationSavePromise) {
|
|
537
|
+
this._annotationSavePromise.reject(new Error(message[1] || 'Annotation save failed'));
|
|
538
|
+
this._annotationSavePromise = null;
|
|
539
|
+
}
|
|
468
540
|
}
|
|
469
541
|
}
|
|
470
542
|
|
|
@@ -476,7 +548,22 @@ export default class Pdf extends Component {
|
|
|
476
548
|
|
|
477
549
|
};
|
|
478
550
|
|
|
551
|
+
_getNativeAnnotations = () => {
|
|
552
|
+
if (!this.props.annotations) {
|
|
553
|
+
return null;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
try {
|
|
557
|
+
return JSON.stringify(this.props.annotations);
|
|
558
|
+
} catch (error) {
|
|
559
|
+
this._onError(error);
|
|
560
|
+
return null;
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
|
|
479
564
|
render() {
|
|
565
|
+
const nativeAnnotations = this._getNativeAnnotations();
|
|
566
|
+
|
|
480
567
|
if (Platform.OS === "android" || Platform.OS === "ios" || Platform.OS === "windows") {
|
|
481
568
|
return (
|
|
482
569
|
<View style={[this.props.style,{overflow: 'hidden'}]}>
|
|
@@ -492,6 +579,7 @@ export default class Pdf extends Component {
|
|
|
492
579
|
<PdfCustom
|
|
493
580
|
ref={component => (this._root = component)}
|
|
494
581
|
{...this.props}
|
|
582
|
+
annotations={nativeAnnotations}
|
|
495
583
|
style={[{flex:1,backgroundColor: '#EEE'}, this.props.style]}
|
|
496
584
|
path={this.state.path}
|
|
497
585
|
onChange={this._onChange}
|
|
@@ -501,6 +589,7 @@ export default class Pdf extends Component {
|
|
|
501
589
|
<PdfCustom
|
|
502
590
|
ref={component => (this._root = component)}
|
|
503
591
|
{...this.props}
|
|
592
|
+
annotations={nativeAnnotations}
|
|
504
593
|
style={[{backgroundColor: '#EEE',overflow: 'hidden'}, this.props.style]}
|
|
505
594
|
path={this.state.path}
|
|
506
595
|
onChange={this._onChange}
|
package/index.js.flow
CHANGED
|
@@ -24,6 +24,68 @@ export type Source = {
|
|
|
24
24
|
uri: string
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
+
export type AnnotationRotation = 0 | 90 | 180 | 270;
|
|
28
|
+
export type AnnotationIdMode = 'auto' | 'manual';
|
|
29
|
+
export type AnnotationTool = 'select' | 'ink' | 'text' | 'highlight' | 'underline' | 'strikeout';
|
|
30
|
+
export type AnnotationTextAlign = 'left' | 'center' | 'right';
|
|
31
|
+
|
|
32
|
+
export type AnnotationPoint = {
|
|
33
|
+
x: number,
|
|
34
|
+
y: number,
|
|
35
|
+
pressure?: number,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export type AnnotationBounds = {
|
|
39
|
+
x: number,
|
|
40
|
+
y: number,
|
|
41
|
+
width: number,
|
|
42
|
+
height: number,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type AnnotationStyle = {
|
|
46
|
+
color?: string,
|
|
47
|
+
thickness?: number,
|
|
48
|
+
fontFamily?: string,
|
|
49
|
+
fontSize?: number,
|
|
50
|
+
textAlign?: AnnotationTextAlign,
|
|
51
|
+
rotation?: AnnotationRotation,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type AnnotationBase = {
|
|
55
|
+
id: string,
|
|
56
|
+
page: number,
|
|
57
|
+
locked?: boolean,
|
|
58
|
+
createdAt?: number,
|
|
59
|
+
updatedAt?: number,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export type InkAnnotation = AnnotationBase & {
|
|
63
|
+
type: 'ink',
|
|
64
|
+
points: Array<AnnotationPoint>,
|
|
65
|
+
style?: AnnotationStyle,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export type TextAnnotation = AnnotationBase & {
|
|
69
|
+
type: 'text',
|
|
70
|
+
bounds: AnnotationBounds,
|
|
71
|
+
text: string,
|
|
72
|
+
style?: AnnotationStyle,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export type MarkupAnnotation = AnnotationBase & {
|
|
76
|
+
type: 'highlight' | 'underline' | 'strikeout',
|
|
77
|
+
bounds: AnnotationBounds,
|
|
78
|
+
style?: AnnotationStyle,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export type Annotation = InkAnnotation | TextAnnotation | MarkupAnnotation;
|
|
82
|
+
|
|
83
|
+
export type AnnotationDocument = {
|
|
84
|
+
editable?: boolean,
|
|
85
|
+
idMode?: AnnotationIdMode,
|
|
86
|
+
annotations: Array<Annotation>,
|
|
87
|
+
};
|
|
88
|
+
|
|
27
89
|
export type TableContent = {
|
|
28
90
|
children: TableContent[],
|
|
29
91
|
mNativePtr: number,
|
|
@@ -33,6 +95,11 @@ export type TableContent = {
|
|
|
33
95
|
|
|
34
96
|
export type Props = {
|
|
35
97
|
renderActivityIndicator?: (progress: number) => Node,
|
|
98
|
+
annotations?: AnnotationDocument,
|
|
99
|
+
annotationMode?: boolean,
|
|
100
|
+
annotationTool?: AnnotationTool,
|
|
101
|
+
annotationEditable?: boolean,
|
|
102
|
+
annotationIdMode?: AnnotationIdMode,
|
|
36
103
|
enableAnnotationRendering?: boolean,
|
|
37
104
|
enableAntialiasing?: boolean,
|
|
38
105
|
enablePaging?: boolean,
|
|
@@ -64,4 +131,5 @@ export type Props = {
|
|
|
64
131
|
|
|
65
132
|
declare export default class Pdf extends Component<Props> {
|
|
66
133
|
setPage: (pageNumber: number) => void;
|
|
134
|
+
saveAnnotations: () => Promise<AnnotationDocument>;
|
|
67
135
|
}
|
|
@@ -49,6 +49,11 @@ UIView
|
|
|
49
49
|
@property(nonatomic) BOOL enableRTL;
|
|
50
50
|
@property(nonatomic) BOOL enableAnnotationRendering;
|
|
51
51
|
@property(nonatomic) BOOL enableDoubleTapZoom;
|
|
52
|
+
@property(nonatomic, strong) NSString *annotations;
|
|
53
|
+
@property(nonatomic) BOOL annotationMode;
|
|
54
|
+
@property(nonatomic, strong) NSString *annotationTool;
|
|
55
|
+
@property(nonatomic) BOOL annotationEditable;
|
|
56
|
+
@property(nonatomic, strong) NSString *annotationIdMode;
|
|
52
57
|
@property(nonatomic) int fitPolicy;
|
|
53
58
|
@property(nonatomic) int spacing;
|
|
54
59
|
@property(nonatomic, strong) NSString *password;
|
|
@@ -56,6 +61,8 @@ UIView
|
|
|
56
61
|
|
|
57
62
|
@property(nonatomic, copy) RCTBubblingEventBlock onChange;
|
|
58
63
|
|
|
64
|
+
- (void)saveAnnotations;
|
|
65
|
+
|
|
59
66
|
@property(nonatomic, strong) NSString *selectedText;
|
|
60
67
|
@property(nonatomic) BOOL enableTextSelection;
|
|
61
68
|
@property(nonatomic, strong) PDFSelection *currentPDFSelection;
|