@dubsdotapp/expo 0.2.53 → 0.2.55
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/dist/index.d.mts +31 -1
- package/dist/index.d.ts +31 -1
- package/dist/index.js +648 -399
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +322 -74
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -2
- package/src/client.ts +18 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/usePushNotifications.ts +169 -0
- package/src/index.ts +2 -0
- package/src/ui/AuthGate.tsx +151 -2
package/dist/index.mjs
CHANGED
|
@@ -459,6 +459,21 @@ var DubsClient = class {
|
|
|
459
459
|
);
|
|
460
460
|
this._token = null;
|
|
461
461
|
}
|
|
462
|
+
// ── Push Notifications ──
|
|
463
|
+
async registerPushToken(params) {
|
|
464
|
+
await this.request(
|
|
465
|
+
"POST",
|
|
466
|
+
"/push/expo-token",
|
|
467
|
+
params
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
async unregisterPushToken(token) {
|
|
471
|
+
await this.request(
|
|
472
|
+
"DELETE",
|
|
473
|
+
"/push/expo-token",
|
|
474
|
+
{ token }
|
|
475
|
+
);
|
|
476
|
+
}
|
|
462
477
|
// ── Error Utilities ──
|
|
463
478
|
async parseError(error) {
|
|
464
479
|
const res = await this.request(
|
|
@@ -533,7 +548,7 @@ function createSecureStoreStorage() {
|
|
|
533
548
|
}
|
|
534
549
|
|
|
535
550
|
// src/provider.tsx
|
|
536
|
-
import { createContext as createContext4, useContext as useContext4, useMemo, useCallback as
|
|
551
|
+
import { createContext as createContext4, useContext as useContext4, useMemo as useMemo2, useCallback as useCallback15, useState as useState16, useEffect as useEffect10 } from "react";
|
|
537
552
|
|
|
538
553
|
// src/ui/theme.ts
|
|
539
554
|
import { createContext, useContext } from "react";
|
|
@@ -1598,7 +1613,7 @@ function ManagedWalletProvider({
|
|
|
1598
1613
|
}
|
|
1599
1614
|
|
|
1600
1615
|
// src/ui/AuthGate.tsx
|
|
1601
|
-
import React2, { useState as
|
|
1616
|
+
import React2, { useState as useState15, useEffect as useEffect9, useRef as useRef4, useCallback as useCallback14 } from "react";
|
|
1602
1617
|
import {
|
|
1603
1618
|
View as View2,
|
|
1604
1619
|
Text as Text2,
|
|
@@ -1608,7 +1623,7 @@ import {
|
|
|
1608
1623
|
StyleSheet as StyleSheet2,
|
|
1609
1624
|
Keyboard,
|
|
1610
1625
|
KeyboardAvoidingView,
|
|
1611
|
-
Platform as
|
|
1626
|
+
Platform as Platform4,
|
|
1612
1627
|
Image as Image2,
|
|
1613
1628
|
Animated,
|
|
1614
1629
|
ScrollView
|
|
@@ -2277,6 +2292,126 @@ function useUFCFighterDetail(athleteId) {
|
|
|
2277
2292
|
return { data, loading, error, refetch: fetchData };
|
|
2278
2293
|
}
|
|
2279
2294
|
|
|
2295
|
+
// src/hooks/usePushNotifications.ts
|
|
2296
|
+
import { useState as useState14, useCallback as useCallback13, useRef as useRef3, useMemo } from "react";
|
|
2297
|
+
import { Platform as Platform3 } from "react-native";
|
|
2298
|
+
function usePushNotifications() {
|
|
2299
|
+
const { client, appName } = useDubs();
|
|
2300
|
+
const channelId = useMemo(() => appName.toLowerCase().replace(/[^a-z0-9-]/g, ""), [appName]);
|
|
2301
|
+
const [hasPermission, setHasPermission] = useState14(false);
|
|
2302
|
+
const [expoPushToken, setExpoPushToken] = useState14(null);
|
|
2303
|
+
const [loading, setLoading] = useState14(false);
|
|
2304
|
+
const [error, setError] = useState14(null);
|
|
2305
|
+
const registering = useRef3(false);
|
|
2306
|
+
const getNotificationsModule = useCallback13(() => {
|
|
2307
|
+
try {
|
|
2308
|
+
return __require("expo-notifications");
|
|
2309
|
+
} catch {
|
|
2310
|
+
return null;
|
|
2311
|
+
}
|
|
2312
|
+
}, []);
|
|
2313
|
+
const getDeviceName = useCallback13(() => {
|
|
2314
|
+
try {
|
|
2315
|
+
const Device = __require("expo-device");
|
|
2316
|
+
return Device.deviceName || null;
|
|
2317
|
+
} catch {
|
|
2318
|
+
return null;
|
|
2319
|
+
}
|
|
2320
|
+
}, []);
|
|
2321
|
+
const setupAndroidChannels = useCallback13((Notifications) => {
|
|
2322
|
+
if (Platform3.OS === "android") {
|
|
2323
|
+
Notifications.setNotificationChannelAsync(channelId || "default", {
|
|
2324
|
+
name: appName || "Default",
|
|
2325
|
+
importance: Notifications.AndroidImportance?.MAX ?? 4,
|
|
2326
|
+
vibrationPattern: [0, 250, 250, 250]
|
|
2327
|
+
}).catch(() => {
|
|
2328
|
+
});
|
|
2329
|
+
}
|
|
2330
|
+
}, [channelId, appName]);
|
|
2331
|
+
const registerTokenWithServer = useCallback13(async (token) => {
|
|
2332
|
+
const deviceName = getDeviceName();
|
|
2333
|
+
await client.registerPushToken({
|
|
2334
|
+
token,
|
|
2335
|
+
platform: Platform3.OS,
|
|
2336
|
+
deviceName: deviceName || void 0
|
|
2337
|
+
});
|
|
2338
|
+
}, [client, getDeviceName]);
|
|
2339
|
+
const register = useCallback13(async () => {
|
|
2340
|
+
if (registering.current) return false;
|
|
2341
|
+
registering.current = true;
|
|
2342
|
+
setLoading(true);
|
|
2343
|
+
setError(null);
|
|
2344
|
+
try {
|
|
2345
|
+
const Notifications = getNotificationsModule();
|
|
2346
|
+
if (!Notifications) {
|
|
2347
|
+
throw new Error("expo-notifications is not installed");
|
|
2348
|
+
}
|
|
2349
|
+
const { status: existingStatus } = await Notifications.getPermissionsAsync();
|
|
2350
|
+
let finalStatus = existingStatus;
|
|
2351
|
+
if (existingStatus !== "granted") {
|
|
2352
|
+
const { status } = await Notifications.requestPermissionsAsync();
|
|
2353
|
+
finalStatus = status;
|
|
2354
|
+
}
|
|
2355
|
+
if (finalStatus !== "granted") {
|
|
2356
|
+
setHasPermission(false);
|
|
2357
|
+
setLoading(false);
|
|
2358
|
+
registering.current = false;
|
|
2359
|
+
return false;
|
|
2360
|
+
}
|
|
2361
|
+
setHasPermission(true);
|
|
2362
|
+
const tokenResult = await Notifications.getExpoPushTokenAsync();
|
|
2363
|
+
const token = tokenResult.data;
|
|
2364
|
+
setExpoPushToken(token);
|
|
2365
|
+
await registerTokenWithServer(token);
|
|
2366
|
+
setupAndroidChannels(Notifications);
|
|
2367
|
+
setLoading(false);
|
|
2368
|
+
registering.current = false;
|
|
2369
|
+
return true;
|
|
2370
|
+
} catch (err) {
|
|
2371
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
2372
|
+
setError(e);
|
|
2373
|
+
setLoading(false);
|
|
2374
|
+
registering.current = false;
|
|
2375
|
+
console.error("[usePushNotifications] Registration error:", e.message);
|
|
2376
|
+
return false;
|
|
2377
|
+
}
|
|
2378
|
+
}, [getNotificationsModule, registerTokenWithServer, setupAndroidChannels]);
|
|
2379
|
+
const unregister = useCallback13(async () => {
|
|
2380
|
+
if (!expoPushToken) return;
|
|
2381
|
+
try {
|
|
2382
|
+
await client.unregisterPushToken(expoPushToken);
|
|
2383
|
+
setExpoPushToken(null);
|
|
2384
|
+
} catch (err) {
|
|
2385
|
+
console.error("[usePushNotifications] Unregister error:", err);
|
|
2386
|
+
}
|
|
2387
|
+
}, [client, expoPushToken]);
|
|
2388
|
+
const restoreIfGranted = useCallback13(async () => {
|
|
2389
|
+
try {
|
|
2390
|
+
const Notifications = getNotificationsModule();
|
|
2391
|
+
if (!Notifications) return;
|
|
2392
|
+
const { status } = await Notifications.getPermissionsAsync();
|
|
2393
|
+
if (status !== "granted") return;
|
|
2394
|
+
setHasPermission(true);
|
|
2395
|
+
const tokenResult = await Notifications.getExpoPushTokenAsync();
|
|
2396
|
+
const token = tokenResult.data;
|
|
2397
|
+
setExpoPushToken(token);
|
|
2398
|
+
await registerTokenWithServer(token);
|
|
2399
|
+
setupAndroidChannels(Notifications);
|
|
2400
|
+
} catch (err) {
|
|
2401
|
+
console.log("[usePushNotifications] Restore skipped:", err instanceof Error ? err.message : err);
|
|
2402
|
+
}
|
|
2403
|
+
}, [getNotificationsModule, registerTokenWithServer, setupAndroidChannels]);
|
|
2404
|
+
return {
|
|
2405
|
+
hasPermission,
|
|
2406
|
+
expoPushToken,
|
|
2407
|
+
loading,
|
|
2408
|
+
error,
|
|
2409
|
+
register,
|
|
2410
|
+
unregister,
|
|
2411
|
+
restoreIfGranted
|
|
2412
|
+
};
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2280
2415
|
// src/ui/AuthGate.tsx
|
|
2281
2416
|
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
2282
2417
|
var DICEBEAR_STYLES = [
|
|
@@ -2305,8 +2440,10 @@ function AuthGate({
|
|
|
2305
2440
|
}) {
|
|
2306
2441
|
const { client } = useDubs();
|
|
2307
2442
|
const auth = useAuth();
|
|
2308
|
-
const [phase, setPhase] =
|
|
2309
|
-
const [registrationPhase, setRegistrationPhase] =
|
|
2443
|
+
const [phase, setPhase] = useState15("init");
|
|
2444
|
+
const [registrationPhase, setRegistrationPhase] = useState15(false);
|
|
2445
|
+
const [showPushSetup, setShowPushSetup] = useState15(false);
|
|
2446
|
+
const [isRestoredSession, setIsRestoredSession] = useState15(false);
|
|
2310
2447
|
useEffect9(() => {
|
|
2311
2448
|
let cancelled = false;
|
|
2312
2449
|
(async () => {
|
|
@@ -2317,6 +2454,7 @@ function AuthGate({
|
|
|
2317
2454
|
const restored = await auth.restoreSession(savedToken);
|
|
2318
2455
|
if (cancelled) return;
|
|
2319
2456
|
if (restored) {
|
|
2457
|
+
setIsRestoredSession(true);
|
|
2320
2458
|
setPhase("active");
|
|
2321
2459
|
return;
|
|
2322
2460
|
}
|
|
@@ -2336,15 +2474,20 @@ function AuthGate({
|
|
|
2336
2474
|
useEffect9(() => {
|
|
2337
2475
|
if (auth.status === "needsRegistration") setRegistrationPhase(true);
|
|
2338
2476
|
}, [auth.status]);
|
|
2477
|
+
useEffect9(() => {
|
|
2478
|
+
if (auth.status === "authenticated" && registrationPhase && !isRestoredSession) {
|
|
2479
|
+
setShowPushSetup(true);
|
|
2480
|
+
}
|
|
2481
|
+
}, [auth.status, registrationPhase, isRestoredSession]);
|
|
2339
2482
|
useEffect9(() => {
|
|
2340
2483
|
if (auth.token) onSaveToken(auth.token);
|
|
2341
2484
|
}, [auth.token]);
|
|
2342
|
-
const retry =
|
|
2485
|
+
const retry = useCallback14(() => {
|
|
2343
2486
|
setRegistrationPhase(false);
|
|
2344
2487
|
auth.reset();
|
|
2345
2488
|
auth.authenticate();
|
|
2346
2489
|
}, [auth]);
|
|
2347
|
-
const handleRegister =
|
|
2490
|
+
const handleRegister = useCallback14(
|
|
2348
2491
|
(username, referralCode, avatarUrl) => {
|
|
2349
2492
|
auth.register(username, referralCode, avatarUrl);
|
|
2350
2493
|
},
|
|
@@ -2355,7 +2498,20 @@ function AuthGate({
|
|
|
2355
2498
|
return /* @__PURE__ */ jsx3(DefaultLoadingScreen, { status: "authenticating", appName, accentColor });
|
|
2356
2499
|
}
|
|
2357
2500
|
if (auth.status === "authenticated") {
|
|
2358
|
-
|
|
2501
|
+
if (showPushSetup) {
|
|
2502
|
+
return /* @__PURE__ */ jsx3(
|
|
2503
|
+
PushSetupScreen,
|
|
2504
|
+
{
|
|
2505
|
+
accentColor,
|
|
2506
|
+
appName,
|
|
2507
|
+
onComplete: () => setShowPushSetup(false)
|
|
2508
|
+
}
|
|
2509
|
+
);
|
|
2510
|
+
}
|
|
2511
|
+
return /* @__PURE__ */ jsxs2(AuthContext.Provider, { value: auth, children: [
|
|
2512
|
+
/* @__PURE__ */ jsx3(PushTokenRestorer, {}),
|
|
2513
|
+
children
|
|
2514
|
+
] });
|
|
2359
2515
|
}
|
|
2360
2516
|
if (registrationPhase) {
|
|
2361
2517
|
const isRegistering = auth.status === "registering";
|
|
@@ -2447,17 +2603,17 @@ function DefaultRegistrationScreen({
|
|
|
2447
2603
|
}) {
|
|
2448
2604
|
const t = useDubsTheme();
|
|
2449
2605
|
const accent = accentColor || t.accent;
|
|
2450
|
-
const [step, setStep] =
|
|
2451
|
-
const [avatarSeed, setAvatarSeed] =
|
|
2452
|
-
const [avatarStyle, setAvatarStyle] =
|
|
2453
|
-
const [showStyles, setShowStyles] =
|
|
2454
|
-
const [username, setUsername] =
|
|
2455
|
-
const [referralCode, setReferralCode] =
|
|
2456
|
-
const [checking, setChecking] =
|
|
2457
|
-
const [availability, setAvailability] =
|
|
2458
|
-
const debounceRef =
|
|
2459
|
-
const fadeAnim =
|
|
2460
|
-
const slideAnim =
|
|
2606
|
+
const [step, setStep] = useState15(0);
|
|
2607
|
+
const [avatarSeed, setAvatarSeed] = useState15(generateSeed);
|
|
2608
|
+
const [avatarStyle, setAvatarStyle] = useState15("adventurer");
|
|
2609
|
+
const [showStyles, setShowStyles] = useState15(false);
|
|
2610
|
+
const [username, setUsername] = useState15("");
|
|
2611
|
+
const [referralCode, setReferralCode] = useState15("");
|
|
2612
|
+
const [checking, setChecking] = useState15(false);
|
|
2613
|
+
const [availability, setAvailability] = useState15(null);
|
|
2614
|
+
const debounceRef = useRef4(null);
|
|
2615
|
+
const fadeAnim = useRef4(new Animated.Value(1)).current;
|
|
2616
|
+
const slideAnim = useRef4(new Animated.Value(0)).current;
|
|
2461
2617
|
const avatarUrl = getAvatarUrl(avatarStyle, avatarSeed);
|
|
2462
2618
|
useEffect9(() => {
|
|
2463
2619
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
@@ -2482,7 +2638,7 @@ function DefaultRegistrationScreen({
|
|
|
2482
2638
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
2483
2639
|
};
|
|
2484
2640
|
}, [username, client]);
|
|
2485
|
-
const animateToStep =
|
|
2641
|
+
const animateToStep = useCallback14((newStep) => {
|
|
2486
2642
|
const dir = newStep > step ? 1 : -1;
|
|
2487
2643
|
Keyboard.dismiss();
|
|
2488
2644
|
Animated.parallel([
|
|
@@ -2694,7 +2850,7 @@ function DefaultRegistrationScreen({
|
|
|
2694
2850
|
KeyboardAvoidingView,
|
|
2695
2851
|
{
|
|
2696
2852
|
style: [s.container, { backgroundColor: t.background }],
|
|
2697
|
-
behavior:
|
|
2853
|
+
behavior: Platform4.OS === "ios" ? "padding" : void 0,
|
|
2698
2854
|
children: /* @__PURE__ */ jsx3(
|
|
2699
2855
|
ScrollView,
|
|
2700
2856
|
{
|
|
@@ -2716,6 +2872,97 @@ function DefaultRegistrationScreen({
|
|
|
2716
2872
|
}
|
|
2717
2873
|
);
|
|
2718
2874
|
}
|
|
2875
|
+
function PushTokenRestorer() {
|
|
2876
|
+
const push = usePushNotifications();
|
|
2877
|
+
const restored = useRef4(false);
|
|
2878
|
+
useEffect9(() => {
|
|
2879
|
+
if (restored.current) return;
|
|
2880
|
+
restored.current = true;
|
|
2881
|
+
push.restoreIfGranted();
|
|
2882
|
+
}, []);
|
|
2883
|
+
return null;
|
|
2884
|
+
}
|
|
2885
|
+
function PushSetupScreen({
|
|
2886
|
+
accentColor,
|
|
2887
|
+
appName,
|
|
2888
|
+
onComplete
|
|
2889
|
+
}) {
|
|
2890
|
+
const t = useDubsTheme();
|
|
2891
|
+
const accent = accentColor || t.accent;
|
|
2892
|
+
const push = usePushNotifications();
|
|
2893
|
+
const fadeAnim = useRef4(new Animated.Value(0)).current;
|
|
2894
|
+
const slideAnim = useRef4(new Animated.Value(30)).current;
|
|
2895
|
+
useEffect9(() => {
|
|
2896
|
+
Animated.parallel([
|
|
2897
|
+
Animated.timing(fadeAnim, { toValue: 1, duration: 300, useNativeDriver: true }),
|
|
2898
|
+
Animated.timing(slideAnim, { toValue: 0, duration: 300, useNativeDriver: true })
|
|
2899
|
+
]).start();
|
|
2900
|
+
}, [fadeAnim, slideAnim]);
|
|
2901
|
+
const handleEnable = async () => {
|
|
2902
|
+
await push.register();
|
|
2903
|
+
onComplete();
|
|
2904
|
+
};
|
|
2905
|
+
const benefits = [
|
|
2906
|
+
"A fight you picked on goes LIVE",
|
|
2907
|
+
"Your pick wins or loses",
|
|
2908
|
+
"Final results and rankings"
|
|
2909
|
+
];
|
|
2910
|
+
return /* @__PURE__ */ jsx3(View2, { style: [s.container, { backgroundColor: t.background }], children: /* @__PURE__ */ jsxs2(
|
|
2911
|
+
Animated.View,
|
|
2912
|
+
{
|
|
2913
|
+
style: [
|
|
2914
|
+
s.stepContainer,
|
|
2915
|
+
{ opacity: fadeAnim, transform: [{ translateY: slideAnim }] }
|
|
2916
|
+
],
|
|
2917
|
+
children: [
|
|
2918
|
+
/* @__PURE__ */ jsxs2(View2, { style: s.stepTop, children: [
|
|
2919
|
+
/* @__PURE__ */ jsx3(Text2, { style: [s.title, { color: t.text }], children: "Enable Notifications" }),
|
|
2920
|
+
/* @__PURE__ */ jsx3(Text2, { style: [s.subtitle, { color: t.textMuted }], children: "Stay in the loop with real-time updates" }),
|
|
2921
|
+
/* @__PURE__ */ jsx3(StepIndicator, { currentStep: 3 }),
|
|
2922
|
+
/* @__PURE__ */ jsx3(View2, { style: pushStyles.iconContainer, children: /* @__PURE__ */ jsx3(View2, { style: [pushStyles.bellCircle, { backgroundColor: accent + "20" }], children: /* @__PURE__ */ jsx3(Text2, { style: [pushStyles.bellIcon, { color: accent }], children: "\u{1F514}" }) }) }),
|
|
2923
|
+
/* @__PURE__ */ jsxs2(View2, { style: pushStyles.benefitsList, children: [
|
|
2924
|
+
/* @__PURE__ */ jsx3(Text2, { style: [pushStyles.benefitsHeader, { color: t.text }], children: "Get real-time updates when:" }),
|
|
2925
|
+
benefits.map((item, i) => /* @__PURE__ */ jsxs2(View2, { style: pushStyles.benefitRow, children: [
|
|
2926
|
+
/* @__PURE__ */ jsx3(View2, { style: [pushStyles.bulletDot, { backgroundColor: accent }] }),
|
|
2927
|
+
/* @__PURE__ */ jsx3(Text2, { style: [pushStyles.benefitText, { color: t.textMuted }], children: item })
|
|
2928
|
+
] }, i))
|
|
2929
|
+
] })
|
|
2930
|
+
] }),
|
|
2931
|
+
/* @__PURE__ */ jsxs2(View2, { style: s.bottomRow, children: [
|
|
2932
|
+
/* @__PURE__ */ jsx3(
|
|
2933
|
+
TouchableOpacity2,
|
|
2934
|
+
{
|
|
2935
|
+
style: [s.secondaryBtn, { borderColor: t.border }],
|
|
2936
|
+
onPress: onComplete,
|
|
2937
|
+
activeOpacity: 0.7,
|
|
2938
|
+
children: /* @__PURE__ */ jsx3(Text2, { style: [s.secondaryBtnText, { color: t.textMuted }], children: "Maybe Later" })
|
|
2939
|
+
}
|
|
2940
|
+
),
|
|
2941
|
+
/* @__PURE__ */ jsx3(
|
|
2942
|
+
TouchableOpacity2,
|
|
2943
|
+
{
|
|
2944
|
+
style: [s.primaryBtn, { backgroundColor: accent, flex: 1, opacity: push.loading ? 0.7 : 1 }],
|
|
2945
|
+
onPress: handleEnable,
|
|
2946
|
+
disabled: push.loading,
|
|
2947
|
+
activeOpacity: 0.8,
|
|
2948
|
+
children: push.loading ? /* @__PURE__ */ jsx3(ActivityIndicator2, { color: "#FFFFFF", size: "small" }) : /* @__PURE__ */ jsx3(Text2, { style: s.primaryBtnText, children: "Enable Notifications" })
|
|
2949
|
+
}
|
|
2950
|
+
)
|
|
2951
|
+
] })
|
|
2952
|
+
]
|
|
2953
|
+
}
|
|
2954
|
+
) });
|
|
2955
|
+
}
|
|
2956
|
+
var pushStyles = StyleSheet2.create({
|
|
2957
|
+
iconContainer: { alignItems: "center", marginVertical: 24 },
|
|
2958
|
+
bellCircle: { width: 100, height: 100, borderRadius: 50, justifyContent: "center", alignItems: "center" },
|
|
2959
|
+
bellIcon: { fontSize: 48 },
|
|
2960
|
+
benefitsList: { paddingHorizontal: 24, gap: 12, marginTop: 8 },
|
|
2961
|
+
benefitsHeader: { fontSize: 17, fontWeight: "700", marginBottom: 4 },
|
|
2962
|
+
benefitRow: { flexDirection: "row", alignItems: "center", gap: 12 },
|
|
2963
|
+
bulletDot: { width: 8, height: 8, borderRadius: 4 },
|
|
2964
|
+
benefitText: { fontSize: 16, flex: 1 }
|
|
2965
|
+
});
|
|
2719
2966
|
var s = StyleSheet2.create({
|
|
2720
2967
|
container: { flex: 1 },
|
|
2721
2968
|
// Loading / Error
|
|
@@ -2803,10 +3050,10 @@ function DubsProvider({
|
|
|
2803
3050
|
const baseUrl = baseUrlOverride || config.baseUrl;
|
|
2804
3051
|
const rpcUrl = rpcUrlOverride || config.rpcUrl;
|
|
2805
3052
|
const cluster = config.cluster;
|
|
2806
|
-
const client =
|
|
2807
|
-
const connection =
|
|
2808
|
-
const storage =
|
|
2809
|
-
const [uiConfig, setUiConfig] =
|
|
3053
|
+
const client = useMemo2(() => new DubsClient({ apiKey, baseUrl }), [apiKey, baseUrl]);
|
|
3054
|
+
const connection = useMemo2(() => new Connection2(rpcUrl, { commitment: "confirmed" }), [rpcUrl]);
|
|
3055
|
+
const storage = useMemo2(() => tokenStorage || createSecureStoreStorage(), [tokenStorage]);
|
|
3056
|
+
const [uiConfig, setUiConfig] = useState16(null);
|
|
2810
3057
|
useEffect10(() => {
|
|
2811
3058
|
client.getAppConfig().then((config2) => {
|
|
2812
3059
|
console.log("[DubsProvider] UI config loaded:", JSON.stringify(config2));
|
|
@@ -2888,11 +3135,11 @@ function ManagedInner({
|
|
|
2888
3135
|
children
|
|
2889
3136
|
}) {
|
|
2890
3137
|
const managedDisconnect = useDisconnect();
|
|
2891
|
-
const disconnect =
|
|
3138
|
+
const disconnect = useCallback15(async () => {
|
|
2892
3139
|
client.setToken(null);
|
|
2893
3140
|
await managedDisconnect?.();
|
|
2894
3141
|
}, [client, managedDisconnect]);
|
|
2895
|
-
const value =
|
|
3142
|
+
const value = useMemo2(
|
|
2896
3143
|
() => ({ client, wallet, connection, appName, network, disconnect, uiConfig }),
|
|
2897
3144
|
[client, wallet, connection, appName, network, disconnect, uiConfig]
|
|
2898
3145
|
);
|
|
@@ -2928,13 +3175,13 @@ function ExternalWalletProvider({
|
|
|
2928
3175
|
uiConfig,
|
|
2929
3176
|
children
|
|
2930
3177
|
}) {
|
|
2931
|
-
const disconnect =
|
|
3178
|
+
const disconnect = useCallback15(async () => {
|
|
2932
3179
|
client.setToken(null);
|
|
2933
3180
|
await storage.deleteItem(STORAGE_KEYS.JWT_TOKEN).catch(() => {
|
|
2934
3181
|
});
|
|
2935
3182
|
await wallet.disconnect?.();
|
|
2936
3183
|
}, [client, storage, wallet]);
|
|
2937
|
-
const value =
|
|
3184
|
+
const value = useMemo2(
|
|
2938
3185
|
() => ({ client, wallet, connection, appName, network, disconnect, uiConfig }),
|
|
2939
3186
|
[client, wallet, connection, appName, network, disconnect, uiConfig]
|
|
2940
3187
|
);
|
|
@@ -2971,7 +3218,7 @@ function useAppConfig() {
|
|
|
2971
3218
|
}
|
|
2972
3219
|
|
|
2973
3220
|
// src/ui/UserProfileCard.tsx
|
|
2974
|
-
import { useMemo as
|
|
3221
|
+
import { useMemo as useMemo3 } from "react";
|
|
2975
3222
|
import { View as View3, Text as Text3, Image as Image3, StyleSheet as StyleSheet3 } from "react-native";
|
|
2976
3223
|
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2977
3224
|
function truncateAddress(address, chars = 4) {
|
|
@@ -2991,7 +3238,7 @@ function UserProfileCard({
|
|
|
2991
3238
|
memberSince
|
|
2992
3239
|
}) {
|
|
2993
3240
|
const t = useDubsTheme();
|
|
2994
|
-
const imageUri =
|
|
3241
|
+
const imageUri = useMemo3(
|
|
2995
3242
|
() => avatarUrl || `https://api.dicebear.com/9.x/avataaars/png?seed=${walletAddress}&size=128`,
|
|
2996
3243
|
[avatarUrl, walletAddress]
|
|
2997
3244
|
);
|
|
@@ -3191,7 +3438,7 @@ var styles3 = StyleSheet4.create({
|
|
|
3191
3438
|
});
|
|
3192
3439
|
|
|
3193
3440
|
// src/ui/game/GamePoster.tsx
|
|
3194
|
-
import { useState as
|
|
3441
|
+
import { useState as useState17 } from "react";
|
|
3195
3442
|
import { StyleSheet as StyleSheet5, View as View5, Text as Text5 } from "react-native";
|
|
3196
3443
|
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
3197
3444
|
function computeCountdown(lockTimestamp) {
|
|
@@ -3241,7 +3488,7 @@ function GamePoster({ game, ImageComponent }) {
|
|
|
3241
3488
|
] });
|
|
3242
3489
|
}
|
|
3243
3490
|
function TeamLogoInternal({ url, size, Img }) {
|
|
3244
|
-
const [failed, setFailed] =
|
|
3491
|
+
const [failed, setFailed] = useState17(false);
|
|
3245
3492
|
if (!url || failed) {
|
|
3246
3493
|
return /* @__PURE__ */ jsx7(View5, { style: [styles4.logoPlaceholder, { width: size, height: size, borderRadius: size / 2 }] });
|
|
3247
3494
|
}
|
|
@@ -3342,7 +3589,7 @@ var styles4 = StyleSheet5.create({
|
|
|
3342
3589
|
});
|
|
3343
3590
|
|
|
3344
3591
|
// src/ui/game/LivePoolsCard.tsx
|
|
3345
|
-
import { useMemo as
|
|
3592
|
+
import { useMemo as useMemo4 } from "react";
|
|
3346
3593
|
import { StyleSheet as StyleSheet6, View as View6, Text as Text6 } from "react-native";
|
|
3347
3594
|
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3348
3595
|
function LivePoolsCard({
|
|
@@ -3358,7 +3605,7 @@ function LivePoolsCard({
|
|
|
3358
3605
|
const homePool = game.homePool || 0;
|
|
3359
3606
|
const awayPool = game.awayPool || 0;
|
|
3360
3607
|
const totalPool = game.totalPool || 0;
|
|
3361
|
-
const { homePercent, awayPercent, homeOdds, awayOdds } =
|
|
3608
|
+
const { homePercent, awayPercent, homeOdds, awayOdds } = useMemo4(() => {
|
|
3362
3609
|
return {
|
|
3363
3610
|
homePercent: totalPool > 0 ? homePool / totalPool * 100 : 50,
|
|
3364
3611
|
awayPercent: totalPool > 0 ? awayPool / totalPool * 100 : 50,
|
|
@@ -3421,7 +3668,7 @@ var styles5 = StyleSheet6.create({
|
|
|
3421
3668
|
});
|
|
3422
3669
|
|
|
3423
3670
|
// src/ui/game/PickWinnerCard.tsx
|
|
3424
|
-
import { useState as
|
|
3671
|
+
import { useState as useState18, useMemo as useMemo5 } from "react";
|
|
3425
3672
|
import { StyleSheet as StyleSheet7, View as View7, Text as Text7, TouchableOpacity as TouchableOpacity4 } from "react-native";
|
|
3426
3673
|
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3427
3674
|
function PickWinnerCard({
|
|
@@ -3439,7 +3686,7 @@ function PickWinnerCard({
|
|
|
3439
3686
|
const totalPool = game.totalPool || 0;
|
|
3440
3687
|
const homePool = game.homePool || 0;
|
|
3441
3688
|
const awayPool = game.awayPool || 0;
|
|
3442
|
-
const { homeOdds, awayOdds, homeBets, awayBets } =
|
|
3689
|
+
const { homeOdds, awayOdds, homeBets, awayBets } = useMemo5(() => ({
|
|
3443
3690
|
homeOdds: homePool > 0 ? (totalPool / homePool).toFixed(2) : "\u2014",
|
|
3444
3691
|
awayOdds: awayPool > 0 ? (totalPool / awayPool).toFixed(2) : "\u2014",
|
|
3445
3692
|
homeBets: bettors.filter((b) => b.team === "home").length,
|
|
@@ -3492,7 +3739,7 @@ function TeamOption({
|
|
|
3492
3739
|
ImageComponent,
|
|
3493
3740
|
t
|
|
3494
3741
|
}) {
|
|
3495
|
-
const [imgFailed, setImgFailed] =
|
|
3742
|
+
const [imgFailed, setImgFailed] = useState18(false);
|
|
3496
3743
|
const Img = ImageComponent || __require("react-native").Image;
|
|
3497
3744
|
const showImage = imageUrl && !imgFailed;
|
|
3498
3745
|
return /* @__PURE__ */ jsxs7(
|
|
@@ -3533,7 +3780,7 @@ var styles6 = StyleSheet7.create({
|
|
|
3533
3780
|
});
|
|
3534
3781
|
|
|
3535
3782
|
// src/ui/game/PlayersCard.tsx
|
|
3536
|
-
import { useState as
|
|
3783
|
+
import { useState as useState19 } from "react";
|
|
3537
3784
|
import { StyleSheet as StyleSheet8, View as View8, Text as Text8 } from "react-native";
|
|
3538
3785
|
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3539
3786
|
function truncateWallet(addr, chars) {
|
|
@@ -3582,7 +3829,7 @@ function BettorRow({
|
|
|
3582
3829
|
ImageComponent,
|
|
3583
3830
|
t
|
|
3584
3831
|
}) {
|
|
3585
|
-
const [imgFailed, setImgFailed] =
|
|
3832
|
+
const [imgFailed, setImgFailed] = useState19(false);
|
|
3586
3833
|
const Img = ImageComponent || __require("react-native").Image;
|
|
3587
3834
|
const showAvatar = bettor.avatar && !imgFailed;
|
|
3588
3835
|
return /* @__PURE__ */ jsxs8(View8, { style: [styles7.row, !isFirst && { borderTopColor: t.border, borderTopWidth: 1 }], children: [
|
|
@@ -3609,7 +3856,7 @@ var styles7 = StyleSheet8.create({
|
|
|
3609
3856
|
});
|
|
3610
3857
|
|
|
3611
3858
|
// src/ui/game/JoinGameButton.tsx
|
|
3612
|
-
import { useMemo as
|
|
3859
|
+
import { useMemo as useMemo6 } from "react";
|
|
3613
3860
|
import { StyleSheet as StyleSheet9, View as View9, Text as Text9, TouchableOpacity as TouchableOpacity5, ActivityIndicator as ActivityIndicator4 } from "react-native";
|
|
3614
3861
|
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3615
3862
|
var STATUS_LABELS = {
|
|
@@ -3620,7 +3867,7 @@ var STATUS_LABELS = {
|
|
|
3620
3867
|
};
|
|
3621
3868
|
function JoinGameButton({ game, walletAddress, selectedTeam, status, onJoin }) {
|
|
3622
3869
|
const t = useDubsTheme();
|
|
3623
|
-
const alreadyJoined =
|
|
3870
|
+
const alreadyJoined = useMemo6(() => {
|
|
3624
3871
|
if (!walletAddress) return false;
|
|
3625
3872
|
return (game.bettors || []).some((b) => b.wallet === walletAddress);
|
|
3626
3873
|
}, [game.bettors, walletAddress]);
|
|
@@ -3661,7 +3908,7 @@ var styles8 = StyleSheet9.create({
|
|
|
3661
3908
|
});
|
|
3662
3909
|
|
|
3663
3910
|
// src/ui/game/CreateCustomGameSheet.tsx
|
|
3664
|
-
import { useState as
|
|
3911
|
+
import { useState as useState20, useEffect as useEffect11, useRef as useRef5, useCallback as useCallback16 } from "react";
|
|
3665
3912
|
import {
|
|
3666
3913
|
View as View10,
|
|
3667
3914
|
Text as Text10,
|
|
@@ -3672,7 +3919,7 @@ import {
|
|
|
3672
3919
|
Animated as Animated2,
|
|
3673
3920
|
StyleSheet as StyleSheet10,
|
|
3674
3921
|
KeyboardAvoidingView as KeyboardAvoidingView2,
|
|
3675
|
-
Platform as
|
|
3922
|
+
Platform as Platform5
|
|
3676
3923
|
} from "react-native";
|
|
3677
3924
|
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3678
3925
|
var STATUS_LABELS2 = {
|
|
@@ -3698,10 +3945,10 @@ function CreateCustomGameSheet({
|
|
|
3698
3945
|
const t = useDubsTheme();
|
|
3699
3946
|
const { wallet } = useDubs();
|
|
3700
3947
|
const mutation = useCreateCustomGame();
|
|
3701
|
-
const [selectedAmount, setSelectedAmount] =
|
|
3702
|
-
const [customAmount, setCustomAmount] =
|
|
3703
|
-
const [isCustom, setIsCustom] =
|
|
3704
|
-
const overlayOpacity =
|
|
3948
|
+
const [selectedAmount, setSelectedAmount] = useState20(null);
|
|
3949
|
+
const [customAmount, setCustomAmount] = useState20("");
|
|
3950
|
+
const [isCustom, setIsCustom] = useState20(false);
|
|
3951
|
+
const overlayOpacity = useRef5(new Animated2.Value(0)).current;
|
|
3705
3952
|
useEffect11(() => {
|
|
3706
3953
|
Animated2.timing(overlayOpacity, {
|
|
3707
3954
|
toValue: visible ? 1 : 0,
|
|
@@ -3731,18 +3978,18 @@ function CreateCustomGameSheet({
|
|
|
3731
3978
|
onError?.(mutation.error);
|
|
3732
3979
|
}
|
|
3733
3980
|
}, [mutation.status, mutation.error]);
|
|
3734
|
-
const handlePresetSelect =
|
|
3981
|
+
const handlePresetSelect = useCallback16((amount) => {
|
|
3735
3982
|
setSelectedAmount(amount);
|
|
3736
3983
|
setIsCustom(false);
|
|
3737
3984
|
setCustomAmount("");
|
|
3738
3985
|
onAmountChange?.(amount);
|
|
3739
3986
|
}, [onAmountChange]);
|
|
3740
|
-
const handleCustomSelect =
|
|
3987
|
+
const handleCustomSelect = useCallback16(() => {
|
|
3741
3988
|
setIsCustom(true);
|
|
3742
3989
|
setSelectedAmount(null);
|
|
3743
3990
|
onAmountChange?.(null);
|
|
3744
3991
|
}, [onAmountChange]);
|
|
3745
|
-
const handleCustomAmountChange =
|
|
3992
|
+
const handleCustomAmountChange = useCallback16((text) => {
|
|
3746
3993
|
const cleaned = text.replace(/[^0-9.]/g, "").replace(/(\..*?)\..*/g, "$1");
|
|
3747
3994
|
setCustomAmount(cleaned);
|
|
3748
3995
|
const parsed = parseFloat(cleaned);
|
|
@@ -3757,7 +4004,7 @@ function CreateCustomGameSheet({
|
|
|
3757
4004
|
const winnerTakes = pot * (1 - fee / 100);
|
|
3758
4005
|
const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
|
|
3759
4006
|
const canCreate = finalAmount !== null && finalAmount > 0 && !isMutating && mutation.status !== "success";
|
|
3760
|
-
const handleCreate =
|
|
4007
|
+
const handleCreate = useCallback16(async () => {
|
|
3761
4008
|
if (!finalAmount || !wallet.publicKey) return;
|
|
3762
4009
|
try {
|
|
3763
4010
|
await mutation.execute({
|
|
@@ -3786,7 +4033,7 @@ function CreateCustomGameSheet({
|
|
|
3786
4033
|
KeyboardAvoidingView2,
|
|
3787
4034
|
{
|
|
3788
4035
|
style: styles9.keyboardView,
|
|
3789
|
-
behavior:
|
|
4036
|
+
behavior: Platform5.OS === "ios" ? "padding" : void 0,
|
|
3790
4037
|
children: /* @__PURE__ */ jsx12(View10, { style: styles9.sheetPositioner, children: /* @__PURE__ */ jsxs10(View10, { style: [styles9.sheet, { backgroundColor: t.background }], children: [
|
|
3791
4038
|
/* @__PURE__ */ jsx12(View10, { style: styles9.handleRow, children: /* @__PURE__ */ jsx12(View10, { style: [styles9.handle, { backgroundColor: t.textMuted }] }) }),
|
|
3792
4039
|
/* @__PURE__ */ jsxs10(View10, { style: styles9.header, children: [
|
|
@@ -4026,7 +4273,7 @@ var styles9 = StyleSheet10.create({
|
|
|
4026
4273
|
});
|
|
4027
4274
|
|
|
4028
4275
|
// src/ui/game/JoinGameSheet.tsx
|
|
4029
|
-
import { useState as
|
|
4276
|
+
import { useState as useState21, useEffect as useEffect12, useRef as useRef6, useCallback as useCallback17, useMemo as useMemo7 } from "react";
|
|
4030
4277
|
import {
|
|
4031
4278
|
View as View11,
|
|
4032
4279
|
Text as Text11,
|
|
@@ -4036,7 +4283,7 @@ import {
|
|
|
4036
4283
|
Animated as Animated3,
|
|
4037
4284
|
StyleSheet as StyleSheet11,
|
|
4038
4285
|
KeyboardAvoidingView as KeyboardAvoidingView3,
|
|
4039
|
-
Platform as
|
|
4286
|
+
Platform as Platform6
|
|
4040
4287
|
} from "react-native";
|
|
4041
4288
|
import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
4042
4289
|
var STATUS_LABELS3 = {
|
|
@@ -4062,8 +4309,8 @@ function JoinGameSheet({
|
|
|
4062
4309
|
const { wallet } = useDubs();
|
|
4063
4310
|
const mutation = useJoinGame();
|
|
4064
4311
|
const isCustomGame = game.gameMode === CUSTOM_GAME_MODE;
|
|
4065
|
-
const [selectedTeam, setSelectedTeam] =
|
|
4066
|
-
const overlayOpacity =
|
|
4312
|
+
const [selectedTeam, setSelectedTeam] = useState21(null);
|
|
4313
|
+
const overlayOpacity = useRef6(new Animated3.Value(0)).current;
|
|
4067
4314
|
useEffect12(() => {
|
|
4068
4315
|
Animated3.timing(overlayOpacity, {
|
|
4069
4316
|
toValue: visible ? 1 : 0,
|
|
@@ -4097,7 +4344,7 @@ function JoinGameSheet({
|
|
|
4097
4344
|
const homePool = game.homePool || 0;
|
|
4098
4345
|
const awayPool = game.awayPool || 0;
|
|
4099
4346
|
const buyIn = game.buyIn;
|
|
4100
|
-
const { homeOdds, awayOdds, homeBets, awayBets } =
|
|
4347
|
+
const { homeOdds, awayOdds, homeBets, awayBets } = useMemo7(() => ({
|
|
4101
4348
|
homeOdds: homePool > 0 ? (totalPool / homePool).toFixed(2) : "\u2014",
|
|
4102
4349
|
awayOdds: awayPool > 0 ? (totalPool / awayPool).toFixed(2) : "\u2014",
|
|
4103
4350
|
homeBets: bettors.filter((b) => b.team === "home").length,
|
|
@@ -4109,14 +4356,14 @@ function JoinGameSheet({
|
|
|
4109
4356
|
const homeName = shortName ? shortName(opponents[0]?.name) : opponents[0]?.name || "Home";
|
|
4110
4357
|
const awayName = shortName ? shortName(opponents[1]?.name) : opponents[1]?.name || "Away";
|
|
4111
4358
|
const selectedName = selectedTeam === "home" ? homeName : selectedTeam === "away" ? awayName : "\u2014";
|
|
4112
|
-
const alreadyJoined =
|
|
4359
|
+
const alreadyJoined = useMemo7(() => {
|
|
4113
4360
|
if (!wallet.publicKey) return false;
|
|
4114
4361
|
const addr = wallet.publicKey.toBase58();
|
|
4115
4362
|
return bettors.some((b) => b.wallet === addr);
|
|
4116
4363
|
}, [bettors, wallet.publicKey]);
|
|
4117
4364
|
const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
|
|
4118
4365
|
const canJoin = selectedTeam !== null && !isMutating && mutation.status !== "success" && !alreadyJoined;
|
|
4119
|
-
const handleJoin =
|
|
4366
|
+
const handleJoin = useCallback17(async () => {
|
|
4120
4367
|
if (!selectedTeam || !wallet.publicKey) return;
|
|
4121
4368
|
try {
|
|
4122
4369
|
await mutation.execute({
|
|
@@ -4142,7 +4389,7 @@ function JoinGameSheet({
|
|
|
4142
4389
|
KeyboardAvoidingView3,
|
|
4143
4390
|
{
|
|
4144
4391
|
style: styles10.keyboardView,
|
|
4145
|
-
behavior:
|
|
4392
|
+
behavior: Platform6.OS === "ios" ? "padding" : void 0,
|
|
4146
4393
|
children: /* @__PURE__ */ jsx13(View11, { style: styles10.sheetPositioner, children: /* @__PURE__ */ jsxs11(View11, { style: [styles10.sheet, { backgroundColor: t.background }], children: [
|
|
4147
4394
|
/* @__PURE__ */ jsx13(View11, { style: styles10.handleRow, children: /* @__PURE__ */ jsx13(View11, { style: [styles10.handle, { backgroundColor: t.textMuted }] }) }),
|
|
4148
4395
|
/* @__PURE__ */ jsxs11(View11, { style: styles10.header, children: [
|
|
@@ -4260,7 +4507,7 @@ function TeamButton({
|
|
|
4260
4507
|
ImageComponent,
|
|
4261
4508
|
t
|
|
4262
4509
|
}) {
|
|
4263
|
-
const [imgFailed, setImgFailed] =
|
|
4510
|
+
const [imgFailed, setImgFailed] = useState21(false);
|
|
4264
4511
|
const Img = ImageComponent || __require("react-native").Image;
|
|
4265
4512
|
const showImage = imageUrl && !imgFailed;
|
|
4266
4513
|
return /* @__PURE__ */ jsxs11(
|
|
@@ -4437,7 +4684,7 @@ var styles10 = StyleSheet11.create({
|
|
|
4437
4684
|
});
|
|
4438
4685
|
|
|
4439
4686
|
// src/ui/game/ClaimPrizeSheet.tsx
|
|
4440
|
-
import { useState as
|
|
4687
|
+
import { useState as useState22, useEffect as useEffect13, useRef as useRef7, useCallback as useCallback18 } from "react";
|
|
4441
4688
|
import {
|
|
4442
4689
|
View as View12,
|
|
4443
4690
|
Text as Text12,
|
|
@@ -4447,7 +4694,7 @@ import {
|
|
|
4447
4694
|
Animated as Animated4,
|
|
4448
4695
|
StyleSheet as StyleSheet12,
|
|
4449
4696
|
KeyboardAvoidingView as KeyboardAvoidingView4,
|
|
4450
|
-
Platform as
|
|
4697
|
+
Platform as Platform7
|
|
4451
4698
|
} from "react-native";
|
|
4452
4699
|
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
4453
4700
|
var STATUS_LABELS4 = {
|
|
@@ -4468,10 +4715,10 @@ function ClaimPrizeSheet({
|
|
|
4468
4715
|
const t = useDubsTheme();
|
|
4469
4716
|
const { wallet } = useDubs();
|
|
4470
4717
|
const mutation = useClaim();
|
|
4471
|
-
const overlayOpacity =
|
|
4472
|
-
const celebrationScale =
|
|
4473
|
-
const celebrationOpacity =
|
|
4474
|
-
const [showCelebration, setShowCelebration] =
|
|
4718
|
+
const overlayOpacity = useRef7(new Animated4.Value(0)).current;
|
|
4719
|
+
const celebrationScale = useRef7(new Animated4.Value(0)).current;
|
|
4720
|
+
const celebrationOpacity = useRef7(new Animated4.Value(0)).current;
|
|
4721
|
+
const [showCelebration, setShowCelebration] = useState22(false);
|
|
4475
4722
|
useEffect13(() => {
|
|
4476
4723
|
Animated4.timing(overlayOpacity, {
|
|
4477
4724
|
toValue: visible ? 1 : 0,
|
|
@@ -4517,7 +4764,7 @@ function ClaimPrizeSheet({
|
|
|
4517
4764
|
}, [mutation.status, mutation.error]);
|
|
4518
4765
|
const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
|
|
4519
4766
|
const canClaim = !isMutating && mutation.status !== "success" && !!wallet.publicKey;
|
|
4520
|
-
const handleClaim =
|
|
4767
|
+
const handleClaim = useCallback18(async () => {
|
|
4521
4768
|
if (!wallet.publicKey) return;
|
|
4522
4769
|
try {
|
|
4523
4770
|
await mutation.execute({
|
|
@@ -4542,7 +4789,7 @@ function ClaimPrizeSheet({
|
|
|
4542
4789
|
KeyboardAvoidingView4,
|
|
4543
4790
|
{
|
|
4544
4791
|
style: styles11.keyboardView,
|
|
4545
|
-
behavior:
|
|
4792
|
+
behavior: Platform7.OS === "ios" ? "padding" : void 0,
|
|
4546
4793
|
children: /* @__PURE__ */ jsx14(View12, { style: styles11.sheetPositioner, children: /* @__PURE__ */ jsxs12(View12, { style: [styles11.sheet, { backgroundColor: t.background }], children: [
|
|
4547
4794
|
/* @__PURE__ */ jsx14(View12, { style: styles11.handleRow, children: /* @__PURE__ */ jsx14(View12, { style: [styles11.handle, { backgroundColor: t.textMuted }] }) }),
|
|
4548
4795
|
/* @__PURE__ */ jsxs12(View12, { style: styles11.header, children: [
|
|
@@ -4750,7 +4997,7 @@ var styles11 = StyleSheet12.create({
|
|
|
4750
4997
|
});
|
|
4751
4998
|
|
|
4752
4999
|
// src/ui/game/ClaimButton.tsx
|
|
4753
|
-
import { useState as
|
|
5000
|
+
import { useState as useState23, useMemo as useMemo8, useCallback as useCallback19 } from "react";
|
|
4754
5001
|
import { StyleSheet as StyleSheet13, Text as Text13, TouchableOpacity as TouchableOpacity9 } from "react-native";
|
|
4755
5002
|
import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
4756
5003
|
function ClaimButton({ gameId, style, onSuccess, onError }) {
|
|
@@ -4758,9 +5005,9 @@ function ClaimButton({ gameId, style, onSuccess, onError }) {
|
|
|
4758
5005
|
const { wallet } = useDubs();
|
|
4759
5006
|
const game = useGame(gameId);
|
|
4760
5007
|
const claimStatus = useHasClaimed(gameId);
|
|
4761
|
-
const [sheetVisible, setSheetVisible] =
|
|
5008
|
+
const [sheetVisible, setSheetVisible] = useState23(false);
|
|
4762
5009
|
const walletAddress = wallet.publicKey?.toBase58() ?? null;
|
|
4763
|
-
const myBet =
|
|
5010
|
+
const myBet = useMemo8(() => {
|
|
4764
5011
|
if (!walletAddress || !game.data?.bettors) return null;
|
|
4765
5012
|
return game.data.bettors.find((b) => b.wallet === walletAddress) ?? null;
|
|
4766
5013
|
}, [walletAddress, game.data?.bettors]);
|
|
@@ -4769,7 +5016,7 @@ function ClaimButton({ gameId, style, onSuccess, onError }) {
|
|
|
4769
5016
|
const isWinner = isResolved && myBet != null && myBet.team === game.data?.winnerSide;
|
|
4770
5017
|
const isEligible = myBet != null && isResolved && (isWinner || isRefund);
|
|
4771
5018
|
const prizeAmount = isRefund ? myBet?.amount ?? 0 : game.data?.totalPool ?? 0;
|
|
4772
|
-
const handleSuccess =
|
|
5019
|
+
const handleSuccess = useCallback19(
|
|
4773
5020
|
(result) => {
|
|
4774
5021
|
claimStatus.refetch();
|
|
4775
5022
|
onSuccess?.(result);
|
|
@@ -4897,6 +5144,7 @@ export {
|
|
|
4897
5144
|
useHasClaimed,
|
|
4898
5145
|
useJoinGame,
|
|
4899
5146
|
useNetworkGames,
|
|
5147
|
+
usePushNotifications,
|
|
4900
5148
|
useUFCFightCard,
|
|
4901
5149
|
useUFCFighterDetail
|
|
4902
5150
|
};
|