Skip to content

Commit ac2b994

Browse files
authored
fix: viewer module errorCodes (#892)
* fix: viewer module errorCodes * Bump @react-native-documents/viewer to major version Updated version of @react-native-documents/viewer to major and fixed viewer module errorCodes. * fix: old arch
1 parent 77fdeac commit ac2b994

File tree

7 files changed

+53
-39
lines changed

7 files changed

+53
-39
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@react-native-documents/viewer": major
3+
---
4+
5+
fix: viewer module errorCodes

packages/document-viewer/android/src/main/java/com/reactnativedocumentviewer/RNDocumentViewerModule.kt

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,18 @@ class RNDocumentViewerModule(reactContext: ReactApplicationContext) : NativeDocu
1919
permissions: String,
2020
mimeType: String?,
2121
title: String?,
22+
androidApplicationId: String?,
2223
presentation: String?,
2324
promise: Promise
2425
) {
25-
val currentActivity = reactApplicationContext.currentActivity
26-
if (currentActivity == null) {
27-
rejectWithNullActivity(promise)
28-
return
29-
}
26+
val currentActivity = reactApplicationContext.currentActivity ?: return rejectWithNullActivity(promise)
3027
if (BuildConfig.DEBUG && mimeType != null && !MimeTypeMap.getSingleton().hasMimeType(mimeType)) {
3128
RNLog.w(
3229
reactApplicationContext, "$mimeType appears to be an unusual mime type, are you sure it's correct?")
3330
}
3431

3532
try {
36-
val (uriToOpen, intentFlags) = constructUri(bookmarkOrUri, permissions)
33+
val (uriToOpen, intentFlags) = constructUri(bookmarkOrUri, permissions, androidApplicationId)
3734

3835
// grantUriPermission is not needed (for file uris WE OWN), we're using the Flags
3936
// on a Uri returned by FileProvider.getUriForFile()
@@ -53,17 +50,19 @@ class RNDocumentViewerModule(reactContext: ReactApplicationContext) : NativeDocu
5350
}
5451
}
5552

56-
private fun constructUri(bookmarkOrUri: String, permissions: String): UriWithFlags {
53+
private fun constructUri(bookmarkOrUri: String, permissions: String, androidApplicationId: String?): UriWithFlags {
5754
val flags = when (permissions) {
5855
"write" -> Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
5956
else -> Intent.FLAG_GRANT_READ_URI_PERMISSION
6057
}
6158
return if (bookmarkOrUri.startsWith("content://")) {
6259
UriWithFlags(Uri.parse(bookmarkOrUri), flags)
6360
} else if (bookmarkOrUri.startsWith("file://")) {
61+
// Package name may not be the same as applicationId but usually is.
62+
// Also see document-viewer/android/src/main/AndroidManifest.xml
63+
val applicationId = androidApplicationId ?: reactApplicationContext.packageName
64+
val authority = "$applicationId.reactnativedocumentviewer.fileprovider"
6465
val uri = Uri.parse(bookmarkOrUri)
65-
// TODO package name may not be the same as applicationId. Also see document-viewer/android/src/main/AndroidManifest.xml
66-
val authority = reactApplicationContext.packageName + ".reactnativedocumentviewer.fileprovider"
6766
val uriPath = uri.path ?: throw IllegalArgumentException("file:// uri must have a path")
6867
val fileUri = FileProvider.getUriForFile(
6968
reactApplicationContext,
@@ -81,10 +80,10 @@ class RNDocumentViewerModule(reactContext: ReactApplicationContext) : NativeDocu
8180

8281
companion object {
8382
fun rejectWithNullActivity(promise: Promise) {
84-
promise.reject(E_ACTIVITY_DOES_NOT_EXIST, "activity is null")
83+
promise.reject(NULL_PRESENTER, "current activity is null")
8584
}
8685

87-
private const val E_ACTIVITY_DOES_NOT_EXIST = "ACTIVITY_DOES_NOT_EXIST"
86+
private const val NULL_PRESENTER = "NULL_PRESENTER"
8887
private const val UNABLE_TO_OPEN_FILE_TYPE = "UNABLE_TO_OPEN_FILE_TYPE"
8988
}
9089
}

packages/document-viewer/android/src/paper/java/com/reactnativedocumentviewer/NativeDocumentViewerSpec.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@ public NativeDocumentViewerSpec(ReactApplicationContext reactContext) {
3434

3535
@ReactMethod
3636
@DoNotStrip
37-
public abstract void viewDocument(String bookmarkOrUri, String permissions, @Nullable String mimeType, @Nullable String title, @Nullable String presentationStyle, Promise promise);
37+
public abstract void viewDocument(String bookmarkOrUri, String permissions, @Nullable String mimeType, @Nullable String title, @Nullable String androidApplicationId, @Nullable String presentationStyle, Promise promise);
3838
}

packages/document-viewer/ios/RNDocumentViewer.mm

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
#import "RNDocumentViewer.h"
44
#import <React/RCTUtils.h>
55
#import "RNDPreviewController.h"
6-
// for UIModalPresentationStyle conversion
7-
// remove after https://github.com/facebook/react-native/commit/2d547a3252b328251e49dabfeec85f8d46c85411 is released
8-
#import <React/RCTModalHostViewManager.h>
6+
#import <React/RCTConvert.h>
7+
8+
static NSString * const RNDocViewerErrorUnableToOpenFileType = @"UNABLE_TO_OPEN_FILE_TYPE";
9+
static NSString * const RNDocViewerErrorNullPresenter = @"NULL_PRESENTER";
910

1011
@interface RNDocumentViewer ()
1112
@property(nonatomic, nullable) NSURL *presentedUrl;
@@ -24,6 +25,7 @@ + (BOOL)requiresMainQueueSetup {
2425
permissions:(NSString *)permissions
2526
mimeType:(NSString *)mimeType
2627
title:(NSString *)title
28+
androidApplicationId:(NSString *)androidApplicationId
2729
presentationStyle:(NSString *)presentationStyle
2830
resolve:(RCTPromiseResolveBlock)resolve
2931
reject:(RCTPromiseRejectBlock)reject) {
@@ -34,10 +36,10 @@ + (BOOL)requiresMainQueueSetup {
3436
[self presentPreview:title restoredURL:restoredURL presentationStyle:_presentationStyle resolve:resolve reject:reject];
3537
} else {
3638
NSData *bookmarkData = [[NSData alloc] initWithBase64EncodedString:bookmarkOrUri options:0];
37-
39+
3840
NSError *error = nil;
3941
BOOL isStale = NO;
40-
42+
4143
NSURL *restoredURL = [NSURL URLByResolvingBookmarkData:bookmarkData
4244
options:NSURLBookmarkResolutionWithoutUI
4345
relativeToURL:nil
@@ -50,7 +52,6 @@ + (BOOL)requiresMainQueueSetup {
5052
reject(@"RNDocViewer", @"Bookmark was resolved but it's stale", nil);
5153
return;
5254
}
53-
5455
if ([restoredURL startAccessingSecurityScopedResource]) {
5556
[self presentPreview:title restoredURL:restoredURL presentationStyle:_presentationStyle resolve:resolve reject:reject];
5657
} else {
@@ -62,7 +63,7 @@ + (BOOL)requiresMainQueueSetup {
6263
}
6364
}
6465

65-
- (void)presentPreview:(NSString *)title
66+
- (void)presentPreview:(NSString *)title
6667
restoredURL:(NSURL *)restoredURL
6768
presentationStyle:(UIModalPresentationStyle) presentationStyle
6869
resolve:(RCTPromiseResolveBlock)resolve
@@ -75,12 +76,16 @@ - (void)presentPreview:(NSString *)title
7576
controller.delegate = self;
7677

7778
if ([QLPreviewController canPreviewItem:item]) {
78-
[RCTPresentedViewController() presentViewController:controller animated:YES completion:^{
79+
UIViewController* presenter = RCTPresentedViewController();
80+
if (presenter) {
81+
[presenter presentViewController:controller animated:YES completion:nil];
7982
resolve([NSNull null]);
80-
}];
83+
} else {
84+
reject(RNDocViewerErrorNullPresenter, @"RCTPresentedViewController was nil", nil);
85+
}
8186
} else {
8287
[self.presentedUrl stopAccessingSecurityScopedResource];
83-
reject(@"UNABLE_TO_OPEN_FILE_TYPE", @"unsupported file", nil);
88+
reject(RNDocViewerErrorUnableToOpenFileType, @"unsupported file", nil);
8489
}
8590
});
8691
}
Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,21 @@
1-
export interface NativeModuleError extends Error {
2-
code: string
3-
}
4-
5-
const OPERATION_CANCELED = 'OPERATION_CANCELED'
6-
const IN_PROGRESS = 'ASYNC_OP_IN_PROGRESS'
71
const UNABLE_TO_OPEN_FILE_TYPE = 'UNABLE_TO_OPEN_FILE_TYPE'
2+
const NULL_PRESENTER = 'NULL_PRESENTER'
83

94
export const errorCodes = Object.freeze({
10-
OPERATION_CANCELED,
11-
IN_PROGRESS,
125
UNABLE_TO_OPEN_FILE_TYPE,
6+
NULL_PRESENTER,
137
})
148

9+
type ErrorCodes = (typeof errorCodes)[keyof typeof errorCodes]
10+
11+
export interface NativeModuleError extends Error {
12+
code: ErrorCodes | (string & {})
13+
}
14+
1515
/**
1616
* TypeScript helper to check if an object has the `code` property.
1717
* This is used to avoid `as` casting when you access the `code` property on errors returned by the module.
1818
*/
19-
export const isErrorWithCode = (error: any): error is NativeModuleError => {
20-
// to account for https://github.com/facebook/react-native/issues/41950
21-
const isNewArchErrorIOS = typeof error === 'object' && error != null
22-
return (error instanceof Error || isNewArchErrorIOS) && 'code' in error
19+
export const isErrorWithCode = (error: unknown): error is NativeModuleError => {
20+
return error instanceof Error && 'code' in error
2321
}

packages/document-viewer/src/index.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,28 @@ export type PresentationStyle =
1717
export type BaseOptions = {
1818
/**
1919
* Android only: The type of permission to grant to the receiving app that will open the document.
20-
* This only has effect if you're viewing a file that lives in the app's sandboxed storage.
20+
* This only has an effect if you're viewing a file that lives in the app's sandboxed storage.
2121
*/
2222
grantPermissions?: 'read' | 'write'
2323
/**
2424
* iOS only: The title to display in the header of the document viewer.
25-
* If not provided, the filename will be used.
25+
* @default the file name.
2626
*/
2727
headerTitle?: string
2828
/**
29-
* Optional, but recommended: the mimetype of the document. This will help the Android OS to find the right app(s) to open the document.
29+
* Optional, but strongly recommended: the mimetype of the document. This helps the Android OS to find the right app(s) to open the document.
3030
*/
3131
mimeType?: string
32-
3332
/**
34-
* iOS only - Controls how the picker is presented, e.g. on an iPad you may want to present it fullscreen. Defaults to `pageSheet`.
33+
* iOS only - Controls how the picker is presented, e.g. on an iPad you may want to present it fullscreen.
34+
* @default `pageSheet`.
3535
* */
3636
presentationStyle?: PresentationStyle
37+
/**
38+
* Android only - Optional, only provide a value if `viewDocument` rejects with `IllegalArgumentException`. Represents the unique identifier for an Android application.
39+
* @default application package name, which usually is the same as the application id.
40+
*/
41+
androidApplicationId?: string
3742
}
3843

3944
/**
@@ -74,6 +79,7 @@ export function viewDocument(data: ViewDocumentOptions): Promise<null> {
7479
data?.grantPermissions ?? 'read',
7580
data?.mimeType,
7681
data?.headerTitle,
82+
data?.androidApplicationId,
7783
data?.presentationStyle,
7884
)
7985
}

packages/document-viewer/src/spec/NativeDocumentViewer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface Spec extends TurboModule {
88
permissions: string,
99
mimeType?: string,
1010
title?: string,
11+
androidApplicationId?: string,
1112
presentationStyle?: string,
1213
): Promise<null>
1314
}

0 commit comments

Comments
 (0)