@scribeup/react-native-scribeup 0.2.0 → 0.3.2
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/README.md +65 -6
- package/android/src/main/java/com/rnscribeupsdk/ScribeupPackage.kt +1 -1
- package/android/src/main/java/com/rnscribeupsdk/ScribeupWidgetViewManager.kt +83 -0
- package/ios/Scribeup.m +9 -0
- package/ios/ScribeupWidgetViewManager.swift +95 -0
- package/package.json +3 -3
- package/src/ScribeUpWidget.d.ts +46 -0
- package/src/ScribeUpWidget.tsx +121 -0
- package/src/index.d.ts +3 -0
- package/src/index.ts +2 -0
package/README.md
CHANGED
|
@@ -11,11 +11,14 @@ The package is a thin wrapper around the native [iOS](https://github.com/ScribeU
|
|
|
11
11
|
1. [Bare React-Native](#bare-react-native)
|
|
12
12
|
2. [Expo Projects](#expo-projects)
|
|
13
13
|
2. [Quick Start](#quick-start)
|
|
14
|
-
3. [
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
3. [Components](#components)
|
|
15
|
+
1. [ScribeUp (Full Screen)](#scribeup-full-screen)
|
|
16
|
+
2. [ScribeUpWidget (Embeddable)](#scribeupwidget-embeddable)
|
|
17
|
+
4. [API Reference](#api-reference)
|
|
18
|
+
5. [Example Projects](#example-projects)
|
|
19
|
+
6. [Troubleshooting](#troubleshooting)
|
|
20
|
+
7. [Author](#author)
|
|
21
|
+
8. [License](#license)
|
|
19
22
|
|
|
20
23
|
|
|
21
24
|
## Installation
|
|
@@ -81,9 +84,51 @@ export default function App() {
|
|
|
81
84
|
|
|
82
85
|
---
|
|
83
86
|
|
|
87
|
+
## Components
|
|
88
|
+
|
|
89
|
+
The SDK provides two components for different integration scenarios:
|
|
90
|
+
|
|
91
|
+
### ScribeUp (Full Screen)
|
|
92
|
+
|
|
93
|
+
The main component that presents a full-screen modal subscription manager.
|
|
94
|
+
|
|
95
|
+
### ScribeUpWidget (Embeddable)
|
|
96
|
+
|
|
97
|
+
A lightweight widget view that can be embedded anywhere in your app and sized however you want.
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
import { ScribeUpWidget, ScribeupWidgetViewRef } from "@scribeup/react-native-scribeup";
|
|
101
|
+
|
|
102
|
+
export default function MyComponent() {
|
|
103
|
+
const widgetRef = useRef<ScribeupWidgetViewRef>(null);
|
|
104
|
+
|
|
105
|
+
const handleReload = () => {
|
|
106
|
+
widgetRef.current?.reload();
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<ScribeUpWidget
|
|
112
|
+
ref={widgetRef}
|
|
113
|
+
url="https://your-subscription-url.com"
|
|
114
|
+
style={{ width: '100%', height: 400 }}
|
|
115
|
+
/>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Key differences from the full-screen component:**
|
|
121
|
+
- Takes only one required parameter: `url`
|
|
122
|
+
- Has no header or navigation controls
|
|
123
|
+
- Can be sized and positioned flexibly
|
|
124
|
+
- Focused purely on displaying web content
|
|
125
|
+
- Provides imperative methods via ref (`reload()`, `loadURL()`)
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
84
129
|
## API Reference
|
|
85
130
|
|
|
86
|
-
ScribeUp
|
|
131
|
+
### ScribeUp (Full Screen)
|
|
87
132
|
|
|
88
133
|
```
|
|
89
134
|
<ScribeUp
|
|
@@ -93,6 +138,20 @@ ScribeUp is a *React component*. Mounting it immediately presents the native sub
|
|
|
93
138
|
/>
|
|
94
139
|
```
|
|
95
140
|
|
|
141
|
+
### ScribeUpWidget (Embeddable)
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
<ScribeUpWidget
|
|
145
|
+
url: string; // required – authenticated manage-subscriptions URL
|
|
146
|
+
style?: ViewStyle; // optional – styling for the widget container
|
|
147
|
+
ref?: ScribeupWidgetViewRef; // optional – ref for imperative methods
|
|
148
|
+
/>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Ref methods:**
|
|
152
|
+
- `reload()` – reloads the current page
|
|
153
|
+
- `loadURL(url: string)` – loads a new URL
|
|
154
|
+
|
|
96
155
|
### Exit Callback
|
|
97
156
|
|
|
98
157
|
`onExit` receives an object with two optional fields:
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
package com.rnscribeupsdk
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
|
+
import com.facebook.react.bridge.ReadableArray
|
|
6
|
+
import com.facebook.react.common.MapBuilder
|
|
7
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
8
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
9
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
10
|
+
import io.scribeup.scribeupsdk.ui.SubscriptionManagerWidgetView
|
|
11
|
+
|
|
12
|
+
class ScribeupWidgetViewManager(private val reactContext: ReactApplicationContext) : SimpleViewManager<SubscriptionManagerWidgetView>() {
|
|
13
|
+
|
|
14
|
+
companion object {
|
|
15
|
+
const val REACT_CLASS = "ScribeupWidgetView"
|
|
16
|
+
const val COMMAND_RELOAD = 1
|
|
17
|
+
const val COMMAND_LOAD_URL = 2
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override fun getName(): String {
|
|
21
|
+
return REACT_CLASS
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
override fun createViewInstance(reactContext: ThemedReactContext): SubscriptionManagerWidgetView {
|
|
25
|
+
return SubscriptionManagerWidgetView(reactContext)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@ReactProp(name = "url")
|
|
29
|
+
fun setUrl(view: SubscriptionManagerWidgetView, url: String?) {
|
|
30
|
+
if (!url.isNullOrEmpty()) {
|
|
31
|
+
view.loadURL(url)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
override fun getCommandsMap(): Map<String, Int>? {
|
|
36
|
+
return MapBuilder.of(
|
|
37
|
+
"reload", COMMAND_RELOAD,
|
|
38
|
+
"loadURL", COMMAND_LOAD_URL
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
override fun receiveCommand(
|
|
43
|
+
root: SubscriptionManagerWidgetView,
|
|
44
|
+
commandId: String?,
|
|
45
|
+
args: ReadableArray?
|
|
46
|
+
) {
|
|
47
|
+
super.receiveCommand(root, commandId, args)
|
|
48
|
+
|
|
49
|
+
when (commandId?.toIntOrNull()) {
|
|
50
|
+
COMMAND_RELOAD -> {
|
|
51
|
+
root.reload()
|
|
52
|
+
}
|
|
53
|
+
COMMAND_LOAD_URL -> {
|
|
54
|
+
if (args != null && args.size() > 0) {
|
|
55
|
+
val url = args.getString(0)
|
|
56
|
+
if (!url.isNullOrEmpty()) {
|
|
57
|
+
root.loadURL(url)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
override fun receiveCommand(
|
|
65
|
+
root: SubscriptionManagerWidgetView,
|
|
66
|
+
commandId: Int,
|
|
67
|
+
args: ReadableArray?
|
|
68
|
+
) {
|
|
69
|
+
when (commandId) {
|
|
70
|
+
COMMAND_RELOAD -> {
|
|
71
|
+
root.reload()
|
|
72
|
+
}
|
|
73
|
+
COMMAND_LOAD_URL -> {
|
|
74
|
+
if (args != null && args.size() > 0) {
|
|
75
|
+
val url = args.getString(0)
|
|
76
|
+
if (!url.isNullOrEmpty()) {
|
|
77
|
+
root.loadURL(url)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
package/ios/Scribeup.m
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#import <React/RCTBridgeModule.h>
|
|
2
2
|
#import <React/RCTEventEmitter.h>
|
|
3
|
+
#import <React/RCTViewManager.h>
|
|
3
4
|
|
|
4
5
|
@interface RCT_EXTERN_MODULE(Scribeup, RCTEventEmitter)
|
|
5
6
|
|
|
@@ -9,3 +10,11 @@ RCT_EXTERN_METHOD(presentWithUrl:(NSString *)url
|
|
|
9
10
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
10
11
|
|
|
11
12
|
@end
|
|
13
|
+
|
|
14
|
+
@interface RCT_EXTERN_MODULE(ScribeupWidgetViewManager, RCTViewManager)
|
|
15
|
+
|
|
16
|
+
RCT_EXPORT_VIEW_PROPERTY(url, NSString)
|
|
17
|
+
RCT_EXTERN_METHOD(reload:(nonnull NSNumber *)reactTag)
|
|
18
|
+
RCT_EXTERN_METHOD(loadURL:(nonnull NSNumber *)reactTag url:(NSString *)url)
|
|
19
|
+
|
|
20
|
+
@end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import ScribeUpSDK
|
|
3
|
+
import React
|
|
4
|
+
|
|
5
|
+
@objc(ScribeupWidgetViewManager)
|
|
6
|
+
class ScribeupWidgetViewManager: RCTViewManager {
|
|
7
|
+
|
|
8
|
+
override func view() -> UIView! {
|
|
9
|
+
return ScribeupWidgetView()
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@objc override static func requiresMainQueueSetup() -> Bool {
|
|
13
|
+
return true
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@objc func reload(_ reactTag: NSNumber) {
|
|
17
|
+
DispatchQueue.main.async {
|
|
18
|
+
self.bridge.uiManager.addUIBlock { (uiManager, viewRegistry) in
|
|
19
|
+
if let view = viewRegistry?[reactTag] as? ScribeupWidgetView {
|
|
20
|
+
view.reload()
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@objc func loadURL(_ reactTag: NSNumber, url: String) {
|
|
27
|
+
DispatchQueue.main.async {
|
|
28
|
+
self.bridge.uiManager.addUIBlock { (uiManager, viewRegistry) in
|
|
29
|
+
if let view = viewRegistry?[reactTag] as? ScribeupWidgetView {
|
|
30
|
+
view.loadURL(url)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
class ScribeupWidgetView: UIView {
|
|
38
|
+
|
|
39
|
+
private var widgetView: SubscriptionManagerWidgetView?
|
|
40
|
+
private var _url: String = ""
|
|
41
|
+
|
|
42
|
+
@objc var url: String = "" {
|
|
43
|
+
didSet {
|
|
44
|
+
_url = url
|
|
45
|
+
updateWidgetView()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
override init(frame: CGRect) {
|
|
50
|
+
super.init(frame: frame)
|
|
51
|
+
setupView()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
required init?(coder: NSCoder) {
|
|
55
|
+
super.init(coder: coder)
|
|
56
|
+
setupView()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private func setupView() {
|
|
60
|
+
backgroundColor = UIColor.clear
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private func updateWidgetView() {
|
|
64
|
+
// Remove existing widget view if any
|
|
65
|
+
widgetView?.removeFromSuperview()
|
|
66
|
+
widgetView = nil
|
|
67
|
+
|
|
68
|
+
// Create new widget view if URL is provided
|
|
69
|
+
if !_url.isEmpty {
|
|
70
|
+
widgetView = SubscriptionManagerWidgetView(url: _url)
|
|
71
|
+
|
|
72
|
+
if let widgetView = widgetView {
|
|
73
|
+
addSubview(widgetView)
|
|
74
|
+
widgetView.translatesAutoresizingMaskIntoConstraints = false
|
|
75
|
+
|
|
76
|
+
NSLayoutConstraint.activate([
|
|
77
|
+
widgetView.topAnchor.constraint(equalTo: topAnchor),
|
|
78
|
+
widgetView.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
79
|
+
widgetView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
80
|
+
widgetView.trailingAnchor.constraint(equalTo: trailingAnchor)
|
|
81
|
+
])
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// MARK: - Public Methods for React Native
|
|
87
|
+
|
|
88
|
+
@objc func reload() {
|
|
89
|
+
widgetView?.reload()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@objc func loadURL(_ urlString: String) {
|
|
93
|
+
widgetView?.loadURL(urlString)
|
|
94
|
+
}
|
|
95
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scribeup/react-native-scribeup",
|
|
3
|
-
"version": "0.2
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
},
|
|
53
53
|
"config": {
|
|
54
54
|
"nativeSDKVersions": {
|
|
55
|
-
"android": "0.7.
|
|
56
|
-
"ios": "0.7.
|
|
55
|
+
"android": "0.7.1",
|
|
56
|
+
"ios": "0.7.7"
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ViewStyle } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export interface ScribeupWidgetViewProps {
|
|
5
|
+
/**
|
|
6
|
+
* The URL to load in the widget
|
|
7
|
+
*/
|
|
8
|
+
url: string;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Optional style for the widget container
|
|
12
|
+
*/
|
|
13
|
+
style?: ViewStyle;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ScribeupWidgetViewRef {
|
|
17
|
+
/**
|
|
18
|
+
* Reload the current page in the widget
|
|
19
|
+
*/
|
|
20
|
+
reload: () => void;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Load a new URL in the widget
|
|
24
|
+
* @param url The new URL to load
|
|
25
|
+
*/
|
|
26
|
+
loadURL: (url: string) => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* ScribeUp Widget Component
|
|
31
|
+
*
|
|
32
|
+
* A lightweight widget view that displays a webview for subscription management.
|
|
33
|
+
* This is a flexible alternative to the full-screen ScribeUp component that can be
|
|
34
|
+
* embedded anywhere in your app and sized however you want.
|
|
35
|
+
*
|
|
36
|
+
* Unlike the full ScribeUp component, this widget:
|
|
37
|
+
* - Takes only one required parameter: url
|
|
38
|
+
* - Has no header or navigation controls
|
|
39
|
+
* - Is a simple View that can be sized flexibly
|
|
40
|
+
* - Is focused purely on displaying web content
|
|
41
|
+
*/
|
|
42
|
+
declare const ScribeUpWidget: React.ForwardRefExoticComponent<
|
|
43
|
+
ScribeupWidgetViewProps & React.RefAttributes<ScribeupWidgetViewRef>
|
|
44
|
+
>;
|
|
45
|
+
|
|
46
|
+
export default ScribeUpWidget;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import React, { useRef, useImperativeHandle, forwardRef } from 'react';
|
|
2
|
+
import { ViewStyle, UIManager, findNodeHandle, Platform } from 'react-native';
|
|
3
|
+
import { requireNativeComponent } from 'react-native';
|
|
4
|
+
|
|
5
|
+
const LINKING_ERROR =
|
|
6
|
+
`The package 'scribeup-react-native-scribeup' doesn't seem to be linked. Make sure: \n\n` +
|
|
7
|
+
Platform.select({
|
|
8
|
+
ios: "- You have run 'pod install'\n",
|
|
9
|
+
default: "",
|
|
10
|
+
}) +
|
|
11
|
+
"- You rebuilt the app after installing the package\n";
|
|
12
|
+
|
|
13
|
+
const ComponentName = 'ScribeupWidgetView';
|
|
14
|
+
|
|
15
|
+
const ScribeupWidgetViewNative =
|
|
16
|
+
UIManager.getViewManagerConfig(ComponentName) != null
|
|
17
|
+
? requireNativeComponent<ScribeupWidgetViewProps>(ComponentName)
|
|
18
|
+
: () => {
|
|
19
|
+
throw new Error(LINKING_ERROR);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export interface ScribeupWidgetViewProps {
|
|
23
|
+
/**
|
|
24
|
+
* The URL to load in the widget
|
|
25
|
+
*/
|
|
26
|
+
url: string;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Optional style for the widget container
|
|
30
|
+
*/
|
|
31
|
+
style?: ViewStyle;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ScribeupWidgetViewRef {
|
|
35
|
+
/**
|
|
36
|
+
* Reload the current page in the widget
|
|
37
|
+
*/
|
|
38
|
+
reload: () => void;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Load a new URL in the widget
|
|
42
|
+
* @param url The new URL to load
|
|
43
|
+
*/
|
|
44
|
+
loadURL: (url: string) => void;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* ScribeUp Widget Component
|
|
49
|
+
*
|
|
50
|
+
* A lightweight widget view that displays a webview for subscription management.
|
|
51
|
+
* This is a flexible alternative to the full-screen ScribeUp component that can be
|
|
52
|
+
* embedded anywhere in your app and sized however you want.
|
|
53
|
+
*
|
|
54
|
+
* Unlike the full ScribeUp component, this widget:
|
|
55
|
+
* - Takes only one required parameter: url
|
|
56
|
+
* - Has no header or navigation controls
|
|
57
|
+
* - Is a simple View that can be sized flexibly
|
|
58
|
+
* - Is focused purely on displaying web content
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```tsx
|
|
62
|
+
* import { ScribeUpWidget } from 'scribeup-react-native-scribeup';
|
|
63
|
+
*
|
|
64
|
+
* const MyComponent = () => {
|
|
65
|
+
* const widgetRef = useRef<ScribeupWidgetViewRef>(null);
|
|
66
|
+
*
|
|
67
|
+
* const handleReload = () => {
|
|
68
|
+
* widgetRef.current?.reload();
|
|
69
|
+
* };
|
|
70
|
+
*
|
|
71
|
+
*
|
|
72
|
+
* return (
|
|
73
|
+
* <ScribeUpWidget
|
|
74
|
+
* ref={widgetRef}
|
|
75
|
+
* url="https://your-subscription-url.com"
|
|
76
|
+
* style={{ width: '100%', height: 400 }}
|
|
77
|
+
* />
|
|
78
|
+
* );
|
|
79
|
+
* };
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
const ScribeUpWidget = forwardRef<ScribeupWidgetViewRef, ScribeupWidgetViewProps>(
|
|
83
|
+
({ url, style }, ref) => {
|
|
84
|
+
const nativeRef = useRef(null);
|
|
85
|
+
|
|
86
|
+
useImperativeHandle(ref, () => ({
|
|
87
|
+
reload: () => {
|
|
88
|
+
const viewId = findNodeHandle(nativeRef.current);
|
|
89
|
+
if (viewId) {
|
|
90
|
+
if (Platform.OS === 'ios') {
|
|
91
|
+
UIManager.dispatchViewManagerCommand(viewId, 'reload', []);
|
|
92
|
+
} else {
|
|
93
|
+
UIManager.dispatchViewManagerCommand(viewId, UIManager.getViewManagerConfig(ComponentName).Commands.reload, []);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
loadURL: (newUrl: string) => {
|
|
98
|
+
const viewId = findNodeHandle(nativeRef.current);
|
|
99
|
+
if (viewId) {
|
|
100
|
+
if (Platform.OS === 'ios') {
|
|
101
|
+
UIManager.dispatchViewManagerCommand(viewId, 'loadURL', [newUrl]);
|
|
102
|
+
} else {
|
|
103
|
+
UIManager.dispatchViewManagerCommand(viewId, UIManager.getViewManagerConfig(ComponentName).Commands.loadURL, [newUrl]);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
}));
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<ScribeupWidgetViewNative
|
|
111
|
+
ref={nativeRef}
|
|
112
|
+
url={url}
|
|
113
|
+
style={style}
|
|
114
|
+
/>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
ScribeUpWidget.displayName = 'ScribeUpWidget';
|
|
120
|
+
|
|
121
|
+
export default ScribeUpWidget;
|
package/src/index.d.ts
CHANGED