@dubsdotapp/expo 0.2.64 → 0.2.66
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/app.plugin.js +53 -38
- package/dist/index.d.mts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +20 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +20 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/hooks/usePushNotifications.ts +6 -1
- package/src/provider.tsx +14 -4
- package/src/ui/AuthGate.tsx +4 -4
- package/src/ui/UserProfileSheet.tsx +29 -27
package/package.json
CHANGED
|
@@ -4,6 +4,8 @@ import { useDubs } from '../provider';
|
|
|
4
4
|
import { DUBS_EXPO_PROJECT_ID } from '../constants';
|
|
5
5
|
|
|
6
6
|
export interface PushNotificationStatus {
|
|
7
|
+
/** Whether push notifications are enabled in the SDK configuration */
|
|
8
|
+
enabled: boolean;
|
|
7
9
|
/** Whether notification permission has been granted */
|
|
8
10
|
hasPermission: boolean;
|
|
9
11
|
/** The Expo push token, if registered */
|
|
@@ -27,7 +29,7 @@ export interface PushNotificationStatus {
|
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
export function usePushNotifications(): PushNotificationStatus {
|
|
30
|
-
const { client, appName } = useDubs();
|
|
32
|
+
const { client, appName, pushEnabled } = useDubs();
|
|
31
33
|
const channelId = useMemo(() => appName.toLowerCase().replace(/[^a-z0-9-]/g, ''), [appName]);
|
|
32
34
|
const [hasPermission, setHasPermission] = useState(false);
|
|
33
35
|
const [expoPushToken, setExpoPushToken] = useState<string | null>(null);
|
|
@@ -72,6 +74,7 @@ export function usePushNotifications(): PushNotificationStatus {
|
|
|
72
74
|
}, [client, getDeviceName]);
|
|
73
75
|
|
|
74
76
|
const register = useCallback(async (): Promise<boolean> => {
|
|
77
|
+
if (!pushEnabled) return false;
|
|
75
78
|
if (registering.current) return false;
|
|
76
79
|
registering.current = true;
|
|
77
80
|
setLoading(true);
|
|
@@ -138,6 +141,7 @@ export function usePushNotifications(): PushNotificationStatus {
|
|
|
138
141
|
}, [client, expoPushToken]);
|
|
139
142
|
|
|
140
143
|
const restoreIfGranted = useCallback(async () => {
|
|
144
|
+
if (!pushEnabled) return;
|
|
141
145
|
try {
|
|
142
146
|
const Notifications = getNotificationsModule();
|
|
143
147
|
if (!Notifications) return;
|
|
@@ -171,6 +175,7 @@ export function usePushNotifications(): PushNotificationStatus {
|
|
|
171
175
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
172
176
|
|
|
173
177
|
return {
|
|
178
|
+
enabled: pushEnabled,
|
|
174
179
|
hasPermission,
|
|
175
180
|
expoPushToken,
|
|
176
181
|
loading,
|
package/src/provider.tsx
CHANGED
|
@@ -24,6 +24,7 @@ export interface DubsContextValue {
|
|
|
24
24
|
network: DubsNetwork;
|
|
25
25
|
disconnect: () => Promise<void>;
|
|
26
26
|
uiConfig: UiConfig;
|
|
27
|
+
pushEnabled: boolean;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
const DubsContext = createContext<DubsContextValue | null>(null);
|
|
@@ -57,6 +58,8 @@ export interface DubsProviderProps {
|
|
|
57
58
|
redirectUri?: string;
|
|
58
59
|
/** App URL shown in Phantom's connect screen. */
|
|
59
60
|
appUrl?: string;
|
|
61
|
+
/** Enable Dubs push notifications. Default: true. Set false if your app manages its own Firebase/push. */
|
|
62
|
+
pushEnabled?: boolean;
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
// ── Provider ──
|
|
@@ -77,6 +80,7 @@ export function DubsProvider({
|
|
|
77
80
|
managed = true,
|
|
78
81
|
redirectUri,
|
|
79
82
|
appUrl,
|
|
83
|
+
pushEnabled = true,
|
|
80
84
|
}: DubsProviderProps) {
|
|
81
85
|
// Resolve network config — explicit props override network defaults
|
|
82
86
|
const config = NETWORK_CONFIG[network];
|
|
@@ -129,6 +133,7 @@ export function DubsProvider({
|
|
|
129
133
|
renderRegistration={renderRegistration}
|
|
130
134
|
accentColor={uiConfig.accentColor}
|
|
131
135
|
uiConfig={uiConfig}
|
|
136
|
+
pushEnabled={pushEnabled}
|
|
132
137
|
>
|
|
133
138
|
{children}
|
|
134
139
|
</ExternalWalletProvider>
|
|
@@ -163,6 +168,7 @@ export function DubsProvider({
|
|
|
163
168
|
renderRegistration={renderRegistration}
|
|
164
169
|
accentColor={uiConfig.accentColor}
|
|
165
170
|
uiConfig={uiConfig}
|
|
171
|
+
pushEnabled={pushEnabled}
|
|
166
172
|
>
|
|
167
173
|
{children}
|
|
168
174
|
</ManagedInner>
|
|
@@ -186,6 +192,7 @@ function ManagedInner({
|
|
|
186
192
|
renderRegistration,
|
|
187
193
|
accentColor,
|
|
188
194
|
uiConfig,
|
|
195
|
+
pushEnabled,
|
|
189
196
|
children,
|
|
190
197
|
}: {
|
|
191
198
|
client: DubsClient;
|
|
@@ -199,6 +206,7 @@ function ManagedInner({
|
|
|
199
206
|
renderRegistration?: (props: RegistrationScreenProps) => React.ReactNode;
|
|
200
207
|
accentColor?: string;
|
|
201
208
|
uiConfig: UiConfig;
|
|
209
|
+
pushEnabled: boolean;
|
|
202
210
|
children: React.ReactNode;
|
|
203
211
|
}) {
|
|
204
212
|
const managedDisconnect = useDisconnect();
|
|
@@ -211,8 +219,8 @@ function ManagedInner({
|
|
|
211
219
|
}, [client, managedDisconnect]);
|
|
212
220
|
|
|
213
221
|
const value = useMemo<DubsContextValue>(
|
|
214
|
-
() => ({ client, wallet, connection, appName, network, disconnect, uiConfig }),
|
|
215
|
-
[client, wallet, connection, appName, network, disconnect, uiConfig],
|
|
222
|
+
() => ({ client, wallet, connection, appName, network, disconnect, uiConfig, pushEnabled }),
|
|
223
|
+
[client, wallet, connection, appName, network, disconnect, uiConfig, pushEnabled],
|
|
216
224
|
);
|
|
217
225
|
|
|
218
226
|
return (
|
|
@@ -250,6 +258,7 @@ function ExternalWalletProvider({
|
|
|
250
258
|
renderRegistration,
|
|
251
259
|
accentColor,
|
|
252
260
|
uiConfig,
|
|
261
|
+
pushEnabled,
|
|
253
262
|
children,
|
|
254
263
|
}: {
|
|
255
264
|
client: DubsClient;
|
|
@@ -264,6 +273,7 @@ function ExternalWalletProvider({
|
|
|
264
273
|
renderRegistration?: (props: RegistrationScreenProps) => React.ReactNode;
|
|
265
274
|
accentColor?: string;
|
|
266
275
|
uiConfig: UiConfig;
|
|
276
|
+
pushEnabled: boolean;
|
|
267
277
|
children: React.ReactNode;
|
|
268
278
|
}) {
|
|
269
279
|
const disconnect = useCallback(async () => {
|
|
@@ -273,8 +283,8 @@ function ExternalWalletProvider({
|
|
|
273
283
|
}, [client, storage, wallet]);
|
|
274
284
|
|
|
275
285
|
const value = useMemo<DubsContextValue>(
|
|
276
|
-
() => ({ client, wallet, connection, appName, network, disconnect, uiConfig }),
|
|
277
|
-
[client, wallet, connection, appName, network, disconnect, uiConfig],
|
|
286
|
+
() => ({ client, wallet, connection, appName, network, disconnect, uiConfig, pushEnabled }),
|
|
287
|
+
[client, wallet, connection, appName, network, disconnect, uiConfig, pushEnabled],
|
|
278
288
|
);
|
|
279
289
|
|
|
280
290
|
if (!managed) {
|
package/src/ui/AuthGate.tsx
CHANGED
|
@@ -73,7 +73,7 @@ export function AuthGate({
|
|
|
73
73
|
appName = 'Dubs',
|
|
74
74
|
accentColor,
|
|
75
75
|
}: AuthGateProps) {
|
|
76
|
-
const { client } = useDubs();
|
|
76
|
+
const { client, pushEnabled } = useDubs();
|
|
77
77
|
const auth = useAuth();
|
|
78
78
|
const [phase, setPhase] = useState<'init' | 'active'>('init');
|
|
79
79
|
const [registrationPhase, setRegistrationPhase] = useState(false);
|
|
@@ -109,10 +109,10 @@ export function AuthGate({
|
|
|
109
109
|
|
|
110
110
|
// Show push setup after new registration completes (not restored sessions)
|
|
111
111
|
useEffect(() => {
|
|
112
|
-
if (auth.status === 'authenticated' && registrationPhase && !isRestoredSession) {
|
|
112
|
+
if (pushEnabled && auth.status === 'authenticated' && registrationPhase && !isRestoredSession) {
|
|
113
113
|
setShowPushSetup(true);
|
|
114
114
|
}
|
|
115
|
-
}, [auth.status, registrationPhase, isRestoredSession]);
|
|
115
|
+
}, [pushEnabled, auth.status, registrationPhase, isRestoredSession]);
|
|
116
116
|
|
|
117
117
|
useEffect(() => {
|
|
118
118
|
if (auth.token) onSaveToken(auth.token);
|
|
@@ -151,7 +151,7 @@ export function AuthGate({
|
|
|
151
151
|
}
|
|
152
152
|
return (
|
|
153
153
|
<AuthContext.Provider value={auth}>
|
|
154
|
-
<PushTokenRestorer />
|
|
154
|
+
{pushEnabled && <PushTokenRestorer />}
|
|
155
155
|
{children}
|
|
156
156
|
</AuthContext.Provider>
|
|
157
157
|
);
|
|
@@ -254,36 +254,38 @@ export function UserProfileSheet({
|
|
|
254
254
|
) : null}
|
|
255
255
|
|
|
256
256
|
{/* Push Notifications */}
|
|
257
|
-
|
|
258
|
-
<View style={styles.
|
|
259
|
-
<
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
257
|
+
{push.enabled && (
|
|
258
|
+
<View style={[styles.notifRow, { backgroundColor: t.surface, borderColor: t.border }]}>
|
|
259
|
+
<View style={styles.notifLeft}>
|
|
260
|
+
<Text style={[styles.notifLabel, { color: t.text }]}>Push Notifications</Text>
|
|
261
|
+
<Text
|
|
262
|
+
style={[
|
|
263
|
+
styles.notifStatus,
|
|
264
|
+
{ color: push.hasPermission ? t.success : t.textMuted },
|
|
265
|
+
]}
|
|
266
|
+
>
|
|
267
|
+
{push.hasPermission ? 'Enabled' : 'Disabled'}
|
|
268
|
+
</Text>
|
|
269
|
+
</View>
|
|
270
|
+
{!push.hasPermission && (
|
|
271
|
+
<TouchableOpacity
|
|
272
|
+
style={[styles.enableButton, { backgroundColor: t.accent }]}
|
|
273
|
+
onPress={push.register}
|
|
274
|
+
disabled={push.loading}
|
|
275
|
+
activeOpacity={0.8}
|
|
276
|
+
>
|
|
277
|
+
{push.loading ? (
|
|
278
|
+
<ActivityIndicator size="small" color="#FFFFFF" />
|
|
279
|
+
) : (
|
|
280
|
+
<Text style={styles.enableText}>Enable</Text>
|
|
281
|
+
)}
|
|
282
|
+
</TouchableOpacity>
|
|
283
|
+
)}
|
|
268
284
|
</View>
|
|
269
|
-
|
|
270
|
-
<TouchableOpacity
|
|
271
|
-
style={[styles.enableButton, { backgroundColor: t.accent }]}
|
|
272
|
-
onPress={push.register}
|
|
273
|
-
disabled={push.loading}
|
|
274
|
-
activeOpacity={0.8}
|
|
275
|
-
>
|
|
276
|
-
{push.loading ? (
|
|
277
|
-
<ActivityIndicator size="small" color="#FFFFFF" />
|
|
278
|
-
) : (
|
|
279
|
-
<Text style={styles.enableText}>Enable</Text>
|
|
280
|
-
)}
|
|
281
|
-
</TouchableOpacity>
|
|
282
|
-
)}
|
|
283
|
-
</View>
|
|
285
|
+
)}
|
|
284
286
|
|
|
285
287
|
{/* Push error */}
|
|
286
|
-
{push.error ? (
|
|
288
|
+
{push.enabled && push.error ? (
|
|
287
289
|
<View style={[styles.errorBox, { backgroundColor: t.errorBg, borderColor: t.errorBorder }]}>
|
|
288
290
|
<Text style={[styles.errorText, { color: t.errorText }]}>{push.error.message}</Text>
|
|
289
291
|
</View>
|