@dubsdotapp/expo 0.5.16 → 0.5.18
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 +2081 -0
- package/dist/index.d.ts +2081 -0
- package/dist/index.js +2102 -170
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2052 -123
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -4
- package/src/chat/hooks.ts +320 -0
- package/src/chat/index.ts +40 -0
- package/src/chat/provider.tsx +213 -0
- package/src/chat/socket.ts +175 -0
- package/src/chat/types.ts +146 -0
- package/src/client.ts +182 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/useEnterJackpot.ts +80 -0
- package/src/hooks/useJackpot.ts +37 -0
- package/src/hooks/useJackpotHistory.ts +34 -0
- package/src/index.ts +55 -0
- package/src/types.ts +60 -0
- package/src/ui/game/JoinGameSheet.tsx +173 -16
- package/src/ui/index.ts +4 -0
- package/src/ui/jackpot/JackpotCard.tsx +417 -0
- package/src/ui/jackpot/JackpotSheet.tsx +683 -0
- package/src/ui/jackpot/JackpotWidget.tsx +74 -0
- package/src/ui/jackpot/index.ts +6 -0
package/dist/index.mjs
CHANGED
|
@@ -594,6 +594,151 @@ var DubsClient = class {
|
|
|
594
594
|
);
|
|
595
595
|
return res.entry;
|
|
596
596
|
}
|
|
597
|
+
// ── Jackpot ──
|
|
598
|
+
/** Get current jackpot round + last winner */
|
|
599
|
+
async getJackpotCurrent() {
|
|
600
|
+
const res = await this.request(
|
|
601
|
+
"GET",
|
|
602
|
+
"/jackpot/current"
|
|
603
|
+
);
|
|
604
|
+
return { round: res.round, lastWinner: res.lastWinner };
|
|
605
|
+
}
|
|
606
|
+
/** Get current round entries with odds */
|
|
607
|
+
async getJackpotEntries() {
|
|
608
|
+
const res = await this.request(
|
|
609
|
+
"GET",
|
|
610
|
+
"/jackpot/entries"
|
|
611
|
+
);
|
|
612
|
+
return { roundId: res.roundId, entries: res.entries, totalEntries: res.totalEntries };
|
|
613
|
+
}
|
|
614
|
+
/** Get recent jackpot round results */
|
|
615
|
+
async getJackpotHistory(limit) {
|
|
616
|
+
const qs = limit ? `?limit=${limit}` : "";
|
|
617
|
+
const res = await this.request(
|
|
618
|
+
"GET",
|
|
619
|
+
`/jackpot/history${qs}`
|
|
620
|
+
);
|
|
621
|
+
return res.rounds;
|
|
622
|
+
}
|
|
623
|
+
/** Get jackpot protocol config */
|
|
624
|
+
async getJackpotConfig() {
|
|
625
|
+
const res = await this.request(
|
|
626
|
+
"GET",
|
|
627
|
+
"/jackpot/config"
|
|
628
|
+
);
|
|
629
|
+
return res.config;
|
|
630
|
+
}
|
|
631
|
+
/** Build unsigned jackpot enter transaction */
|
|
632
|
+
async buildJackpotEnter(playerAddress, amount) {
|
|
633
|
+
const res = await this.request(
|
|
634
|
+
"POST",
|
|
635
|
+
"/jackpot/build-enter",
|
|
636
|
+
{ playerAddress, amount }
|
|
637
|
+
);
|
|
638
|
+
return { transaction: res.transaction, roundId: res.roundId, amount: res.amount, amountSol: res.amountSol };
|
|
639
|
+
}
|
|
640
|
+
/** Confirm jackpot entry after wallet signs (creates developer attribution) */
|
|
641
|
+
async confirmJackpotEnter(params) {
|
|
642
|
+
const res = await this.request(
|
|
643
|
+
"POST",
|
|
644
|
+
"/jackpot/confirm-enter",
|
|
645
|
+
params
|
|
646
|
+
);
|
|
647
|
+
return { attributed: res.attributed, appId: res.appId, signature: res.signature };
|
|
648
|
+
}
|
|
649
|
+
// ── Chat ──
|
|
650
|
+
/** Get recent global chat messages */
|
|
651
|
+
async getChatMessages(params) {
|
|
652
|
+
const qs = new URLSearchParams();
|
|
653
|
+
if (params?.limit) qs.set("limit", String(params.limit));
|
|
654
|
+
if (params?.before) qs.set("before", String(params.before));
|
|
655
|
+
const query = qs.toString();
|
|
656
|
+
return this.request("GET", `/chat/messages${query ? `?${query}` : ""}`);
|
|
657
|
+
}
|
|
658
|
+
/** Send a message to global chat */
|
|
659
|
+
async sendChatMessage(params) {
|
|
660
|
+
return this.request("POST", "/chat/message", params);
|
|
661
|
+
}
|
|
662
|
+
/** Edit your own message */
|
|
663
|
+
async editChatMessage(id, message) {
|
|
664
|
+
return this.request("PUT", `/chat/message/${id}`, { message });
|
|
665
|
+
}
|
|
666
|
+
/** Delete your own message */
|
|
667
|
+
async deleteChatMessage(id) {
|
|
668
|
+
return this.request("DELETE", `/chat/message/${id}`);
|
|
669
|
+
}
|
|
670
|
+
/** Block a user */
|
|
671
|
+
async blockUser(targetUserId) {
|
|
672
|
+
await this.request("POST", `/chat/block/${targetUserId}`);
|
|
673
|
+
}
|
|
674
|
+
/** Unblock a user */
|
|
675
|
+
async unblockUser(targetUserId) {
|
|
676
|
+
await this.request("DELETE", `/chat/block/${targetUserId}`);
|
|
677
|
+
}
|
|
678
|
+
// ── DMs ──
|
|
679
|
+
/** Get DM conversations inbox */
|
|
680
|
+
async getConversations(limit) {
|
|
681
|
+
const qs = limit ? `?limit=${limit}` : "";
|
|
682
|
+
return this.request("GET", `/dm/conversations${qs}`);
|
|
683
|
+
}
|
|
684
|
+
/** Get conversation history with a specific user */
|
|
685
|
+
async getConversation(walletAddress, params) {
|
|
686
|
+
const qs = new URLSearchParams();
|
|
687
|
+
if (params?.limit) qs.set("limit", String(params.limit));
|
|
688
|
+
if (params?.beforeId) qs.set("beforeId", String(params.beforeId));
|
|
689
|
+
const query = qs.toString();
|
|
690
|
+
return this.request("GET", `/dm/conversation/${encodeURIComponent(walletAddress)}${query ? `?${query}` : ""}`);
|
|
691
|
+
}
|
|
692
|
+
/** Send a direct message */
|
|
693
|
+
async sendDirectMessage(params) {
|
|
694
|
+
return this.request("POST", "/dm/send", params);
|
|
695
|
+
}
|
|
696
|
+
/** Mark all DMs from a user as read */
|
|
697
|
+
async markDMRead(walletAddress) {
|
|
698
|
+
return this.request("POST", `/dm/read/${encodeURIComponent(walletAddress)}`);
|
|
699
|
+
}
|
|
700
|
+
/** Get unread DM count */
|
|
701
|
+
async getDMUnreadCount() {
|
|
702
|
+
return this.request("GET", "/dm/unread");
|
|
703
|
+
}
|
|
704
|
+
/** Delete a DM conversation (soft delete) */
|
|
705
|
+
async deleteConversation(walletAddress) {
|
|
706
|
+
await this.request("DELETE", `/dm/conversation/${encodeURIComponent(walletAddress)}`);
|
|
707
|
+
}
|
|
708
|
+
// ── Social ──
|
|
709
|
+
/** Search users by username */
|
|
710
|
+
async searchUsers(query) {
|
|
711
|
+
const qs = query ? `?q=${encodeURIComponent(query)}` : "";
|
|
712
|
+
return this.request("GET", `/social/search${qs}`);
|
|
713
|
+
}
|
|
714
|
+
/** Send a friend request */
|
|
715
|
+
async sendFriendRequest(targetUserId) {
|
|
716
|
+
return this.request("POST", `/social/friend-request/${targetUserId}`);
|
|
717
|
+
}
|
|
718
|
+
/** Get pending friend requests (received) */
|
|
719
|
+
async getPendingFriendRequests() {
|
|
720
|
+
return this.request("GET", "/social/friend-requests");
|
|
721
|
+
}
|
|
722
|
+
/** Accept a friend request */
|
|
723
|
+
async acceptFriendRequest(requestId) {
|
|
724
|
+
await this.request("POST", `/social/request/${requestId}/accept`);
|
|
725
|
+
}
|
|
726
|
+
/** Reject a friend request */
|
|
727
|
+
async rejectFriendRequest(requestId) {
|
|
728
|
+
await this.request("POST", `/social/request/${requestId}/reject`);
|
|
729
|
+
}
|
|
730
|
+
/** Get friends list */
|
|
731
|
+
async getFriends() {
|
|
732
|
+
return this.request("GET", "/social/friends");
|
|
733
|
+
}
|
|
734
|
+
/** Remove a friend */
|
|
735
|
+
async removeFriend(targetUserId) {
|
|
736
|
+
await this.request("DELETE", `/social/friend/${targetUserId}`);
|
|
737
|
+
}
|
|
738
|
+
/** Get blocked users list */
|
|
739
|
+
async getBlockedUsers() {
|
|
740
|
+
return this.request("GET", "/social/blocked");
|
|
741
|
+
}
|
|
597
742
|
// ── App Config ──
|
|
598
743
|
/** Fetch the app's UI customization config (accent color, icon, tagline, environment) */
|
|
599
744
|
async getAppConfig() {
|
|
@@ -645,7 +790,7 @@ function createSecureStoreStorage() {
|
|
|
645
790
|
}
|
|
646
791
|
|
|
647
792
|
// src/provider.tsx
|
|
648
|
-
import { createContext as createContext4, useContext as useContext4, useMemo as useMemo3, useCallback as
|
|
793
|
+
import { createContext as createContext4, useContext as useContext4, useMemo as useMemo3, useCallback as useCallback25, useState as useState27, useEffect as useEffect18 } from "react";
|
|
649
794
|
|
|
650
795
|
// src/ui/theme.ts
|
|
651
796
|
import { createContext, useContext } from "react";
|
|
@@ -1710,7 +1855,7 @@ function ManagedWalletProvider({
|
|
|
1710
1855
|
}
|
|
1711
1856
|
|
|
1712
1857
|
// src/ui/AuthGate.tsx
|
|
1713
|
-
import React2, { useState as
|
|
1858
|
+
import React2, { useState as useState26, useEffect as useEffect17, useRef as useRef6, useCallback as useCallback24 } from "react";
|
|
1714
1859
|
import {
|
|
1715
1860
|
View as View3,
|
|
1716
1861
|
Text as Text3,
|
|
@@ -2934,6 +3079,117 @@ function useArcadeBridge({
|
|
|
2934
3079
|
return { webviewRef, handleMessage, triggerPlay, lastResult, bridgeLoading };
|
|
2935
3080
|
}
|
|
2936
3081
|
|
|
3082
|
+
// src/hooks/useJackpot.ts
|
|
3083
|
+
import { useState as useState23, useEffect as useEffect15, useCallback as useCallback21 } from "react";
|
|
3084
|
+
function useJackpot() {
|
|
3085
|
+
const { client } = useDubs();
|
|
3086
|
+
const [round, setRound] = useState23(null);
|
|
3087
|
+
const [lastWinner, setLastWinner] = useState23(null);
|
|
3088
|
+
const [loading, setLoading] = useState23(false);
|
|
3089
|
+
const [error, setError] = useState23(null);
|
|
3090
|
+
const fetch2 = useCallback21(async () => {
|
|
3091
|
+
setLoading(true);
|
|
3092
|
+
setError(null);
|
|
3093
|
+
try {
|
|
3094
|
+
const result = await client.getJackpotCurrent();
|
|
3095
|
+
setRound(result.round);
|
|
3096
|
+
setLastWinner(result.lastWinner);
|
|
3097
|
+
} catch (err) {
|
|
3098
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
3099
|
+
} finally {
|
|
3100
|
+
setLoading(false);
|
|
3101
|
+
}
|
|
3102
|
+
}, [client]);
|
|
3103
|
+
useEffect15(() => {
|
|
3104
|
+
fetch2();
|
|
3105
|
+
}, [fetch2]);
|
|
3106
|
+
return { round, lastWinner, loading, error, refetch: fetch2 };
|
|
3107
|
+
}
|
|
3108
|
+
|
|
3109
|
+
// src/hooks/useJackpotHistory.ts
|
|
3110
|
+
import { useState as useState24, useEffect as useEffect16, useCallback as useCallback22 } from "react";
|
|
3111
|
+
function useJackpotHistory(limit) {
|
|
3112
|
+
const { client } = useDubs();
|
|
3113
|
+
const [rounds, setRounds] = useState24([]);
|
|
3114
|
+
const [loading, setLoading] = useState24(false);
|
|
3115
|
+
const [error, setError] = useState24(null);
|
|
3116
|
+
const fetch2 = useCallback22(async () => {
|
|
3117
|
+
setLoading(true);
|
|
3118
|
+
setError(null);
|
|
3119
|
+
try {
|
|
3120
|
+
const result = await client.getJackpotHistory(limit);
|
|
3121
|
+
setRounds(result);
|
|
3122
|
+
} catch (err) {
|
|
3123
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
3124
|
+
} finally {
|
|
3125
|
+
setLoading(false);
|
|
3126
|
+
}
|
|
3127
|
+
}, [client, limit]);
|
|
3128
|
+
useEffect16(() => {
|
|
3129
|
+
fetch2();
|
|
3130
|
+
}, [fetch2]);
|
|
3131
|
+
return { rounds, loading, error, refetch: fetch2 };
|
|
3132
|
+
}
|
|
3133
|
+
|
|
3134
|
+
// src/hooks/useEnterJackpot.ts
|
|
3135
|
+
import { useState as useState25, useCallback as useCallback23 } from "react";
|
|
3136
|
+
function useEnterJackpot() {
|
|
3137
|
+
const { client, wallet, connection } = useDubs();
|
|
3138
|
+
const [status, setStatus] = useState25("idle");
|
|
3139
|
+
const [error, setError] = useState25(null);
|
|
3140
|
+
const [data, setData] = useState25(null);
|
|
3141
|
+
const reset = useCallback23(() => {
|
|
3142
|
+
setStatus("idle");
|
|
3143
|
+
setError(null);
|
|
3144
|
+
setData(null);
|
|
3145
|
+
}, []);
|
|
3146
|
+
const execute = useCallback23(async (amountLamports) => {
|
|
3147
|
+
if (!wallet.publicKey) throw new Error("Wallet not connected");
|
|
3148
|
+
const walletAddress = wallet.publicKey.toBase58();
|
|
3149
|
+
setStatus("building");
|
|
3150
|
+
setError(null);
|
|
3151
|
+
setData(null);
|
|
3152
|
+
try {
|
|
3153
|
+
console.log("[useEnterJackpot] Step 1: Building transaction...", { walletAddress, amountLamports });
|
|
3154
|
+
const buildResult = await client.buildJackpotEnter(walletAddress, amountLamports);
|
|
3155
|
+
console.log("[useEnterJackpot] Step 1 done:", { roundId: buildResult.roundId, amount: buildResult.amount });
|
|
3156
|
+
setStatus("signing");
|
|
3157
|
+
console.log("[useEnterJackpot] Step 2: Signing and sending...");
|
|
3158
|
+
const signature = await signAndSendBase64Transaction(
|
|
3159
|
+
buildResult.transaction,
|
|
3160
|
+
wallet,
|
|
3161
|
+
connection
|
|
3162
|
+
);
|
|
3163
|
+
console.log("[useEnterJackpot] Step 2 done. Signature:", signature);
|
|
3164
|
+
setStatus("confirming");
|
|
3165
|
+
console.log("[useEnterJackpot] Step 3: Confirming with backend...");
|
|
3166
|
+
await client.confirmJackpotEnter({
|
|
3167
|
+
playerAddress: walletAddress,
|
|
3168
|
+
roundId: buildResult.roundId,
|
|
3169
|
+
amount: amountLamports,
|
|
3170
|
+
signature
|
|
3171
|
+
});
|
|
3172
|
+
console.log("[useEnterJackpot] Step 3 done. Entry confirmed + attributed.");
|
|
3173
|
+
const result = {
|
|
3174
|
+
roundId: buildResult.roundId,
|
|
3175
|
+
amount: buildResult.amount,
|
|
3176
|
+
amountSol: buildResult.amountSol,
|
|
3177
|
+
signature
|
|
3178
|
+
};
|
|
3179
|
+
setData(result);
|
|
3180
|
+
setStatus("success");
|
|
3181
|
+
return result;
|
|
3182
|
+
} catch (err) {
|
|
3183
|
+
console.error("[useEnterJackpot] FAILED:", err);
|
|
3184
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
3185
|
+
setError(e);
|
|
3186
|
+
setStatus("error");
|
|
3187
|
+
throw e;
|
|
3188
|
+
}
|
|
3189
|
+
}, [client, wallet, connection]);
|
|
3190
|
+
return { execute, status, error, data, reset };
|
|
3191
|
+
}
|
|
3192
|
+
|
|
2937
3193
|
// src/ui/AvatarEditor.tsx
|
|
2938
3194
|
import {
|
|
2939
3195
|
View as View2,
|
|
@@ -3102,11 +3358,11 @@ function AuthGate({
|
|
|
3102
3358
|
}) {
|
|
3103
3359
|
const { client, pushEnabled } = useDubs();
|
|
3104
3360
|
const auth = useAuth();
|
|
3105
|
-
const [phase, setPhase] =
|
|
3106
|
-
const [registrationPhase, setRegistrationPhase] =
|
|
3107
|
-
const [showPushSetup, setShowPushSetup] =
|
|
3108
|
-
const [isRestoredSession, setIsRestoredSession] =
|
|
3109
|
-
|
|
3361
|
+
const [phase, setPhase] = useState26("init");
|
|
3362
|
+
const [registrationPhase, setRegistrationPhase] = useState26(false);
|
|
3363
|
+
const [showPushSetup, setShowPushSetup] = useState26(false);
|
|
3364
|
+
const [isRestoredSession, setIsRestoredSession] = useState26(false);
|
|
3365
|
+
useEffect17(() => {
|
|
3110
3366
|
let cancelled = false;
|
|
3111
3367
|
(async () => {
|
|
3112
3368
|
try {
|
|
@@ -3133,23 +3389,23 @@ function AuthGate({
|
|
|
3133
3389
|
cancelled = true;
|
|
3134
3390
|
};
|
|
3135
3391
|
}, []);
|
|
3136
|
-
|
|
3392
|
+
useEffect17(() => {
|
|
3137
3393
|
if (auth.status === "needsRegistration") setRegistrationPhase(true);
|
|
3138
3394
|
}, [auth.status]);
|
|
3139
|
-
|
|
3395
|
+
useEffect17(() => {
|
|
3140
3396
|
if (pushEnabled && auth.status === "authenticated" && registrationPhase && !isRestoredSession) {
|
|
3141
3397
|
setShowPushSetup(true);
|
|
3142
3398
|
}
|
|
3143
3399
|
}, [pushEnabled, auth.status, registrationPhase, isRestoredSession]);
|
|
3144
|
-
|
|
3400
|
+
useEffect17(() => {
|
|
3145
3401
|
if (auth.token) onSaveToken(auth.token);
|
|
3146
3402
|
}, [auth.token]);
|
|
3147
|
-
const retry =
|
|
3403
|
+
const retry = useCallback24(() => {
|
|
3148
3404
|
setRegistrationPhase(false);
|
|
3149
3405
|
auth.reset();
|
|
3150
3406
|
auth.authenticate();
|
|
3151
3407
|
}, [auth]);
|
|
3152
|
-
const handleRegister =
|
|
3408
|
+
const handleRegister = useCallback24(
|
|
3153
3409
|
(username, referralCode, avatarUrl) => {
|
|
3154
3410
|
auth.register(username, referralCode, avatarUrl);
|
|
3155
3411
|
},
|
|
@@ -3273,20 +3529,20 @@ function DefaultRegistrationScreen({
|
|
|
3273
3529
|
}) {
|
|
3274
3530
|
const t = useDubsTheme();
|
|
3275
3531
|
const accent = accentColor || t.accent;
|
|
3276
|
-
const [step, setStep] =
|
|
3277
|
-
const [avatarSeed, setAvatarSeed] =
|
|
3278
|
-
const [avatarStyle, setAvatarStyle] =
|
|
3279
|
-
const [avatarBg, setAvatarBg] =
|
|
3280
|
-
const [showStyles, setShowStyles] =
|
|
3281
|
-
const [username, setUsername] =
|
|
3282
|
-
const [referralCode, setReferralCode] =
|
|
3283
|
-
const [checking, setChecking] =
|
|
3284
|
-
const [availability, setAvailability] =
|
|
3532
|
+
const [step, setStep] = useState26(0);
|
|
3533
|
+
const [avatarSeed, setAvatarSeed] = useState26(generateSeed);
|
|
3534
|
+
const [avatarStyle, setAvatarStyle] = useState26("adventurer");
|
|
3535
|
+
const [avatarBg, setAvatarBg] = useState26("1a1a2e");
|
|
3536
|
+
const [showStyles, setShowStyles] = useState26(false);
|
|
3537
|
+
const [username, setUsername] = useState26("");
|
|
3538
|
+
const [referralCode, setReferralCode] = useState26("");
|
|
3539
|
+
const [checking, setChecking] = useState26(false);
|
|
3540
|
+
const [availability, setAvailability] = useState26(null);
|
|
3285
3541
|
const debounceRef = useRef6(null);
|
|
3286
3542
|
const fadeAnim = useRef6(new Animated.Value(1)).current;
|
|
3287
3543
|
const slideAnim = useRef6(new Animated.Value(0)).current;
|
|
3288
3544
|
const avatarUrl = getAvatarUrl(avatarStyle, avatarSeed, avatarBg);
|
|
3289
|
-
|
|
3545
|
+
useEffect17(() => {
|
|
3290
3546
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
3291
3547
|
const trimmed = username.trim();
|
|
3292
3548
|
if (trimmed.length < 3) {
|
|
@@ -3309,7 +3565,7 @@ function DefaultRegistrationScreen({
|
|
|
3309
3565
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
3310
3566
|
};
|
|
3311
3567
|
}, [username, client]);
|
|
3312
|
-
const animateToStep =
|
|
3568
|
+
const animateToStep = useCallback24((newStep) => {
|
|
3313
3569
|
const dir = newStep > step ? 1 : -1;
|
|
3314
3570
|
Keyboard.dismiss();
|
|
3315
3571
|
Animated.parallel([
|
|
@@ -3549,7 +3805,7 @@ function DefaultRegistrationScreen({
|
|
|
3549
3805
|
function PushTokenRestorer() {
|
|
3550
3806
|
const push = usePushNotifications();
|
|
3551
3807
|
const restored = useRef6(false);
|
|
3552
|
-
|
|
3808
|
+
useEffect17(() => {
|
|
3553
3809
|
if (restored.current) return;
|
|
3554
3810
|
restored.current = true;
|
|
3555
3811
|
push.restoreIfGranted();
|
|
@@ -3566,7 +3822,7 @@ function PushSetupScreen({
|
|
|
3566
3822
|
const push = usePushNotifications();
|
|
3567
3823
|
const fadeAnim = useRef6(new Animated.Value(0)).current;
|
|
3568
3824
|
const slideAnim = useRef6(new Animated.Value(30)).current;
|
|
3569
|
-
|
|
3825
|
+
useEffect17(() => {
|
|
3570
3826
|
Animated.parallel([
|
|
3571
3827
|
Animated.timing(fadeAnim, { toValue: 1, duration: 300, useNativeDriver: true }),
|
|
3572
3828
|
Animated.timing(slideAnim, { toValue: 0, duration: 300, useNativeDriver: true })
|
|
@@ -3726,9 +3982,9 @@ function DubsProvider({
|
|
|
3726
3982
|
const rpcUrl = rpcUrlOverride || config.rpcUrl;
|
|
3727
3983
|
const client = useMemo3(() => new DubsClient({ apiKey, baseUrl }), [apiKey, baseUrl]);
|
|
3728
3984
|
const storage = useMemo3(() => tokenStorage || createSecureStoreStorage(), [tokenStorage]);
|
|
3729
|
-
const [uiConfig, setUiConfig] =
|
|
3730
|
-
const [resolvedNetwork, setResolvedNetwork] =
|
|
3731
|
-
|
|
3985
|
+
const [uiConfig, setUiConfig] = useState27(null);
|
|
3986
|
+
const [resolvedNetwork, setResolvedNetwork] = useState27(network);
|
|
3987
|
+
useEffect18(() => {
|
|
3732
3988
|
client.getAppConfig().then((cfg) => {
|
|
3733
3989
|
console.log("[DubsProvider] UI config loaded:", JSON.stringify(cfg));
|
|
3734
3990
|
setUiConfig(cfg);
|
|
@@ -3820,7 +4076,7 @@ function ManagedInner({
|
|
|
3820
4076
|
children
|
|
3821
4077
|
}) {
|
|
3822
4078
|
const managedDisconnect = useDisconnect();
|
|
3823
|
-
const disconnect =
|
|
4079
|
+
const disconnect = useCallback25(async () => {
|
|
3824
4080
|
client.setToken(null);
|
|
3825
4081
|
await managedDisconnect?.();
|
|
3826
4082
|
}, [client, managedDisconnect]);
|
|
@@ -3861,7 +4117,7 @@ function ExternalWalletProvider({
|
|
|
3861
4117
|
pushEnabled,
|
|
3862
4118
|
children
|
|
3863
4119
|
}) {
|
|
3864
|
-
const disconnect =
|
|
4120
|
+
const disconnect = useCallback25(async () => {
|
|
3865
4121
|
client.setToken(null);
|
|
3866
4122
|
await storage.deleteItem(STORAGE_KEYS.JWT_TOKEN).catch(() => {
|
|
3867
4123
|
});
|
|
@@ -4182,7 +4438,7 @@ var styles5 = StyleSheet6.create({
|
|
|
4182
4438
|
});
|
|
4183
4439
|
|
|
4184
4440
|
// src/ui/UserProfileSheet.tsx
|
|
4185
|
-
import { useState as
|
|
4441
|
+
import { useState as useState28, useEffect as useEffect19, useRef as useRef7, useCallback as useCallback26, useMemo as useMemo5 } from "react";
|
|
4186
4442
|
import {
|
|
4187
4443
|
View as View7,
|
|
4188
4444
|
Text as Text7,
|
|
@@ -4215,29 +4471,29 @@ function UserProfileSheet({
|
|
|
4215
4471
|
const push = usePushNotifications();
|
|
4216
4472
|
const overlayOpacity = useRef7(new Animated2.Value(0)).current;
|
|
4217
4473
|
const parsed = useMemo5(() => parseAvatarUrl(user.avatar), [user.avatar]);
|
|
4218
|
-
const [avatarStyle, setAvatarStyle] =
|
|
4219
|
-
const [avatarSeed, setAvatarSeed] =
|
|
4220
|
-
const [bgColor, setBgColor] =
|
|
4221
|
-
const [saving, setSaving] =
|
|
4222
|
-
const [error, setError] =
|
|
4223
|
-
|
|
4474
|
+
const [avatarStyle, setAvatarStyle] = useState28(parsed.style);
|
|
4475
|
+
const [avatarSeed, setAvatarSeed] = useState28(parsed.seed);
|
|
4476
|
+
const [bgColor, setBgColor] = useState28(parsed.bg);
|
|
4477
|
+
const [saving, setSaving] = useState28(false);
|
|
4478
|
+
const [error, setError] = useState28(null);
|
|
4479
|
+
useEffect19(() => {
|
|
4224
4480
|
const p = parseAvatarUrl(user.avatar);
|
|
4225
4481
|
setAvatarStyle(p.style);
|
|
4226
4482
|
setAvatarSeed(p.seed);
|
|
4227
4483
|
setBgColor(p.bg);
|
|
4228
4484
|
}, [user.avatar]);
|
|
4229
|
-
|
|
4485
|
+
useEffect19(() => {
|
|
4230
4486
|
Animated2.timing(overlayOpacity, {
|
|
4231
4487
|
toValue: visible ? 1 : 0,
|
|
4232
4488
|
duration: 250,
|
|
4233
4489
|
useNativeDriver: true
|
|
4234
4490
|
}).start();
|
|
4235
4491
|
}, [visible, overlayOpacity]);
|
|
4236
|
-
|
|
4492
|
+
useEffect19(() => {
|
|
4237
4493
|
if (visible) setError(null);
|
|
4238
4494
|
}, [visible]);
|
|
4239
4495
|
const currentAvatarUrl = getAvatarUrl(avatarStyle, avatarSeed, bgColor);
|
|
4240
|
-
const saveAvatar =
|
|
4496
|
+
const saveAvatar = useCallback26(async (newUrl) => {
|
|
4241
4497
|
setSaving(true);
|
|
4242
4498
|
setError(null);
|
|
4243
4499
|
try {
|
|
@@ -4250,16 +4506,16 @@ function UserProfileSheet({
|
|
|
4250
4506
|
setSaving(false);
|
|
4251
4507
|
}
|
|
4252
4508
|
}, [client, refreshUser, onAvatarUpdated]);
|
|
4253
|
-
const handleStyleChange =
|
|
4509
|
+
const handleStyleChange = useCallback26((style) => {
|
|
4254
4510
|
setAvatarStyle(style);
|
|
4255
4511
|
saveAvatar(getAvatarUrl(style, avatarSeed, bgColor));
|
|
4256
4512
|
}, [avatarSeed, bgColor, saveAvatar]);
|
|
4257
|
-
const handleShuffle =
|
|
4513
|
+
const handleShuffle = useCallback26(() => {
|
|
4258
4514
|
const newSeed = generateSeed();
|
|
4259
4515
|
setAvatarSeed(newSeed);
|
|
4260
4516
|
saveAvatar(getAvatarUrl(avatarStyle, newSeed, bgColor));
|
|
4261
4517
|
}, [avatarStyle, bgColor, saveAvatar]);
|
|
4262
|
-
const handleBgChange =
|
|
4518
|
+
const handleBgChange = useCallback26((color) => {
|
|
4263
4519
|
setBgColor(color);
|
|
4264
4520
|
saveAvatar(getAvatarUrl(avatarStyle, avatarSeed, color));
|
|
4265
4521
|
}, [avatarStyle, avatarSeed, saveAvatar]);
|
|
@@ -4539,7 +4795,7 @@ var styles6 = StyleSheet7.create({
|
|
|
4539
4795
|
});
|
|
4540
4796
|
|
|
4541
4797
|
// src/ui/game/GamePoster.tsx
|
|
4542
|
-
import { useState as
|
|
4798
|
+
import { useState as useState29 } from "react";
|
|
4543
4799
|
import { StyleSheet as StyleSheet8, View as View8, Text as Text8 } from "react-native";
|
|
4544
4800
|
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
4545
4801
|
function computeCountdown(lockTimestamp) {
|
|
@@ -4589,7 +4845,7 @@ function GamePoster({ game, ImageComponent }) {
|
|
|
4589
4845
|
] });
|
|
4590
4846
|
}
|
|
4591
4847
|
function TeamLogoInternal({ url, size, Img }) {
|
|
4592
|
-
const [failed, setFailed] =
|
|
4848
|
+
const [failed, setFailed] = useState29(false);
|
|
4593
4849
|
if (!url || failed) {
|
|
4594
4850
|
return /* @__PURE__ */ jsx10(View8, { style: [styles7.logoPlaceholder, { width: size, height: size, borderRadius: size / 2 }] });
|
|
4595
4851
|
}
|
|
@@ -4769,7 +5025,7 @@ var styles8 = StyleSheet9.create({
|
|
|
4769
5025
|
});
|
|
4770
5026
|
|
|
4771
5027
|
// src/ui/game/PickWinnerCard.tsx
|
|
4772
|
-
import { useState as
|
|
5028
|
+
import { useState as useState30, useMemo as useMemo7 } from "react";
|
|
4773
5029
|
import { StyleSheet as StyleSheet10, View as View10, Text as Text10, TouchableOpacity as TouchableOpacity7 } from "react-native";
|
|
4774
5030
|
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
4775
5031
|
function PickWinnerCard({
|
|
@@ -4840,7 +5096,7 @@ function TeamOption({
|
|
|
4840
5096
|
ImageComponent,
|
|
4841
5097
|
t
|
|
4842
5098
|
}) {
|
|
4843
|
-
const [imgFailed, setImgFailed] =
|
|
5099
|
+
const [imgFailed, setImgFailed] = useState30(false);
|
|
4844
5100
|
const Img = ImageComponent || __require("react-native").Image;
|
|
4845
5101
|
const showImage = imageUrl && !imgFailed;
|
|
4846
5102
|
return /* @__PURE__ */ jsxs9(
|
|
@@ -4881,7 +5137,7 @@ var styles9 = StyleSheet10.create({
|
|
|
4881
5137
|
});
|
|
4882
5138
|
|
|
4883
5139
|
// src/ui/game/PlayersCard.tsx
|
|
4884
|
-
import { useState as
|
|
5140
|
+
import { useState as useState31 } from "react";
|
|
4885
5141
|
import { StyleSheet as StyleSheet11, View as View11, Text as Text11 } from "react-native";
|
|
4886
5142
|
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
4887
5143
|
function truncateWallet(addr, chars) {
|
|
@@ -4930,7 +5186,7 @@ function BettorRow({
|
|
|
4930
5186
|
ImageComponent,
|
|
4931
5187
|
t
|
|
4932
5188
|
}) {
|
|
4933
|
-
const [imgFailed, setImgFailed] =
|
|
5189
|
+
const [imgFailed, setImgFailed] = useState31(false);
|
|
4934
5190
|
const Img = ImageComponent || __require("react-native").Image;
|
|
4935
5191
|
const showAvatar = bettor.avatar && !imgFailed;
|
|
4936
5192
|
return /* @__PURE__ */ jsxs10(View11, { style: [styles10.row, !isFirst && { borderTopColor: t.border, borderTopWidth: 1 }], children: [
|
|
@@ -5009,7 +5265,7 @@ var styles11 = StyleSheet12.create({
|
|
|
5009
5265
|
});
|
|
5010
5266
|
|
|
5011
5267
|
// src/ui/game/CreateCustomGameSheet.tsx
|
|
5012
|
-
import { useState as
|
|
5268
|
+
import { useState as useState32, useEffect as useEffect20, useRef as useRef8, useCallback as useCallback27 } from "react";
|
|
5013
5269
|
import {
|
|
5014
5270
|
View as View13,
|
|
5015
5271
|
Text as Text13,
|
|
@@ -5046,18 +5302,18 @@ function CreateCustomGameSheet({
|
|
|
5046
5302
|
const t = useDubsTheme();
|
|
5047
5303
|
const { wallet } = useDubs();
|
|
5048
5304
|
const mutation = useCreateCustomGame();
|
|
5049
|
-
const [selectedAmount, setSelectedAmount] =
|
|
5050
|
-
const [customAmount, setCustomAmount] =
|
|
5051
|
-
const [isCustom, setIsCustom] =
|
|
5305
|
+
const [selectedAmount, setSelectedAmount] = useState32(null);
|
|
5306
|
+
const [customAmount, setCustomAmount] = useState32("");
|
|
5307
|
+
const [isCustom, setIsCustom] = useState32(false);
|
|
5052
5308
|
const overlayOpacity = useRef8(new Animated3.Value(0)).current;
|
|
5053
|
-
|
|
5309
|
+
useEffect20(() => {
|
|
5054
5310
|
Animated3.timing(overlayOpacity, {
|
|
5055
5311
|
toValue: visible ? 1 : 0,
|
|
5056
5312
|
duration: 250,
|
|
5057
5313
|
useNativeDriver: true
|
|
5058
5314
|
}).start();
|
|
5059
5315
|
}, [visible, overlayOpacity]);
|
|
5060
|
-
|
|
5316
|
+
useEffect20(() => {
|
|
5061
5317
|
if (visible) {
|
|
5062
5318
|
setSelectedAmount(defaultAmount ?? null);
|
|
5063
5319
|
setCustomAmount("");
|
|
@@ -5065,7 +5321,7 @@ function CreateCustomGameSheet({
|
|
|
5065
5321
|
mutation.reset();
|
|
5066
5322
|
}
|
|
5067
5323
|
}, [visible]);
|
|
5068
|
-
|
|
5324
|
+
useEffect20(() => {
|
|
5069
5325
|
if (mutation.status === "success" && mutation.data) {
|
|
5070
5326
|
onSuccess?.(mutation.data);
|
|
5071
5327
|
const timer = setTimeout(() => {
|
|
@@ -5074,23 +5330,23 @@ function CreateCustomGameSheet({
|
|
|
5074
5330
|
return () => clearTimeout(timer);
|
|
5075
5331
|
}
|
|
5076
5332
|
}, [mutation.status, mutation.data]);
|
|
5077
|
-
|
|
5333
|
+
useEffect20(() => {
|
|
5078
5334
|
if (mutation.status === "error" && mutation.error) {
|
|
5079
5335
|
onError?.(mutation.error);
|
|
5080
5336
|
}
|
|
5081
5337
|
}, [mutation.status, mutation.error]);
|
|
5082
|
-
const handlePresetSelect =
|
|
5338
|
+
const handlePresetSelect = useCallback27((amount) => {
|
|
5083
5339
|
setSelectedAmount(amount);
|
|
5084
5340
|
setIsCustom(false);
|
|
5085
5341
|
setCustomAmount("");
|
|
5086
5342
|
onAmountChange?.(amount);
|
|
5087
5343
|
}, [onAmountChange]);
|
|
5088
|
-
const handleCustomSelect =
|
|
5344
|
+
const handleCustomSelect = useCallback27(() => {
|
|
5089
5345
|
setIsCustom(true);
|
|
5090
5346
|
setSelectedAmount(null);
|
|
5091
5347
|
onAmountChange?.(null);
|
|
5092
5348
|
}, [onAmountChange]);
|
|
5093
|
-
const handleCustomAmountChange =
|
|
5349
|
+
const handleCustomAmountChange = useCallback27((text) => {
|
|
5094
5350
|
const cleaned = text.replace(/[^0-9.]/g, "").replace(/(\..*?)\..*/g, "$1");
|
|
5095
5351
|
setCustomAmount(cleaned);
|
|
5096
5352
|
const parsed = parseFloat(cleaned);
|
|
@@ -5105,7 +5361,7 @@ function CreateCustomGameSheet({
|
|
|
5105
5361
|
const winnerTakes = pot * (1 - fee / 100);
|
|
5106
5362
|
const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
|
|
5107
5363
|
const canCreate = finalAmount !== null && finalAmount > 0 && !isMutating && mutation.status !== "success";
|
|
5108
|
-
const handleCreate =
|
|
5364
|
+
const handleCreate = useCallback27(async () => {
|
|
5109
5365
|
if (!finalAmount || !wallet.publicKey) return;
|
|
5110
5366
|
try {
|
|
5111
5367
|
await mutation.execute({
|
|
@@ -5374,7 +5630,7 @@ var styles12 = StyleSheet13.create({
|
|
|
5374
5630
|
});
|
|
5375
5631
|
|
|
5376
5632
|
// src/ui/game/JoinGameSheet.tsx
|
|
5377
|
-
import { useState as
|
|
5633
|
+
import { useState as useState34, useEffect as useEffect21, useRef as useRef10, useCallback as useCallback29, useMemo as useMemo9 } from "react";
|
|
5378
5634
|
import {
|
|
5379
5635
|
View as View16,
|
|
5380
5636
|
Text as Text16,
|
|
@@ -5584,7 +5840,7 @@ var styles13 = StyleSheet14.create({
|
|
|
5584
5840
|
});
|
|
5585
5841
|
|
|
5586
5842
|
// src/ui/game/TeamButton.tsx
|
|
5587
|
-
import { useState as
|
|
5843
|
+
import { useState as useState33 } from "react";
|
|
5588
5844
|
import { View as View15, Text as Text15, TouchableOpacity as TouchableOpacity10, StyleSheet as StyleSheet15 } from "react-native";
|
|
5589
5845
|
import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
5590
5846
|
function TeamButton({
|
|
@@ -5598,7 +5854,7 @@ function TeamButton({
|
|
|
5598
5854
|
ImageComponent,
|
|
5599
5855
|
t
|
|
5600
5856
|
}) {
|
|
5601
|
-
const [imgFailed, setImgFailed] =
|
|
5857
|
+
const [imgFailed, setImgFailed] = useState33(false);
|
|
5602
5858
|
const Img = ImageComponent || __require("react-native").Image;
|
|
5603
5859
|
const showImage = imageUrl && !imgFailed;
|
|
5604
5860
|
return /* @__PURE__ */ jsxs14(
|
|
@@ -5702,20 +5958,20 @@ function JoinGameSheet({
|
|
|
5702
5958
|
const { wallet } = useDubs();
|
|
5703
5959
|
const mutation = useJoinGame();
|
|
5704
5960
|
const isCustomGame = game.gameMode === CUSTOM_GAME_MODE;
|
|
5705
|
-
const [selectedTeam, setSelectedTeam] =
|
|
5706
|
-
const [wager, setWager] =
|
|
5707
|
-
const [showSuccess, setShowSuccess] =
|
|
5961
|
+
const [selectedTeam, setSelectedTeam] = useState34(null);
|
|
5962
|
+
const [wager, setWager] = useState34(game.buyIn);
|
|
5963
|
+
const [showSuccess, setShowSuccess] = useState34(false);
|
|
5708
5964
|
const overlayOpacity = useRef10(new Animated4.Value(0)).current;
|
|
5709
5965
|
const successScale = useRef10(new Animated4.Value(0)).current;
|
|
5710
5966
|
const successOpacity = useRef10(new Animated4.Value(0)).current;
|
|
5711
|
-
|
|
5967
|
+
useEffect21(() => {
|
|
5712
5968
|
Animated4.timing(overlayOpacity, {
|
|
5713
5969
|
toValue: visible ? 1 : 0,
|
|
5714
5970
|
duration: 250,
|
|
5715
5971
|
useNativeDriver: true
|
|
5716
5972
|
}).start();
|
|
5717
5973
|
}, [visible, overlayOpacity]);
|
|
5718
|
-
|
|
5974
|
+
useEffect21(() => {
|
|
5719
5975
|
if (visible) {
|
|
5720
5976
|
setSelectedTeam(isPoolModeEnabled ? "home" : isCustomGame ? "away" : null);
|
|
5721
5977
|
setWager(game.buyIn);
|
|
@@ -5725,7 +5981,7 @@ function JoinGameSheet({
|
|
|
5725
5981
|
mutation.reset();
|
|
5726
5982
|
}
|
|
5727
5983
|
}, [visible]);
|
|
5728
|
-
|
|
5984
|
+
useEffect21(() => {
|
|
5729
5985
|
if (mutation.status === "success" && mutation.data) {
|
|
5730
5986
|
setShowSuccess(true);
|
|
5731
5987
|
onSuccess?.(mutation.data);
|
|
@@ -5742,7 +5998,7 @@ function JoinGameSheet({
|
|
|
5742
5998
|
return () => clearTimeout(timer);
|
|
5743
5999
|
}
|
|
5744
6000
|
}, [mutation.status, mutation.data]);
|
|
5745
|
-
|
|
6001
|
+
useEffect21(() => {
|
|
5746
6002
|
if (mutation.status === "error" && mutation.error) {
|
|
5747
6003
|
onError?.(mutation.error);
|
|
5748
6004
|
}
|
|
@@ -5786,7 +6042,7 @@ function JoinGameSheet({
|
|
|
5786
6042
|
const alreadyJoined = myBet !== null;
|
|
5787
6043
|
const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
|
|
5788
6044
|
const canJoin = selectedTeam !== null && !isMutating && mutation.status !== "success" && !alreadyJoined;
|
|
5789
|
-
const handleJoin =
|
|
6045
|
+
const handleJoin = useCallback29(async () => {
|
|
5790
6046
|
if (!selectedTeam || !wallet.publicKey) return;
|
|
5791
6047
|
try {
|
|
5792
6048
|
await mutation.execute({
|
|
@@ -5846,13 +6102,15 @@ function JoinGameSheet({
|
|
|
5846
6102
|
] }) })
|
|
5847
6103
|
] })
|
|
5848
6104
|
] }),
|
|
5849
|
-
!isCustomGame && !isPoolModeEnabled && !alreadyJoined &&
|
|
5850
|
-
/*
|
|
5851
|
-
/* @__PURE__ */ jsxs15(View16, { style: styles15.
|
|
6105
|
+
!isCustomGame && !isPoolModeEnabled && !alreadyJoined && (hasDrawOption ? (
|
|
6106
|
+
/* ── 3-way layout: Home / VS / Away / OR / Draw ── */
|
|
6107
|
+
/* @__PURE__ */ jsxs15(View16, { style: styles15.section, children: [
|
|
6108
|
+
/* @__PURE__ */ jsx18(Text16, { style: [styles15.sectionLabel, { color: t.textSecondary }], children: "Who will win?" }),
|
|
5852
6109
|
/* @__PURE__ */ jsx18(
|
|
5853
|
-
|
|
6110
|
+
PickRow,
|
|
5854
6111
|
{
|
|
5855
6112
|
name: homeName,
|
|
6113
|
+
subtitle: "Home Team",
|
|
5856
6114
|
imageUrl: opponents[0]?.imageUrl,
|
|
5857
6115
|
odds: homeOdds,
|
|
5858
6116
|
bets: homeBets,
|
|
@@ -5866,10 +6124,16 @@ function JoinGameSheet({
|
|
|
5866
6124
|
t
|
|
5867
6125
|
}
|
|
5868
6126
|
),
|
|
6127
|
+
/* @__PURE__ */ jsxs15(View16, { style: styles15.dividerRow, children: [
|
|
6128
|
+
/* @__PURE__ */ jsx18(View16, { style: [styles15.dividerLine, { backgroundColor: t.border }] }),
|
|
6129
|
+
/* @__PURE__ */ jsx18(Text16, { style: [styles15.dividerText, { color: t.textMuted }], children: "VS" }),
|
|
6130
|
+
/* @__PURE__ */ jsx18(View16, { style: [styles15.dividerLine, { backgroundColor: t.border }] })
|
|
6131
|
+
] }),
|
|
5869
6132
|
/* @__PURE__ */ jsx18(
|
|
5870
|
-
|
|
6133
|
+
PickRow,
|
|
5871
6134
|
{
|
|
5872
6135
|
name: awayName,
|
|
6136
|
+
subtitle: "Away Team",
|
|
5873
6137
|
imageUrl: opponents[1]?.imageUrl,
|
|
5874
6138
|
odds: awayOdds,
|
|
5875
6139
|
bets: awayBets,
|
|
@@ -5882,24 +6146,71 @@ function JoinGameSheet({
|
|
|
5882
6146
|
ImageComponent,
|
|
5883
6147
|
t
|
|
5884
6148
|
}
|
|
6149
|
+
),
|
|
6150
|
+
/* @__PURE__ */ jsxs15(View16, { style: styles15.dividerRow, children: [
|
|
6151
|
+
/* @__PURE__ */ jsx18(View16, { style: [styles15.dividerLine, { backgroundColor: t.border }] }),
|
|
6152
|
+
/* @__PURE__ */ jsx18(Text16, { style: [styles15.dividerText, { color: t.textMuted }], children: "OR" }),
|
|
6153
|
+
/* @__PURE__ */ jsx18(View16, { style: [styles15.dividerLine, { backgroundColor: t.border }] })
|
|
6154
|
+
] }),
|
|
6155
|
+
/* @__PURE__ */ jsx18(
|
|
6156
|
+
PickRow,
|
|
6157
|
+
{
|
|
6158
|
+
name: "Draw",
|
|
6159
|
+
subtitle: "Match ends in a tie",
|
|
6160
|
+
odds: drawOdds,
|
|
6161
|
+
bets: drawBets,
|
|
6162
|
+
color: drawColor,
|
|
6163
|
+
selected: selectedTeam === "draw",
|
|
6164
|
+
onPress: () => {
|
|
6165
|
+
setSelectedTeam("draw");
|
|
6166
|
+
onTeamSelect?.("draw");
|
|
6167
|
+
},
|
|
6168
|
+
t
|
|
6169
|
+
}
|
|
5885
6170
|
)
|
|
5886
|
-
] })
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
6171
|
+
] })
|
|
6172
|
+
) : (
|
|
6173
|
+
/* ── 2-way layout: side by side ── */
|
|
6174
|
+
/* @__PURE__ */ jsxs15(View16, { style: styles15.section, children: [
|
|
6175
|
+
/* @__PURE__ */ jsx18(Text16, { style: [styles15.sectionLabel, { color: t.textSecondary }], children: "Pick Your Side" }),
|
|
6176
|
+
/* @__PURE__ */ jsxs15(View16, { style: styles15.teamsRow, children: [
|
|
6177
|
+
/* @__PURE__ */ jsx18(
|
|
6178
|
+
TeamButton,
|
|
6179
|
+
{
|
|
6180
|
+
name: homeName,
|
|
6181
|
+
imageUrl: opponents[0]?.imageUrl,
|
|
6182
|
+
odds: homeOdds,
|
|
6183
|
+
bets: homeBets,
|
|
6184
|
+
color: homeColor,
|
|
6185
|
+
selected: selectedTeam === "home",
|
|
6186
|
+
onPress: () => {
|
|
6187
|
+
setSelectedTeam("home");
|
|
6188
|
+
onTeamSelect?.("home");
|
|
6189
|
+
},
|
|
6190
|
+
ImageComponent,
|
|
6191
|
+
t
|
|
6192
|
+
}
|
|
6193
|
+
),
|
|
6194
|
+
/* @__PURE__ */ jsx18(
|
|
6195
|
+
TeamButton,
|
|
6196
|
+
{
|
|
6197
|
+
name: awayName,
|
|
6198
|
+
imageUrl: opponents[1]?.imageUrl,
|
|
6199
|
+
odds: awayOdds,
|
|
6200
|
+
bets: awayBets,
|
|
6201
|
+
color: awayColor,
|
|
6202
|
+
selected: selectedTeam === "away",
|
|
6203
|
+
onPress: () => {
|
|
6204
|
+
setSelectedTeam("away");
|
|
6205
|
+
onTeamSelect?.("away");
|
|
6206
|
+
},
|
|
6207
|
+
ImageComponent,
|
|
6208
|
+
t
|
|
6209
|
+
}
|
|
6210
|
+
)
|
|
6211
|
+
] })
|
|
6212
|
+
] })
|
|
6213
|
+
)),
|
|
5903
6214
|
alreadyJoined && myBet && /* @__PURE__ */ jsxs15(View16, { style: [styles15.myBetCard, { backgroundColor: (myBet.team === "home" ? homeColor : myBet.team === "away" ? awayColor : drawColor) + "15", borderColor: myBet.team === "home" ? homeColor : myBet.team === "away" ? awayColor : drawColor }], children: [
|
|
5904
6215
|
/* @__PURE__ */ jsx18(Text16, { style: [styles15.myBetLabel, { color: myBet.team === "home" ? homeColor : myBet.team === "away" ? awayColor : drawColor }], children: "YOUR BET" }),
|
|
5905
6216
|
/* @__PURE__ */ jsx18(Text16, { style: [styles15.myBetTeam, { color: t.text }], children: myBet.team === "home" ? homeName : myBet.team === "away" ? awayName : "Draw" }),
|
|
@@ -5982,6 +6293,100 @@ function JoinGameSheet({
|
|
|
5982
6293
|
}
|
|
5983
6294
|
);
|
|
5984
6295
|
}
|
|
6296
|
+
function PickRow({
|
|
6297
|
+
name,
|
|
6298
|
+
subtitle,
|
|
6299
|
+
imageUrl,
|
|
6300
|
+
odds,
|
|
6301
|
+
bets,
|
|
6302
|
+
color,
|
|
6303
|
+
selected,
|
|
6304
|
+
onPress,
|
|
6305
|
+
ImageComponent,
|
|
6306
|
+
t
|
|
6307
|
+
}) {
|
|
6308
|
+
const [imgFailed, setImgFailed] = useState34(false);
|
|
6309
|
+
const Img = ImageComponent || __require("react-native").Image;
|
|
6310
|
+
const showImage = imageUrl && !imgFailed;
|
|
6311
|
+
return /* @__PURE__ */ jsxs15(
|
|
6312
|
+
TouchableOpacity11,
|
|
6313
|
+
{
|
|
6314
|
+
style: [pickStyles.row, { borderColor: selected ? color : t.border, backgroundColor: selected ? color + "12" : t.background }],
|
|
6315
|
+
onPress,
|
|
6316
|
+
activeOpacity: 0.7,
|
|
6317
|
+
children: [
|
|
6318
|
+
showImage ? /* @__PURE__ */ jsx18(Img, { source: { uri: imageUrl }, style: pickStyles.logo, resizeMode: "contain", onError: () => setImgFailed(true) }) : /* @__PURE__ */ jsx18(View16, { style: [pickStyles.logoPlaceholder, { backgroundColor: color + "20" }], children: /* @__PURE__ */ jsx18(Text16, { style: [pickStyles.logoEmoji, { color }], children: name === "Draw" ? "\u{1F91D}" : name.charAt(0) }) }),
|
|
6319
|
+
/* @__PURE__ */ jsxs15(View16, { style: pickStyles.info, children: [
|
|
6320
|
+
/* @__PURE__ */ jsx18(Text16, { style: [pickStyles.name, { color: t.text }], children: name }),
|
|
6321
|
+
subtitle && /* @__PURE__ */ jsx18(Text16, { style: [pickStyles.subtitle, { color: t.textMuted }], children: subtitle })
|
|
6322
|
+
] }),
|
|
6323
|
+
odds !== "\u2014" && /* @__PURE__ */ jsxs15(Text16, { style: [pickStyles.odds, { color }], children: [
|
|
6324
|
+
odds,
|
|
6325
|
+
"x"
|
|
6326
|
+
] }),
|
|
6327
|
+
bets > 0 && /* @__PURE__ */ jsx18(Text16, { style: [pickStyles.bets, { color: t.textMuted }], children: bets }),
|
|
6328
|
+
selected && /* @__PURE__ */ jsx18(View16, { style: [pickStyles.check, { backgroundColor: color }], children: /* @__PURE__ */ jsx18(Text16, { style: pickStyles.checkText, children: "\u2713" }) })
|
|
6329
|
+
]
|
|
6330
|
+
}
|
|
6331
|
+
);
|
|
6332
|
+
}
|
|
6333
|
+
var pickStyles = StyleSheet16.create({
|
|
6334
|
+
row: {
|
|
6335
|
+
flexDirection: "row",
|
|
6336
|
+
alignItems: "center",
|
|
6337
|
+
borderWidth: 1.5,
|
|
6338
|
+
borderRadius: 14,
|
|
6339
|
+
paddingVertical: 12,
|
|
6340
|
+
paddingHorizontal: 14,
|
|
6341
|
+
gap: 12
|
|
6342
|
+
},
|
|
6343
|
+
logo: {
|
|
6344
|
+
width: 36,
|
|
6345
|
+
height: 36,
|
|
6346
|
+
borderRadius: 18
|
|
6347
|
+
},
|
|
6348
|
+
logoPlaceholder: {
|
|
6349
|
+
width: 36,
|
|
6350
|
+
height: 36,
|
|
6351
|
+
borderRadius: 18,
|
|
6352
|
+
alignItems: "center",
|
|
6353
|
+
justifyContent: "center"
|
|
6354
|
+
},
|
|
6355
|
+
logoEmoji: {
|
|
6356
|
+
fontSize: 16,
|
|
6357
|
+
fontWeight: "800"
|
|
6358
|
+
},
|
|
6359
|
+
info: {
|
|
6360
|
+
flex: 1
|
|
6361
|
+
},
|
|
6362
|
+
name: {
|
|
6363
|
+
fontSize: 15,
|
|
6364
|
+
fontWeight: "700"
|
|
6365
|
+
},
|
|
6366
|
+
subtitle: {
|
|
6367
|
+
fontSize: 12,
|
|
6368
|
+
marginTop: 1
|
|
6369
|
+
},
|
|
6370
|
+
odds: {
|
|
6371
|
+
fontSize: 16,
|
|
6372
|
+
fontWeight: "800"
|
|
6373
|
+
},
|
|
6374
|
+
bets: {
|
|
6375
|
+
fontSize: 12
|
|
6376
|
+
},
|
|
6377
|
+
check: {
|
|
6378
|
+
width: 22,
|
|
6379
|
+
height: 22,
|
|
6380
|
+
borderRadius: 11,
|
|
6381
|
+
alignItems: "center",
|
|
6382
|
+
justifyContent: "center"
|
|
6383
|
+
},
|
|
6384
|
+
checkText: {
|
|
6385
|
+
color: "#FFF",
|
|
6386
|
+
fontSize: 13,
|
|
6387
|
+
fontWeight: "800"
|
|
6388
|
+
}
|
|
6389
|
+
});
|
|
5985
6390
|
var styles15 = StyleSheet16.create({
|
|
5986
6391
|
overlay: {
|
|
5987
6392
|
...StyleSheet16.absoluteFillObject,
|
|
@@ -6104,6 +6509,20 @@ var styles15 = StyleSheet16.create({
|
|
|
6104
6509
|
drawRow: {
|
|
6105
6510
|
marginTop: 8
|
|
6106
6511
|
},
|
|
6512
|
+
dividerRow: {
|
|
6513
|
+
flexDirection: "row",
|
|
6514
|
+
alignItems: "center",
|
|
6515
|
+
gap: 12,
|
|
6516
|
+
marginVertical: 6
|
|
6517
|
+
},
|
|
6518
|
+
dividerLine: {
|
|
6519
|
+
flex: 1,
|
|
6520
|
+
height: 1
|
|
6521
|
+
},
|
|
6522
|
+
dividerText: {
|
|
6523
|
+
fontSize: 12,
|
|
6524
|
+
fontWeight: "700"
|
|
6525
|
+
},
|
|
6107
6526
|
summaryCard: {
|
|
6108
6527
|
marginTop: 20,
|
|
6109
6528
|
borderRadius: 16,
|
|
@@ -6179,7 +6598,7 @@ var styles15 = StyleSheet16.create({
|
|
|
6179
6598
|
});
|
|
6180
6599
|
|
|
6181
6600
|
// src/ui/game/ClaimPrizeSheet.tsx
|
|
6182
|
-
import { useState as
|
|
6601
|
+
import { useState as useState35, useEffect as useEffect22, useRef as useRef11, useCallback as useCallback30 } from "react";
|
|
6183
6602
|
import {
|
|
6184
6603
|
View as View17,
|
|
6185
6604
|
Text as Text17,
|
|
@@ -6213,15 +6632,15 @@ function ClaimPrizeSheet({
|
|
|
6213
6632
|
const overlayOpacity = useRef11(new Animated5.Value(0)).current;
|
|
6214
6633
|
const celebrationScale = useRef11(new Animated5.Value(0)).current;
|
|
6215
6634
|
const celebrationOpacity = useRef11(new Animated5.Value(0)).current;
|
|
6216
|
-
const [showCelebration, setShowCelebration] =
|
|
6217
|
-
|
|
6635
|
+
const [showCelebration, setShowCelebration] = useState35(false);
|
|
6636
|
+
useEffect22(() => {
|
|
6218
6637
|
Animated5.timing(overlayOpacity, {
|
|
6219
6638
|
toValue: visible ? 1 : 0,
|
|
6220
6639
|
duration: 250,
|
|
6221
6640
|
useNativeDriver: true
|
|
6222
6641
|
}).start();
|
|
6223
6642
|
}, [visible, overlayOpacity]);
|
|
6224
|
-
|
|
6643
|
+
useEffect22(() => {
|
|
6225
6644
|
if (visible) {
|
|
6226
6645
|
mutation.reset();
|
|
6227
6646
|
setShowCelebration(false);
|
|
@@ -6229,7 +6648,7 @@ function ClaimPrizeSheet({
|
|
|
6229
6648
|
celebrationOpacity.setValue(0);
|
|
6230
6649
|
}
|
|
6231
6650
|
}, [visible]);
|
|
6232
|
-
|
|
6651
|
+
useEffect22(() => {
|
|
6233
6652
|
if (mutation.status === "success" && mutation.data) {
|
|
6234
6653
|
setShowCelebration(true);
|
|
6235
6654
|
Animated5.parallel([
|
|
@@ -6252,14 +6671,14 @@ function ClaimPrizeSheet({
|
|
|
6252
6671
|
return () => clearTimeout(timer);
|
|
6253
6672
|
}
|
|
6254
6673
|
}, [mutation.status, mutation.data]);
|
|
6255
|
-
|
|
6674
|
+
useEffect22(() => {
|
|
6256
6675
|
if (mutation.status === "error" && mutation.error) {
|
|
6257
6676
|
onError?.(mutation.error);
|
|
6258
6677
|
}
|
|
6259
6678
|
}, [mutation.status, mutation.error]);
|
|
6260
6679
|
const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
|
|
6261
6680
|
const canClaim = !isMutating && mutation.status !== "success" && !!wallet.publicKey;
|
|
6262
|
-
const handleClaim =
|
|
6681
|
+
const handleClaim = useCallback30(async () => {
|
|
6263
6682
|
if (!wallet.publicKey) return;
|
|
6264
6683
|
try {
|
|
6265
6684
|
await mutation.execute({
|
|
@@ -6492,7 +6911,7 @@ var styles16 = StyleSheet17.create({
|
|
|
6492
6911
|
});
|
|
6493
6912
|
|
|
6494
6913
|
// src/ui/game/ClaimButton.tsx
|
|
6495
|
-
import { useState as
|
|
6914
|
+
import { useState as useState36, useMemo as useMemo10, useCallback as useCallback31 } from "react";
|
|
6496
6915
|
import { StyleSheet as StyleSheet18, Text as Text18, TouchableOpacity as TouchableOpacity13 } from "react-native";
|
|
6497
6916
|
import { Fragment as Fragment5, jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
6498
6917
|
function ClaimButton({ gameId, style, onSuccess, onError }) {
|
|
@@ -6500,7 +6919,7 @@ function ClaimButton({ gameId, style, onSuccess, onError }) {
|
|
|
6500
6919
|
const { wallet } = useDubs();
|
|
6501
6920
|
const game = useGame(gameId);
|
|
6502
6921
|
const claimStatus = useHasClaimed(gameId);
|
|
6503
|
-
const [sheetVisible, setSheetVisible] =
|
|
6922
|
+
const [sheetVisible, setSheetVisible] = useState36(false);
|
|
6504
6923
|
const walletAddress = wallet.publicKey?.toBase58() ?? null;
|
|
6505
6924
|
const myBet = useMemo10(() => {
|
|
6506
6925
|
if (!walletAddress || !game.data?.bettors) return null;
|
|
@@ -6511,7 +6930,7 @@ function ClaimButton({ gameId, style, onSuccess, onError }) {
|
|
|
6511
6930
|
const isWinner = isResolved && myBet != null && myBet.team === game.data?.winnerSide;
|
|
6512
6931
|
const isEligible = myBet != null && isResolved && (isWinner || isRefund);
|
|
6513
6932
|
const prizeAmount = isRefund ? myBet?.amount ?? 0 : game.data?.totalPool ?? 0;
|
|
6514
|
-
const handleSuccess =
|
|
6933
|
+
const handleSuccess = useCallback31(
|
|
6515
6934
|
(result) => {
|
|
6516
6935
|
claimStatus.refetch();
|
|
6517
6936
|
onSuccess?.(result);
|
|
@@ -6598,7 +7017,7 @@ var styles17 = StyleSheet18.create({
|
|
|
6598
7017
|
});
|
|
6599
7018
|
|
|
6600
7019
|
// src/ui/game/EnterArcadePoolSheet.tsx
|
|
6601
|
-
import { useEffect as
|
|
7020
|
+
import { useEffect as useEffect23, useRef as useRef12, useCallback as useCallback32 } from "react";
|
|
6602
7021
|
import {
|
|
6603
7022
|
View as View18,
|
|
6604
7023
|
Text as Text19,
|
|
@@ -6630,19 +7049,19 @@ function EnterArcadePoolSheet({
|
|
|
6630
7049
|
const { wallet } = useDubs();
|
|
6631
7050
|
const mutation = useEnterArcadePool();
|
|
6632
7051
|
const overlayOpacity = useRef12(new Animated6.Value(0)).current;
|
|
6633
|
-
|
|
7052
|
+
useEffect23(() => {
|
|
6634
7053
|
Animated6.timing(overlayOpacity, {
|
|
6635
7054
|
toValue: visible ? 1 : 0,
|
|
6636
7055
|
duration: 250,
|
|
6637
7056
|
useNativeDriver: true
|
|
6638
7057
|
}).start();
|
|
6639
7058
|
}, [visible, overlayOpacity]);
|
|
6640
|
-
|
|
7059
|
+
useEffect23(() => {
|
|
6641
7060
|
if (visible) {
|
|
6642
7061
|
mutation.reset();
|
|
6643
7062
|
}
|
|
6644
7063
|
}, [visible]);
|
|
6645
|
-
|
|
7064
|
+
useEffect23(() => {
|
|
6646
7065
|
if (mutation.status === "success" && mutation.data) {
|
|
6647
7066
|
onSuccess?.(mutation.data);
|
|
6648
7067
|
const timer = setTimeout(() => {
|
|
@@ -6651,7 +7070,7 @@ function EnterArcadePoolSheet({
|
|
|
6651
7070
|
return () => clearTimeout(timer);
|
|
6652
7071
|
}
|
|
6653
7072
|
}, [mutation.status, mutation.data]);
|
|
6654
|
-
|
|
7073
|
+
useEffect23(() => {
|
|
6655
7074
|
if (mutation.status === "error" && mutation.error) {
|
|
6656
7075
|
onError?.(mutation.error);
|
|
6657
7076
|
}
|
|
@@ -6663,7 +7082,7 @@ function EnterArcadePoolSheet({
|
|
|
6663
7082
|
const potSol = (pool.buy_in_lamports * Number(totalBuyIns) / 1e9).toFixed(4);
|
|
6664
7083
|
const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
|
|
6665
7084
|
const canJoin = !isMutating && mutation.status !== "success";
|
|
6666
|
-
const handleJoin =
|
|
7085
|
+
const handleJoin = useCallback32(async () => {
|
|
6667
7086
|
if (!wallet.publicKey) return;
|
|
6668
7087
|
try {
|
|
6669
7088
|
await mutation.execute(pool.id);
|
|
@@ -6814,7 +7233,7 @@ var styles18 = StyleSheet19.create({
|
|
|
6814
7233
|
});
|
|
6815
7234
|
|
|
6816
7235
|
// src/ui/game/ArcadeLeaderboardSheet.tsx
|
|
6817
|
-
import { useEffect as
|
|
7236
|
+
import { useEffect as useEffect24, useRef as useRef13 } from "react";
|
|
6818
7237
|
import {
|
|
6819
7238
|
View as View19,
|
|
6820
7239
|
Text as Text20,
|
|
@@ -6843,14 +7262,14 @@ function ArcadeLeaderboardSheet({
|
|
|
6843
7262
|
const t = useDubsTheme();
|
|
6844
7263
|
const { pool, leaderboard, stats, loading, refetch } = useArcadePool(poolId);
|
|
6845
7264
|
const overlayOpacity = useRef13(new Animated7.Value(0)).current;
|
|
6846
|
-
|
|
7265
|
+
useEffect24(() => {
|
|
6847
7266
|
Animated7.timing(overlayOpacity, {
|
|
6848
7267
|
toValue: visible ? 1 : 0,
|
|
6849
7268
|
duration: 250,
|
|
6850
7269
|
useNativeDriver: true
|
|
6851
7270
|
}).start();
|
|
6852
7271
|
}, [visible, overlayOpacity]);
|
|
6853
|
-
|
|
7272
|
+
useEffect24(() => {
|
|
6854
7273
|
if (visible) refetch();
|
|
6855
7274
|
}, [visible]);
|
|
6856
7275
|
const renderItem = ({ item, index }) => {
|
|
@@ -6997,7 +7416,7 @@ var styles19 = StyleSheet20.create({
|
|
|
6997
7416
|
});
|
|
6998
7417
|
|
|
6999
7418
|
// src/ui/game/CreateGameSheet.tsx
|
|
7000
|
-
import { useState as
|
|
7419
|
+
import { useState as useState38, useEffect as useEffect25, useRef as useRef14, useCallback as useCallback33 } from "react";
|
|
7001
7420
|
import {
|
|
7002
7421
|
View as View20,
|
|
7003
7422
|
Text as Text21,
|
|
@@ -7036,20 +7455,20 @@ function CreateGameSheet({
|
|
|
7036
7455
|
const t = useDubsTheme();
|
|
7037
7456
|
const { wallet } = useDubs();
|
|
7038
7457
|
const mutation = useCreateGame();
|
|
7039
|
-
const [selectedTeam, setSelectedTeam] =
|
|
7040
|
-
const [wager, setWager] =
|
|
7041
|
-
const [showSuccess, setShowSuccess] =
|
|
7458
|
+
const [selectedTeam, setSelectedTeam] = useState38(null);
|
|
7459
|
+
const [wager, setWager] = useState38(0.01);
|
|
7460
|
+
const [showSuccess, setShowSuccess] = useState38(false);
|
|
7042
7461
|
const overlayOpacity = useRef14(new Animated8.Value(0)).current;
|
|
7043
7462
|
const successScale = useRef14(new Animated8.Value(0)).current;
|
|
7044
7463
|
const successOpacity = useRef14(new Animated8.Value(0)).current;
|
|
7045
|
-
|
|
7464
|
+
useEffect25(() => {
|
|
7046
7465
|
Animated8.timing(overlayOpacity, {
|
|
7047
7466
|
toValue: visible ? 1 : 0,
|
|
7048
7467
|
duration: 250,
|
|
7049
7468
|
useNativeDriver: true
|
|
7050
7469
|
}).start();
|
|
7051
7470
|
}, [visible]);
|
|
7052
|
-
|
|
7471
|
+
useEffect25(() => {
|
|
7053
7472
|
if (visible) {
|
|
7054
7473
|
setSelectedTeam(null);
|
|
7055
7474
|
setWager(0.01);
|
|
@@ -7059,7 +7478,7 @@ function CreateGameSheet({
|
|
|
7059
7478
|
mutation.reset();
|
|
7060
7479
|
}
|
|
7061
7480
|
}, [visible]);
|
|
7062
|
-
|
|
7481
|
+
useEffect25(() => {
|
|
7063
7482
|
if (mutation.status === "success" && mutation.data) {
|
|
7064
7483
|
setShowSuccess(true);
|
|
7065
7484
|
onSuccess?.(mutation.data);
|
|
@@ -7076,7 +7495,7 @@ function CreateGameSheet({
|
|
|
7076
7495
|
return () => clearTimeout(timer);
|
|
7077
7496
|
}
|
|
7078
7497
|
}, [mutation.status, mutation.data]);
|
|
7079
|
-
|
|
7498
|
+
useEffect25(() => {
|
|
7080
7499
|
if (mutation.status === "error" && mutation.error) {
|
|
7081
7500
|
onError?.(mutation.error);
|
|
7082
7501
|
}
|
|
@@ -7086,7 +7505,7 @@ function CreateGameSheet({
|
|
|
7086
7505
|
const awayName = shortName ? shortName(opponents[1]?.name) : opponents[1]?.name || "Away";
|
|
7087
7506
|
const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
|
|
7088
7507
|
const canCreate = selectedTeam !== null && !isMutating && mutation.status !== "success";
|
|
7089
|
-
const handleCreate =
|
|
7508
|
+
const handleCreate = useCallback33(async () => {
|
|
7090
7509
|
if (!selectedTeam || !wallet.publicKey) return;
|
|
7091
7510
|
try {
|
|
7092
7511
|
await mutation.execute({
|
|
@@ -7232,9 +7651,1500 @@ var styles20 = StyleSheet21.create({
|
|
|
7232
7651
|
successTitle: { color: "#FFFFFF", fontSize: 28, fontWeight: "900" },
|
|
7233
7652
|
successSub: { color: "#8E8E93", fontSize: 16 }
|
|
7234
7653
|
});
|
|
7654
|
+
|
|
7655
|
+
// src/ui/jackpot/JackpotCard.tsx
|
|
7656
|
+
import { useEffect as useEffect26, useRef as useRef15 } from "react";
|
|
7657
|
+
import {
|
|
7658
|
+
View as View21,
|
|
7659
|
+
Text as Text22,
|
|
7660
|
+
TouchableOpacity as TouchableOpacity17,
|
|
7661
|
+
Animated as Animated9,
|
|
7662
|
+
StyleSheet as StyleSheet22
|
|
7663
|
+
} from "react-native";
|
|
7664
|
+
import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
7665
|
+
function formatSOL(lamports) {
|
|
7666
|
+
const val = typeof lamports === "string" ? parseInt(lamports, 10) : lamports;
|
|
7667
|
+
if (isNaN(val) || val === 0) return "0";
|
|
7668
|
+
const sol = val / 1e9;
|
|
7669
|
+
if (sol >= 100) return sol.toFixed(0);
|
|
7670
|
+
if (sol >= 1) return sol.toFixed(2);
|
|
7671
|
+
if (sol >= 0.01) return sol.toFixed(3);
|
|
7672
|
+
return sol.toFixed(4);
|
|
7673
|
+
}
|
|
7674
|
+
function truncateWallet2(addr) {
|
|
7675
|
+
if (!addr || addr.length < 8) return addr || "";
|
|
7676
|
+
return `${addr.slice(0, 4)}...${addr.slice(-4)}`;
|
|
7677
|
+
}
|
|
7678
|
+
function JackpotCard({ round, lastWinner, entries, onPress, style }) {
|
|
7679
|
+
const shimmerAnim = useRef15(new Animated9.Value(-1)).current;
|
|
7680
|
+
const pulseAnim = useRef15(new Animated9.Value(0.4)).current;
|
|
7681
|
+
useEffect26(() => {
|
|
7682
|
+
const shimmer = Animated9.loop(
|
|
7683
|
+
Animated9.sequence([
|
|
7684
|
+
Animated9.timing(shimmerAnim, { toValue: 1, duration: 4e3, useNativeDriver: true }),
|
|
7685
|
+
Animated9.delay(500),
|
|
7686
|
+
Animated9.timing(shimmerAnim, { toValue: -1, duration: 0, useNativeDriver: true })
|
|
7687
|
+
])
|
|
7688
|
+
);
|
|
7689
|
+
shimmer.start();
|
|
7690
|
+
const pulse = Animated9.loop(
|
|
7691
|
+
Animated9.sequence([
|
|
7692
|
+
Animated9.timing(pulseAnim, { toValue: 1, duration: 1e3, useNativeDriver: true }),
|
|
7693
|
+
Animated9.timing(pulseAnim, { toValue: 0.4, duration: 1e3, useNativeDriver: true })
|
|
7694
|
+
])
|
|
7695
|
+
);
|
|
7696
|
+
pulse.start();
|
|
7697
|
+
return () => {
|
|
7698
|
+
shimmer.stop();
|
|
7699
|
+
pulse.stop();
|
|
7700
|
+
};
|
|
7701
|
+
}, [shimmerAnim, pulseAnim]);
|
|
7702
|
+
const potSol = round ? formatSOL(round.totalPotLamports) : "0";
|
|
7703
|
+
const isOpen = round?.status === "Open";
|
|
7704
|
+
const entryCount = round?.entryCount ?? 0;
|
|
7705
|
+
const totalWeight = round ? Number(BigInt(round.totalWeight || "0")) : 0;
|
|
7706
|
+
return /* @__PURE__ */ jsxs21(
|
|
7707
|
+
TouchableOpacity17,
|
|
7708
|
+
{
|
|
7709
|
+
activeOpacity: 0.9,
|
|
7710
|
+
onPress,
|
|
7711
|
+
style: [styles21.card, style],
|
|
7712
|
+
children: [
|
|
7713
|
+
/* @__PURE__ */ jsx24(View21, { style: styles21.gradientBg }),
|
|
7714
|
+
/* @__PURE__ */ jsx24(
|
|
7715
|
+
Animated9.View,
|
|
7716
|
+
{
|
|
7717
|
+
style: [
|
|
7718
|
+
styles21.shimmer,
|
|
7719
|
+
{
|
|
7720
|
+
transform: [{
|
|
7721
|
+
translateX: shimmerAnim.interpolate({
|
|
7722
|
+
inputRange: [-1, 1],
|
|
7723
|
+
outputRange: [-400, 400]
|
|
7724
|
+
})
|
|
7725
|
+
}]
|
|
7726
|
+
}
|
|
7727
|
+
]
|
|
7728
|
+
}
|
|
7729
|
+
),
|
|
7730
|
+
/* @__PURE__ */ jsx24(View21, { style: styles21.accentBar }),
|
|
7731
|
+
/* @__PURE__ */ jsxs21(View21, { style: styles21.content, children: [
|
|
7732
|
+
/* @__PURE__ */ jsxs21(View21, { style: styles21.statusRow, children: [
|
|
7733
|
+
/* @__PURE__ */ jsxs21(View21, { style: [styles21.statusBadge, isOpen ? styles21.statusOpen : styles21.statusClosed], children: [
|
|
7734
|
+
isOpen && /* @__PURE__ */ jsx24(Animated9.View, { style: [styles21.statusDot, { opacity: pulseAnim }] }),
|
|
7735
|
+
/* @__PURE__ */ jsx24(Text22, { style: [styles21.statusText, { color: isOpen ? "#22c55e" : "#9ca3af" }], children: isOpen ? "Open" : round?.status ?? "Loading" })
|
|
7736
|
+
] }),
|
|
7737
|
+
/* @__PURE__ */ jsxs21(Text22, { style: styles21.entryCountText, children: [
|
|
7738
|
+
entryCount,
|
|
7739
|
+
" player",
|
|
7740
|
+
entryCount !== 1 ? "s" : ""
|
|
7741
|
+
] })
|
|
7742
|
+
] }),
|
|
7743
|
+
/* @__PURE__ */ jsxs21(View21, { style: styles21.heroSection, children: [
|
|
7744
|
+
/* @__PURE__ */ jsxs21(View21, { style: styles21.potInfo, children: [
|
|
7745
|
+
/* @__PURE__ */ jsx24(Text22, { style: styles21.jackpotLabel, children: "JACKPOT" }),
|
|
7746
|
+
/* @__PURE__ */ jsxs21(Text22, { style: styles21.potValue, children: [
|
|
7747
|
+
potSol,
|
|
7748
|
+
" SOL"
|
|
7749
|
+
] })
|
|
7750
|
+
] }),
|
|
7751
|
+
/* @__PURE__ */ jsx24(Text22, { style: styles21.potEmoji, children: "\u{1F911}" })
|
|
7752
|
+
] }),
|
|
7753
|
+
/* @__PURE__ */ jsxs21(View21, { style: styles21.infoGrid, children: [
|
|
7754
|
+
/* @__PURE__ */ jsxs21(View21, { style: styles21.infoCard, children: [
|
|
7755
|
+
/* @__PURE__ */ jsx24(Text22, { style: styles21.infoLabel, children: "PLAYERS" }),
|
|
7756
|
+
/* @__PURE__ */ jsx24(Text22, { style: styles21.infoValue, children: entryCount })
|
|
7757
|
+
] }),
|
|
7758
|
+
/* @__PURE__ */ jsxs21(View21, { style: styles21.infoCard, children: [
|
|
7759
|
+
/* @__PURE__ */ jsx24(Text22, { style: styles21.infoLabel, children: "TOTAL POT" }),
|
|
7760
|
+
/* @__PURE__ */ jsx24(Text22, { style: [styles21.infoValue, { color: "#4ade80" }], children: potSol })
|
|
7761
|
+
] }),
|
|
7762
|
+
/* @__PURE__ */ jsxs21(View21, { style: styles21.infoCard, children: [
|
|
7763
|
+
/* @__PURE__ */ jsx24(Text22, { style: styles21.infoLabel, children: "LAST WIN" }),
|
|
7764
|
+
/* @__PURE__ */ jsx24(Text22, { style: [styles21.infoValue, { color: "#22c55e" }], children: lastWinner ? formatSOL(lastWinner.winAmount) : "\u2014" })
|
|
7765
|
+
] })
|
|
7766
|
+
] }),
|
|
7767
|
+
entries && entries.length > 0 && /* @__PURE__ */ jsxs21(View21, { style: styles21.playersSection, children: [
|
|
7768
|
+
/* @__PURE__ */ jsxs21(View21, { style: styles21.playersSectionHeader, children: [
|
|
7769
|
+
/* @__PURE__ */ jsx24(Text22, { style: styles21.playersSectionTitle, children: "Players in Round" }),
|
|
7770
|
+
/* @__PURE__ */ jsx24(View21, { style: styles21.activeCountBadge, children: /* @__PURE__ */ jsx24(Text22, { style: styles21.activeCountText, children: entries.length }) })
|
|
7771
|
+
] }),
|
|
7772
|
+
/* @__PURE__ */ jsxs21(View21, { style: styles21.playersCarousel, children: [
|
|
7773
|
+
entries.slice(0, 8).map((entry, i) => {
|
|
7774
|
+
const odds = entry.oddsPercent;
|
|
7775
|
+
return /* @__PURE__ */ jsxs21(View21, { style: styles21.playerCard, children: [
|
|
7776
|
+
/* @__PURE__ */ jsx24(View21, { style: styles21.playerAvatar, children: /* @__PURE__ */ jsx24(Text22, { style: styles21.playerAvatarText, children: entry.player.slice(0, 2).toUpperCase() }) }),
|
|
7777
|
+
/* @__PURE__ */ jsx24(Text22, { style: styles21.playerWallet, numberOfLines: 1, children: truncateWallet2(entry.player) }),
|
|
7778
|
+
/* @__PURE__ */ jsxs21(Text22, { style: styles21.playerWager, children: [
|
|
7779
|
+
entry.weightSol.toFixed(2),
|
|
7780
|
+
" SOL"
|
|
7781
|
+
] }),
|
|
7782
|
+
/* @__PURE__ */ jsxs21(Text22, { style: styles21.playerOdds, children: [
|
|
7783
|
+
odds,
|
|
7784
|
+
"%"
|
|
7785
|
+
] })
|
|
7786
|
+
] }, `${entry.player}-${i}`);
|
|
7787
|
+
}),
|
|
7788
|
+
entries.length > 8 && /* @__PURE__ */ jsx24(View21, { style: styles21.playerCardMore, children: /* @__PURE__ */ jsxs21(Text22, { style: styles21.playerMoreText, children: [
|
|
7789
|
+
"+",
|
|
7790
|
+
entries.length - 8
|
|
7791
|
+
] }) })
|
|
7792
|
+
] })
|
|
7793
|
+
] }),
|
|
7794
|
+
/* @__PURE__ */ jsx24(
|
|
7795
|
+
TouchableOpacity17,
|
|
7796
|
+
{
|
|
7797
|
+
style: styles21.placeBetButton,
|
|
7798
|
+
activeOpacity: 0.85,
|
|
7799
|
+
onPress,
|
|
7800
|
+
children: /* @__PURE__ */ jsx24(Text22, { style: styles21.placeBetText, children: "Place Bet" })
|
|
7801
|
+
}
|
|
7802
|
+
)
|
|
7803
|
+
] })
|
|
7804
|
+
]
|
|
7805
|
+
}
|
|
7806
|
+
);
|
|
7807
|
+
}
|
|
7808
|
+
var styles21 = StyleSheet22.create({
|
|
7809
|
+
card: {
|
|
7810
|
+
borderRadius: 16,
|
|
7811
|
+
borderWidth: 1,
|
|
7812
|
+
borderColor: "rgba(34, 197, 94, 0.2)",
|
|
7813
|
+
backgroundColor: "#0c0c14",
|
|
7814
|
+
overflow: "hidden",
|
|
7815
|
+
position: "relative"
|
|
7816
|
+
},
|
|
7817
|
+
gradientBg: {
|
|
7818
|
+
...StyleSheet22.absoluteFillObject,
|
|
7819
|
+
backgroundColor: "rgba(34, 197, 94, 0.04)"
|
|
7820
|
+
},
|
|
7821
|
+
shimmer: {
|
|
7822
|
+
position: "absolute",
|
|
7823
|
+
top: 0,
|
|
7824
|
+
bottom: 0,
|
|
7825
|
+
width: 120,
|
|
7826
|
+
backgroundColor: "rgba(34, 197, 94, 0.08)"
|
|
7827
|
+
},
|
|
7828
|
+
accentBar: {
|
|
7829
|
+
position: "absolute",
|
|
7830
|
+
bottom: 0,
|
|
7831
|
+
left: 0,
|
|
7832
|
+
right: "40%",
|
|
7833
|
+
height: 2,
|
|
7834
|
+
backgroundColor: "#22c55e"
|
|
7835
|
+
},
|
|
7836
|
+
content: {
|
|
7837
|
+
padding: 16,
|
|
7838
|
+
gap: 12
|
|
7839
|
+
},
|
|
7840
|
+
// Status row
|
|
7841
|
+
statusRow: {
|
|
7842
|
+
flexDirection: "row",
|
|
7843
|
+
alignItems: "center",
|
|
7844
|
+
gap: 8
|
|
7845
|
+
},
|
|
7846
|
+
statusBadge: {
|
|
7847
|
+
flexDirection: "row",
|
|
7848
|
+
alignItems: "center",
|
|
7849
|
+
gap: 6,
|
|
7850
|
+
paddingHorizontal: 10,
|
|
7851
|
+
paddingVertical: 4,
|
|
7852
|
+
borderRadius: 100
|
|
7853
|
+
},
|
|
7854
|
+
statusOpen: {
|
|
7855
|
+
backgroundColor: "rgba(34, 197, 94, 0.15)"
|
|
7856
|
+
},
|
|
7857
|
+
statusClosed: {
|
|
7858
|
+
backgroundColor: "rgba(156, 163, 175, 0.15)"
|
|
7859
|
+
},
|
|
7860
|
+
statusDot: {
|
|
7861
|
+
width: 6,
|
|
7862
|
+
height: 6,
|
|
7863
|
+
borderRadius: 3,
|
|
7864
|
+
backgroundColor: "#22c55e"
|
|
7865
|
+
},
|
|
7866
|
+
statusText: {
|
|
7867
|
+
fontSize: 12,
|
|
7868
|
+
fontWeight: "700"
|
|
7869
|
+
},
|
|
7870
|
+
entryCountText: {
|
|
7871
|
+
fontSize: 12,
|
|
7872
|
+
color: "#6b6b6b",
|
|
7873
|
+
fontWeight: "500"
|
|
7874
|
+
},
|
|
7875
|
+
// Hero pot
|
|
7876
|
+
heroSection: {
|
|
7877
|
+
flexDirection: "row",
|
|
7878
|
+
alignItems: "center",
|
|
7879
|
+
justifyContent: "space-between"
|
|
7880
|
+
},
|
|
7881
|
+
potInfo: {
|
|
7882
|
+
flex: 1
|
|
7883
|
+
},
|
|
7884
|
+
jackpotLabel: {
|
|
7885
|
+
fontSize: 10,
|
|
7886
|
+
fontWeight: "600",
|
|
7887
|
+
color: "#6b6b6b",
|
|
7888
|
+
letterSpacing: 3,
|
|
7889
|
+
textTransform: "uppercase",
|
|
7890
|
+
marginBottom: 4
|
|
7891
|
+
},
|
|
7892
|
+
potValue: {
|
|
7893
|
+
fontSize: 36,
|
|
7894
|
+
fontWeight: "900",
|
|
7895
|
+
color: "#4ade80",
|
|
7896
|
+
letterSpacing: -1
|
|
7897
|
+
},
|
|
7898
|
+
potEmoji: {
|
|
7899
|
+
fontSize: 40,
|
|
7900
|
+
opacity: 0.2
|
|
7901
|
+
},
|
|
7902
|
+
// Info grid
|
|
7903
|
+
infoGrid: {
|
|
7904
|
+
flexDirection: "row",
|
|
7905
|
+
gap: 8
|
|
7906
|
+
},
|
|
7907
|
+
infoCard: {
|
|
7908
|
+
flex: 1,
|
|
7909
|
+
borderRadius: 12,
|
|
7910
|
+
borderWidth: 1,
|
|
7911
|
+
borderColor: "#1e1e2a",
|
|
7912
|
+
backgroundColor: "#0c0c14",
|
|
7913
|
+
padding: 12
|
|
7914
|
+
},
|
|
7915
|
+
infoLabel: {
|
|
7916
|
+
fontSize: 9,
|
|
7917
|
+
fontWeight: "600",
|
|
7918
|
+
color: "#6b6b6b",
|
|
7919
|
+
letterSpacing: 2,
|
|
7920
|
+
textTransform: "uppercase",
|
|
7921
|
+
marginBottom: 4
|
|
7922
|
+
},
|
|
7923
|
+
infoValue: {
|
|
7924
|
+
fontSize: 18,
|
|
7925
|
+
fontWeight: "700",
|
|
7926
|
+
color: "#FFFFFF"
|
|
7927
|
+
},
|
|
7928
|
+
// Players section
|
|
7929
|
+
playersSection: {
|
|
7930
|
+
borderRadius: 12,
|
|
7931
|
+
borderWidth: 1,
|
|
7932
|
+
borderColor: "#1e1e2a",
|
|
7933
|
+
backgroundColor: "rgba(139, 92, 246, 0.04)",
|
|
7934
|
+
padding: 12,
|
|
7935
|
+
overflow: "hidden"
|
|
7936
|
+
},
|
|
7937
|
+
playersSectionHeader: {
|
|
7938
|
+
flexDirection: "row",
|
|
7939
|
+
alignItems: "center",
|
|
7940
|
+
justifyContent: "space-between",
|
|
7941
|
+
marginBottom: 10
|
|
7942
|
+
},
|
|
7943
|
+
playersSectionTitle: {
|
|
7944
|
+
fontSize: 13,
|
|
7945
|
+
fontWeight: "600",
|
|
7946
|
+
color: "#a0a0a0"
|
|
7947
|
+
},
|
|
7948
|
+
activeCountBadge: {
|
|
7949
|
+
backgroundColor: "rgba(34, 197, 94, 0.15)",
|
|
7950
|
+
paddingHorizontal: 8,
|
|
7951
|
+
paddingVertical: 2,
|
|
7952
|
+
borderRadius: 100
|
|
7953
|
+
},
|
|
7954
|
+
activeCountText: {
|
|
7955
|
+
fontSize: 11,
|
|
7956
|
+
fontWeight: "700",
|
|
7957
|
+
color: "#22c55e"
|
|
7958
|
+
},
|
|
7959
|
+
playersCarousel: {
|
|
7960
|
+
flexDirection: "row",
|
|
7961
|
+
gap: 10
|
|
7962
|
+
},
|
|
7963
|
+
playerCard: {
|
|
7964
|
+
width: 96,
|
|
7965
|
+
borderRadius: 12,
|
|
7966
|
+
borderWidth: 1.5,
|
|
7967
|
+
borderColor: "rgba(139, 92, 246, 0.4)",
|
|
7968
|
+
backgroundColor: "rgba(139, 92, 246, 0.08)",
|
|
7969
|
+
padding: 10,
|
|
7970
|
+
alignItems: "center",
|
|
7971
|
+
gap: 4
|
|
7972
|
+
},
|
|
7973
|
+
playerAvatar: {
|
|
7974
|
+
width: 40,
|
|
7975
|
+
height: 40,
|
|
7976
|
+
borderRadius: 20,
|
|
7977
|
+
borderWidth: 1.5,
|
|
7978
|
+
borderColor: "#8b5cf6",
|
|
7979
|
+
backgroundColor: "rgba(139, 92, 246, 0.2)",
|
|
7980
|
+
alignItems: "center",
|
|
7981
|
+
justifyContent: "center"
|
|
7982
|
+
},
|
|
7983
|
+
playerAvatarText: {
|
|
7984
|
+
fontSize: 14,
|
|
7985
|
+
fontWeight: "700",
|
|
7986
|
+
color: "#a78bfa"
|
|
7987
|
+
},
|
|
7988
|
+
playerWallet: {
|
|
7989
|
+
fontSize: 10,
|
|
7990
|
+
fontWeight: "500",
|
|
7991
|
+
color: "#a0a0a0",
|
|
7992
|
+
width: "100%",
|
|
7993
|
+
textAlign: "center"
|
|
7994
|
+
},
|
|
7995
|
+
playerWager: {
|
|
7996
|
+
fontSize: 12,
|
|
7997
|
+
fontWeight: "600",
|
|
7998
|
+
color: "#a78bfa"
|
|
7999
|
+
},
|
|
8000
|
+
playerOdds: {
|
|
8001
|
+
fontSize: 10,
|
|
8002
|
+
fontWeight: "700",
|
|
8003
|
+
color: "#22c55e"
|
|
8004
|
+
},
|
|
8005
|
+
playerCardMore: {
|
|
8006
|
+
width: 96,
|
|
8007
|
+
borderRadius: 12,
|
|
8008
|
+
borderWidth: 1.5,
|
|
8009
|
+
borderColor: "#1e1e2a",
|
|
8010
|
+
backgroundColor: "#14141e",
|
|
8011
|
+
alignItems: "center",
|
|
8012
|
+
justifyContent: "center"
|
|
8013
|
+
},
|
|
8014
|
+
playerMoreText: {
|
|
8015
|
+
fontSize: 16,
|
|
8016
|
+
fontWeight: "700",
|
|
8017
|
+
color: "#6b6b6b"
|
|
8018
|
+
},
|
|
8019
|
+
// Place bet CTA
|
|
8020
|
+
placeBetButton: {
|
|
8021
|
+
height: 52,
|
|
8022
|
+
borderRadius: 12,
|
|
8023
|
+
alignItems: "center",
|
|
8024
|
+
justifyContent: "center",
|
|
8025
|
+
backgroundColor: "#22c55e",
|
|
8026
|
+
shadowColor: "#22c55e",
|
|
8027
|
+
shadowOffset: { width: 0, height: 4 },
|
|
8028
|
+
shadowOpacity: 0.25,
|
|
8029
|
+
shadowRadius: 12,
|
|
8030
|
+
elevation: 6
|
|
8031
|
+
},
|
|
8032
|
+
placeBetText: {
|
|
8033
|
+
color: "#FFFFFF",
|
|
8034
|
+
fontSize: 16,
|
|
8035
|
+
fontWeight: "700"
|
|
8036
|
+
}
|
|
8037
|
+
});
|
|
8038
|
+
|
|
8039
|
+
// src/ui/jackpot/JackpotSheet.tsx
|
|
8040
|
+
import { useState as useState39, useEffect as useEffect27, useRef as useRef16, useCallback as useCallback34 } from "react";
|
|
8041
|
+
import {
|
|
8042
|
+
View as View22,
|
|
8043
|
+
Text as Text23,
|
|
8044
|
+
TouchableOpacity as TouchableOpacity18,
|
|
8045
|
+
ActivityIndicator as ActivityIndicator12,
|
|
8046
|
+
Modal as Modal8,
|
|
8047
|
+
Animated as Animated10,
|
|
8048
|
+
StyleSheet as StyleSheet23,
|
|
8049
|
+
ScrollView as ScrollView5,
|
|
8050
|
+
FlatList as FlatList2,
|
|
8051
|
+
TextInput as TextInput3,
|
|
8052
|
+
Platform as Platform13
|
|
8053
|
+
} from "react-native";
|
|
8054
|
+
import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
8055
|
+
var STATUS_LABELS7 = {
|
|
8056
|
+
building: "Building transaction...",
|
|
8057
|
+
signing: "Approve in wallet...",
|
|
8058
|
+
confirming: "Confirming entry...",
|
|
8059
|
+
success: "You're in! \u{1F3C6}"
|
|
8060
|
+
};
|
|
8061
|
+
var QUICK_AMOUNTS = [0.1, 0.5, 1];
|
|
8062
|
+
function formatSOL2(lamports) {
|
|
8063
|
+
const val = typeof lamports === "string" ? parseInt(lamports, 10) : lamports;
|
|
8064
|
+
if (isNaN(val) || val === 0) return "0";
|
|
8065
|
+
const sol = val / 1e9;
|
|
8066
|
+
if (sol >= 100) return sol.toFixed(0);
|
|
8067
|
+
if (sol >= 1) return sol.toFixed(2);
|
|
8068
|
+
if (sol >= 0.01) return sol.toFixed(3);
|
|
8069
|
+
return sol.toFixed(4);
|
|
8070
|
+
}
|
|
8071
|
+
function truncateWallet3(addr) {
|
|
8072
|
+
if (!addr || addr.length < 8) return addr || "";
|
|
8073
|
+
return `${addr.slice(0, 4)}...${addr.slice(-4)}`;
|
|
8074
|
+
}
|
|
8075
|
+
function JackpotSheet({
|
|
8076
|
+
visible,
|
|
8077
|
+
onDismiss,
|
|
8078
|
+
onSuccess,
|
|
8079
|
+
onError,
|
|
8080
|
+
minEntry = 0.01,
|
|
8081
|
+
maxEntry = 10
|
|
8082
|
+
}) {
|
|
8083
|
+
const t = useDubsTheme();
|
|
8084
|
+
const { wallet, client } = useDubs();
|
|
8085
|
+
const { round, lastWinner, refetch } = useJackpot();
|
|
8086
|
+
const mutation = useEnterJackpot();
|
|
8087
|
+
const [betAmount, setBetAmount] = useState39("0.1");
|
|
8088
|
+
const [entries, setEntries] = useState39([]);
|
|
8089
|
+
const overlayOpacity = useRef16(new Animated10.Value(0)).current;
|
|
8090
|
+
useEffect27(() => {
|
|
8091
|
+
Animated10.timing(overlayOpacity, {
|
|
8092
|
+
toValue: visible ? 1 : 0,
|
|
8093
|
+
duration: 250,
|
|
8094
|
+
useNativeDriver: true
|
|
8095
|
+
}).start();
|
|
8096
|
+
}, [visible, overlayOpacity]);
|
|
8097
|
+
useEffect27(() => {
|
|
8098
|
+
if (visible) {
|
|
8099
|
+
mutation.reset();
|
|
8100
|
+
setBetAmount("0.1");
|
|
8101
|
+
refetch();
|
|
8102
|
+
client.getJackpotEntries().then((res) => setEntries(res.entries)).catch(() => {
|
|
8103
|
+
});
|
|
8104
|
+
}
|
|
8105
|
+
}, [visible]);
|
|
8106
|
+
useEffect27(() => {
|
|
8107
|
+
if (mutation.status === "success" && mutation.data) {
|
|
8108
|
+
onSuccess?.(mutation.data);
|
|
8109
|
+
refetch();
|
|
8110
|
+
client.getJackpotEntries().then((res) => setEntries(res.entries)).catch(() => {
|
|
8111
|
+
});
|
|
8112
|
+
const timer = setTimeout(() => onDismiss(), 2500);
|
|
8113
|
+
return () => clearTimeout(timer);
|
|
8114
|
+
}
|
|
8115
|
+
}, [mutation.status, mutation.data]);
|
|
8116
|
+
useEffect27(() => {
|
|
8117
|
+
if (mutation.status === "error" && mutation.error) {
|
|
8118
|
+
onError?.(mutation.error);
|
|
8119
|
+
}
|
|
8120
|
+
}, [mutation.status, mutation.error]);
|
|
8121
|
+
const potSol = round ? Number(BigInt(round.totalPotLamports || "0")) / 1e9 : 0;
|
|
8122
|
+
const totalWeight = round ? Number(BigInt(round.totalWeight || "0")) : 0;
|
|
8123
|
+
const betSol = parseFloat(betAmount) || 0;
|
|
8124
|
+
const entryLamports = Math.round(betSol * 1e9);
|
|
8125
|
+
const userOdds = totalWeight > 0 ? (entryLamports / (totalWeight + entryLamports) * 100).toFixed(1) : entries.length === 0 ? "100.0" : "0.0";
|
|
8126
|
+
const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
|
|
8127
|
+
const canEnter = !isMutating && mutation.status !== "success" && round?.status === "Open" && betSol >= minEntry;
|
|
8128
|
+
const handleQuickAdd = useCallback34((amount) => {
|
|
8129
|
+
setBetAmount((prev) => {
|
|
8130
|
+
const current = parseFloat(prev) || 0;
|
|
8131
|
+
const next = Math.min(current + amount, maxEntry);
|
|
8132
|
+
return next.toFixed(2);
|
|
8133
|
+
});
|
|
8134
|
+
}, [maxEntry]);
|
|
8135
|
+
const handleEnter = useCallback34(async () => {
|
|
8136
|
+
if (!wallet.publicKey || entryLamports < 1e4) return;
|
|
8137
|
+
try {
|
|
8138
|
+
await mutation.execute(entryLamports);
|
|
8139
|
+
} catch {
|
|
8140
|
+
}
|
|
8141
|
+
}, [wallet.publicKey, mutation.execute, entryLamports]);
|
|
8142
|
+
const statusLabel = STATUS_LABELS7[mutation.status] || "";
|
|
8143
|
+
const renderPlayerCard = ({ item, index }) => /* @__PURE__ */ jsxs22(View22, { style: styles22.playerCard, children: [
|
|
8144
|
+
/* @__PURE__ */ jsx25(View22, { style: styles22.playerAvatar, children: /* @__PURE__ */ jsx25(Text23, { style: styles22.playerAvatarText, children: item.player.slice(0, 2).toUpperCase() }) }),
|
|
8145
|
+
/* @__PURE__ */ jsxs22(Text23, { style: styles22.playerUsername, numberOfLines: 1, children: [
|
|
8146
|
+
"@",
|
|
8147
|
+
truncateWallet3(item.player)
|
|
8148
|
+
] }),
|
|
8149
|
+
/* @__PURE__ */ jsx25(View22, { style: styles22.playerWagerRow, children: /* @__PURE__ */ jsxs22(Text23, { style: styles22.playerWagerAmount, children: [
|
|
8150
|
+
item.weightSol.toFixed(2),
|
|
8151
|
+
" SOL"
|
|
8152
|
+
] }) }),
|
|
8153
|
+
/* @__PURE__ */ jsxs22(Text23, { style: styles22.playerOdds, children: [
|
|
8154
|
+
item.oddsPercent,
|
|
8155
|
+
"%"
|
|
8156
|
+
] })
|
|
8157
|
+
] });
|
|
8158
|
+
return /* @__PURE__ */ jsxs22(
|
|
8159
|
+
Modal8,
|
|
8160
|
+
{
|
|
8161
|
+
visible,
|
|
8162
|
+
animationType: "slide",
|
|
8163
|
+
transparent: true,
|
|
8164
|
+
onRequestClose: onDismiss,
|
|
8165
|
+
children: [
|
|
8166
|
+
/* @__PURE__ */ jsx25(Animated10.View, { style: [styles22.overlay, { opacity: overlayOpacity }], children: /* @__PURE__ */ jsx25(TouchableOpacity18, { style: styles22.overlayTap, activeOpacity: 1, onPress: onDismiss }) }),
|
|
8167
|
+
/* @__PURE__ */ jsx25(View22, { style: styles22.sheetPositioner, children: /* @__PURE__ */ jsxs22(View22, { style: styles22.sheet, children: [
|
|
8168
|
+
/* @__PURE__ */ jsx25(View22, { style: styles22.handleRow, children: /* @__PURE__ */ jsx25(View22, { style: styles22.handle }) }),
|
|
8169
|
+
/* @__PURE__ */ jsxs22(
|
|
8170
|
+
ScrollView5,
|
|
8171
|
+
{
|
|
8172
|
+
style: styles22.scrollView,
|
|
8173
|
+
contentContainerStyle: styles22.scrollContent,
|
|
8174
|
+
showsVerticalScrollIndicator: false,
|
|
8175
|
+
bounces: true,
|
|
8176
|
+
children: [
|
|
8177
|
+
/* @__PURE__ */ jsxs22(View22, { style: styles22.header, children: [
|
|
8178
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.headerTitle, children: "Jackpot" }),
|
|
8179
|
+
/* @__PURE__ */ jsx25(TouchableOpacity18, { onPress: onDismiss, activeOpacity: 0.8, style: styles22.closeBtn, children: /* @__PURE__ */ jsx25(Text23, { style: styles22.closeBtnText, children: "\u2715" }) })
|
|
8180
|
+
] }),
|
|
8181
|
+
/* @__PURE__ */ jsxs22(View22, { style: styles22.heroCard, children: [
|
|
8182
|
+
/* @__PURE__ */ jsx25(View22, { style: styles22.heroGradient }),
|
|
8183
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.heroLabel, children: "JACKPOT" }),
|
|
8184
|
+
/* @__PURE__ */ jsxs22(View22, { style: styles22.heroPotRow, children: [
|
|
8185
|
+
/* @__PURE__ */ jsxs22(Text23, { style: styles22.heroPotValue, children: [
|
|
8186
|
+
potSol.toFixed(4),
|
|
8187
|
+
" SOL"
|
|
8188
|
+
] }),
|
|
8189
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.heroEmoji, children: "\u{1F911}" })
|
|
8190
|
+
] }),
|
|
8191
|
+
/* @__PURE__ */ jsx25(View22, { style: styles22.heroAccentBar })
|
|
8192
|
+
] }),
|
|
8193
|
+
/* @__PURE__ */ jsxs22(View22, { style: styles22.infoRow, children: [
|
|
8194
|
+
/* @__PURE__ */ jsxs22(View22, { style: styles22.infoCard, children: [
|
|
8195
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.infoCardLabel, children: "YOUR WAGER" }),
|
|
8196
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.infoCardValue, children: betSol.toFixed(2) })
|
|
8197
|
+
] }),
|
|
8198
|
+
/* @__PURE__ */ jsxs22(View22, { style: styles22.infoCard, children: [
|
|
8199
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.infoCardLabel, children: "YOUR CHANCE" }),
|
|
8200
|
+
/* @__PURE__ */ jsxs22(Text23, { style: [styles22.infoCardValue, { color: "#22c55e" }], children: [
|
|
8201
|
+
userOdds,
|
|
8202
|
+
"%"
|
|
8203
|
+
] })
|
|
8204
|
+
] }),
|
|
8205
|
+
/* @__PURE__ */ jsxs22(View22, { style: styles22.infoCard, children: [
|
|
8206
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.infoCardLabel, children: "PLAYERS" }),
|
|
8207
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.infoCardValue, children: entries.length })
|
|
8208
|
+
] })
|
|
8209
|
+
] }),
|
|
8210
|
+
entries.length > 0 && /* @__PURE__ */ jsxs22(View22, { style: styles22.playersSection, children: [
|
|
8211
|
+
/* @__PURE__ */ jsxs22(View22, { style: styles22.playersSectionHeader, children: [
|
|
8212
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.playersSectionTitle, children: "Players in Round" }),
|
|
8213
|
+
/* @__PURE__ */ jsxs22(View22, { style: styles22.playersBadge, children: [
|
|
8214
|
+
/* @__PURE__ */ jsx25(View22, { style: styles22.playersBadgeDot }),
|
|
8215
|
+
/* @__PURE__ */ jsxs22(Text23, { style: styles22.playersBadgeText, children: [
|
|
8216
|
+
entries.length,
|
|
8217
|
+
" active"
|
|
8218
|
+
] })
|
|
8219
|
+
] })
|
|
8220
|
+
] }),
|
|
8221
|
+
/* @__PURE__ */ jsx25(
|
|
8222
|
+
FlatList2,
|
|
8223
|
+
{
|
|
8224
|
+
data: entries,
|
|
8225
|
+
renderItem: renderPlayerCard,
|
|
8226
|
+
keyExtractor: (item, i) => `${item.player}-${i}`,
|
|
8227
|
+
horizontal: true,
|
|
8228
|
+
showsHorizontalScrollIndicator: false,
|
|
8229
|
+
contentContainerStyle: styles22.playersListContent,
|
|
8230
|
+
ItemSeparatorComponent: () => /* @__PURE__ */ jsx25(View22, { style: { width: 10 } })
|
|
8231
|
+
}
|
|
8232
|
+
)
|
|
8233
|
+
] }),
|
|
8234
|
+
entries.length === 0 && /* @__PURE__ */ jsxs22(View22, { style: styles22.emptyState, children: [
|
|
8235
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.emptyEmoji, children: "\u{1F911}" }),
|
|
8236
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.emptyTitle, children: "No players yet" }),
|
|
8237
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.emptySubtitle, children: "Be the first to join!" })
|
|
8238
|
+
] }),
|
|
8239
|
+
/* @__PURE__ */ jsxs22(View22, { style: styles22.betSection, children: [
|
|
8240
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.betLabel, children: "Bet Amount" }),
|
|
8241
|
+
/* @__PURE__ */ jsxs22(View22, { style: styles22.betInputRow, children: [
|
|
8242
|
+
/* @__PURE__ */ jsx25(View22, { style: styles22.solIcon, children: /* @__PURE__ */ jsx25(Text23, { style: styles22.solIconText, children: "\u25CE" }) }),
|
|
8243
|
+
/* @__PURE__ */ jsx25(
|
|
8244
|
+
TextInput3,
|
|
8245
|
+
{
|
|
8246
|
+
style: styles22.betInput,
|
|
8247
|
+
value: betAmount,
|
|
8248
|
+
onChangeText: setBetAmount,
|
|
8249
|
+
keyboardType: "decimal-pad",
|
|
8250
|
+
placeholder: "0.00",
|
|
8251
|
+
placeholderTextColor: "#6b6b6b",
|
|
8252
|
+
selectTextOnFocus: true
|
|
8253
|
+
}
|
|
8254
|
+
),
|
|
8255
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.betInputSuffix, children: "SOL" })
|
|
8256
|
+
] }),
|
|
8257
|
+
/* @__PURE__ */ jsx25(View22, { style: styles22.quickBetRow, children: QUICK_AMOUNTS.map((amount) => /* @__PURE__ */ jsx25(
|
|
8258
|
+
TouchableOpacity18,
|
|
8259
|
+
{
|
|
8260
|
+
style: styles22.quickBetBtn,
|
|
8261
|
+
onPress: () => handleQuickAdd(amount),
|
|
8262
|
+
activeOpacity: 0.7,
|
|
8263
|
+
children: /* @__PURE__ */ jsxs22(Text23, { style: styles22.quickBetText, children: [
|
|
8264
|
+
"+",
|
|
8265
|
+
amount,
|
|
8266
|
+
" SOL"
|
|
8267
|
+
] })
|
|
8268
|
+
},
|
|
8269
|
+
amount
|
|
8270
|
+
)) })
|
|
8271
|
+
] }),
|
|
8272
|
+
mutation.error && /* @__PURE__ */ jsx25(View22, { style: styles22.errorBox, children: /* @__PURE__ */ jsx25(Text23, { style: styles22.errorText, children: mutation.error.message }) }),
|
|
8273
|
+
/* @__PURE__ */ jsx25(
|
|
8274
|
+
TouchableOpacity18,
|
|
8275
|
+
{
|
|
8276
|
+
style: [
|
|
8277
|
+
styles22.placeBetBtn,
|
|
8278
|
+
!canEnter && styles22.placeBetBtnDisabled,
|
|
8279
|
+
mutation.status === "success" && styles22.placeBetBtnSuccess
|
|
8280
|
+
],
|
|
8281
|
+
disabled: !canEnter,
|
|
8282
|
+
onPress: handleEnter,
|
|
8283
|
+
activeOpacity: 0.85,
|
|
8284
|
+
children: isMutating ? /* @__PURE__ */ jsxs22(View22, { style: styles22.placeBetLoading, children: [
|
|
8285
|
+
/* @__PURE__ */ jsx25(ActivityIndicator12, { size: "small", color: "#FFFFFF" }),
|
|
8286
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.placeBetText, children: statusLabel })
|
|
8287
|
+
] }) : mutation.status === "success" ? /* @__PURE__ */ jsx25(Text23, { style: styles22.placeBetText, children: "You're in! \u{1F3C6}" }) : /* @__PURE__ */ jsxs22(Text23, { style: [styles22.placeBetText, !canEnter && { opacity: 0.5 }], children: [
|
|
8288
|
+
"Place Bet \u2014 ",
|
|
8289
|
+
betSol.toFixed(2),
|
|
8290
|
+
" SOL"
|
|
8291
|
+
] })
|
|
8292
|
+
}
|
|
8293
|
+
),
|
|
8294
|
+
lastWinner && /* @__PURE__ */ jsxs22(View22, { style: styles22.lastWinnerSection, children: [
|
|
8295
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.lastWinnerLabel, children: "Last Winner" }),
|
|
8296
|
+
/* @__PURE__ */ jsxs22(View22, { style: styles22.lastWinnerRow, children: [
|
|
8297
|
+
/* @__PURE__ */ jsx25(Text23, { style: styles22.lastWinnerWallet, children: truncateWallet3(lastWinner.winner) }),
|
|
8298
|
+
/* @__PURE__ */ jsxs22(Text23, { style: styles22.lastWinnerAmount, children: [
|
|
8299
|
+
"won ",
|
|
8300
|
+
formatSOL2(lastWinner.winAmount),
|
|
8301
|
+
" SOL"
|
|
8302
|
+
] })
|
|
8303
|
+
] })
|
|
8304
|
+
] })
|
|
8305
|
+
]
|
|
8306
|
+
}
|
|
8307
|
+
)
|
|
8308
|
+
] }) })
|
|
8309
|
+
]
|
|
8310
|
+
}
|
|
8311
|
+
);
|
|
8312
|
+
}
|
|
8313
|
+
var styles22 = StyleSheet23.create({
|
|
8314
|
+
overlay: {
|
|
8315
|
+
...StyleSheet23.absoluteFillObject,
|
|
8316
|
+
backgroundColor: "rgba(0,0,0,0.65)"
|
|
8317
|
+
},
|
|
8318
|
+
overlayTap: { flex: 1 },
|
|
8319
|
+
sheetPositioner: {
|
|
8320
|
+
flex: 1,
|
|
8321
|
+
justifyContent: "flex-end"
|
|
8322
|
+
},
|
|
8323
|
+
sheet: {
|
|
8324
|
+
backgroundColor: "#08080e",
|
|
8325
|
+
borderTopLeftRadius: 24,
|
|
8326
|
+
borderTopRightRadius: 24,
|
|
8327
|
+
maxHeight: "92%",
|
|
8328
|
+
borderWidth: 1,
|
|
8329
|
+
borderColor: "#1e1e2a",
|
|
8330
|
+
borderBottomWidth: 0
|
|
8331
|
+
},
|
|
8332
|
+
handleRow: { alignItems: "center", paddingTop: 10, paddingBottom: 4 },
|
|
8333
|
+
handle: { width: 36, height: 4, borderRadius: 2, backgroundColor: "#2a2a3a" },
|
|
8334
|
+
scrollView: { flexGrow: 0 },
|
|
8335
|
+
scrollContent: {
|
|
8336
|
+
paddingHorizontal: 16,
|
|
8337
|
+
paddingBottom: Platform13.OS === "ios" ? 40 : 24
|
|
8338
|
+
},
|
|
8339
|
+
// Header
|
|
8340
|
+
header: {
|
|
8341
|
+
flexDirection: "row",
|
|
8342
|
+
alignItems: "center",
|
|
8343
|
+
justifyContent: "space-between",
|
|
8344
|
+
paddingVertical: 12
|
|
8345
|
+
},
|
|
8346
|
+
headerTitle: { fontSize: 20, fontWeight: "700", color: "#FFFFFF" },
|
|
8347
|
+
closeBtn: { padding: 4 },
|
|
8348
|
+
closeBtnText: { fontSize: 20, color: "#6b6b6b" },
|
|
8349
|
+
// Hero pot card
|
|
8350
|
+
heroCard: {
|
|
8351
|
+
borderRadius: 16,
|
|
8352
|
+
borderWidth: 1,
|
|
8353
|
+
borderColor: "rgba(34, 197, 94, 0.2)",
|
|
8354
|
+
padding: 16,
|
|
8355
|
+
overflow: "hidden",
|
|
8356
|
+
position: "relative"
|
|
8357
|
+
},
|
|
8358
|
+
heroGradient: {
|
|
8359
|
+
...StyleSheet23.absoluteFillObject,
|
|
8360
|
+
backgroundColor: "rgba(34, 197, 94, 0.04)"
|
|
8361
|
+
},
|
|
8362
|
+
heroLabel: {
|
|
8363
|
+
fontSize: 10,
|
|
8364
|
+
fontWeight: "600",
|
|
8365
|
+
color: "#6b6b6b",
|
|
8366
|
+
letterSpacing: 3,
|
|
8367
|
+
marginBottom: 4
|
|
8368
|
+
},
|
|
8369
|
+
heroPotRow: {
|
|
8370
|
+
flexDirection: "row",
|
|
8371
|
+
alignItems: "center",
|
|
8372
|
+
justifyContent: "space-between"
|
|
8373
|
+
},
|
|
8374
|
+
heroPotValue: {
|
|
8375
|
+
fontSize: 32,
|
|
8376
|
+
fontWeight: "900",
|
|
8377
|
+
color: "#4ade80",
|
|
8378
|
+
letterSpacing: -1
|
|
8379
|
+
},
|
|
8380
|
+
heroEmoji: {
|
|
8381
|
+
fontSize: 36,
|
|
8382
|
+
opacity: 0.2
|
|
8383
|
+
},
|
|
8384
|
+
heroAccentBar: {
|
|
8385
|
+
position: "absolute",
|
|
8386
|
+
bottom: 0,
|
|
8387
|
+
left: 0,
|
|
8388
|
+
width: "60%",
|
|
8389
|
+
height: 2,
|
|
8390
|
+
backgroundColor: "#22c55e"
|
|
8391
|
+
},
|
|
8392
|
+
// Info row
|
|
8393
|
+
infoRow: {
|
|
8394
|
+
flexDirection: "row",
|
|
8395
|
+
gap: 8,
|
|
8396
|
+
marginTop: 12
|
|
8397
|
+
},
|
|
8398
|
+
infoCard: {
|
|
8399
|
+
flex: 1,
|
|
8400
|
+
borderRadius: 12,
|
|
8401
|
+
borderWidth: 1,
|
|
8402
|
+
borderColor: "#1e1e2a",
|
|
8403
|
+
backgroundColor: "#0c0c14",
|
|
8404
|
+
padding: 12
|
|
8405
|
+
},
|
|
8406
|
+
infoCardLabel: {
|
|
8407
|
+
fontSize: 9,
|
|
8408
|
+
fontWeight: "600",
|
|
8409
|
+
color: "#6b6b6b",
|
|
8410
|
+
letterSpacing: 2,
|
|
8411
|
+
marginBottom: 4
|
|
8412
|
+
},
|
|
8413
|
+
infoCardValue: {
|
|
8414
|
+
fontSize: 18,
|
|
8415
|
+
fontWeight: "700",
|
|
8416
|
+
color: "#FFFFFF"
|
|
8417
|
+
},
|
|
8418
|
+
// Players section
|
|
8419
|
+
playersSection: {
|
|
8420
|
+
marginTop: 16,
|
|
8421
|
+
borderRadius: 16,
|
|
8422
|
+
borderWidth: 1,
|
|
8423
|
+
borderColor: "#1e1e2a",
|
|
8424
|
+
backgroundColor: "rgba(139, 92, 246, 0.03)",
|
|
8425
|
+
padding: 12,
|
|
8426
|
+
overflow: "hidden"
|
|
8427
|
+
},
|
|
8428
|
+
playersSectionHeader: {
|
|
8429
|
+
flexDirection: "row",
|
|
8430
|
+
alignItems: "center",
|
|
8431
|
+
justifyContent: "space-between",
|
|
8432
|
+
marginBottom: 12
|
|
8433
|
+
},
|
|
8434
|
+
playersSectionTitle: {
|
|
8435
|
+
fontSize: 13,
|
|
8436
|
+
fontWeight: "600",
|
|
8437
|
+
color: "#a0a0a0"
|
|
8438
|
+
},
|
|
8439
|
+
playersBadge: {
|
|
8440
|
+
flexDirection: "row",
|
|
8441
|
+
alignItems: "center",
|
|
8442
|
+
gap: 6,
|
|
8443
|
+
backgroundColor: "rgba(34, 197, 94, 0.15)",
|
|
8444
|
+
paddingHorizontal: 8,
|
|
8445
|
+
paddingVertical: 3,
|
|
8446
|
+
borderRadius: 100
|
|
8447
|
+
},
|
|
8448
|
+
playersBadgeDot: {
|
|
8449
|
+
width: 6,
|
|
8450
|
+
height: 6,
|
|
8451
|
+
borderRadius: 3,
|
|
8452
|
+
backgroundColor: "#22c55e"
|
|
8453
|
+
},
|
|
8454
|
+
playersBadgeText: {
|
|
8455
|
+
fontSize: 11,
|
|
8456
|
+
fontWeight: "700",
|
|
8457
|
+
color: "#22c55e"
|
|
8458
|
+
},
|
|
8459
|
+
playersListContent: {
|
|
8460
|
+
paddingRight: 4
|
|
8461
|
+
},
|
|
8462
|
+
// Player cards (carousel items)
|
|
8463
|
+
playerCard: {
|
|
8464
|
+
width: 110,
|
|
8465
|
+
borderRadius: 12,
|
|
8466
|
+
borderWidth: 1.5,
|
|
8467
|
+
borderColor: "rgba(139, 92, 246, 0.4)",
|
|
8468
|
+
backgroundColor: "rgba(139, 92, 246, 0.08)",
|
|
8469
|
+
padding: 12,
|
|
8470
|
+
alignItems: "center",
|
|
8471
|
+
gap: 6
|
|
8472
|
+
},
|
|
8473
|
+
playerAvatar: {
|
|
8474
|
+
width: 48,
|
|
8475
|
+
height: 48,
|
|
8476
|
+
borderRadius: 24,
|
|
8477
|
+
borderWidth: 2,
|
|
8478
|
+
borderColor: "#8b5cf6",
|
|
8479
|
+
backgroundColor: "rgba(139, 92, 246, 0.15)",
|
|
8480
|
+
alignItems: "center",
|
|
8481
|
+
justifyContent: "center"
|
|
8482
|
+
},
|
|
8483
|
+
playerAvatarText: {
|
|
8484
|
+
fontSize: 16,
|
|
8485
|
+
fontWeight: "700",
|
|
8486
|
+
color: "#a78bfa"
|
|
8487
|
+
},
|
|
8488
|
+
playerUsername: {
|
|
8489
|
+
fontSize: 11,
|
|
8490
|
+
fontWeight: "500",
|
|
8491
|
+
color: "#a0a0a0",
|
|
8492
|
+
textAlign: "center"
|
|
8493
|
+
},
|
|
8494
|
+
playerWagerRow: {
|
|
8495
|
+
flexDirection: "row",
|
|
8496
|
+
alignItems: "center",
|
|
8497
|
+
gap: 4
|
|
8498
|
+
},
|
|
8499
|
+
playerWagerAmount: {
|
|
8500
|
+
fontSize: 13,
|
|
8501
|
+
fontWeight: "600",
|
|
8502
|
+
color: "#a78bfa"
|
|
8503
|
+
},
|
|
8504
|
+
playerOdds: {
|
|
8505
|
+
fontSize: 11,
|
|
8506
|
+
fontWeight: "700",
|
|
8507
|
+
color: "#22c55e"
|
|
8508
|
+
},
|
|
8509
|
+
// Empty state
|
|
8510
|
+
emptyState: {
|
|
8511
|
+
marginTop: 16,
|
|
8512
|
+
alignItems: "center",
|
|
8513
|
+
paddingVertical: 24,
|
|
8514
|
+
borderRadius: 16,
|
|
8515
|
+
borderWidth: 1,
|
|
8516
|
+
borderColor: "#1e1e2a",
|
|
8517
|
+
backgroundColor: "#0c0c14"
|
|
8518
|
+
},
|
|
8519
|
+
emptyEmoji: { fontSize: 40, marginBottom: 8 },
|
|
8520
|
+
emptyTitle: { fontSize: 16, fontWeight: "600", color: "#FFFFFF" },
|
|
8521
|
+
emptySubtitle: { fontSize: 13, color: "#6b6b6b", marginTop: 4 },
|
|
8522
|
+
// Bet section
|
|
8523
|
+
betSection: {
|
|
8524
|
+
marginTop: 16
|
|
8525
|
+
},
|
|
8526
|
+
betLabel: {
|
|
8527
|
+
fontSize: 13,
|
|
8528
|
+
fontWeight: "500",
|
|
8529
|
+
color: "#6b6b6b",
|
|
8530
|
+
marginBottom: 8
|
|
8531
|
+
},
|
|
8532
|
+
betInputRow: {
|
|
8533
|
+
flexDirection: "row",
|
|
8534
|
+
alignItems: "center",
|
|
8535
|
+
gap: 8,
|
|
8536
|
+
backgroundColor: "#08080e",
|
|
8537
|
+
borderWidth: 1,
|
|
8538
|
+
borderColor: "#2a2a3a",
|
|
8539
|
+
borderRadius: 12,
|
|
8540
|
+
paddingHorizontal: 14,
|
|
8541
|
+
paddingVertical: Platform13.OS === "ios" ? 14 : 10
|
|
8542
|
+
},
|
|
8543
|
+
solIcon: {
|
|
8544
|
+
width: 32,
|
|
8545
|
+
height: 32,
|
|
8546
|
+
borderRadius: 16,
|
|
8547
|
+
backgroundColor: "rgba(139, 92, 246, 0.15)",
|
|
8548
|
+
alignItems: "center",
|
|
8549
|
+
justifyContent: "center"
|
|
8550
|
+
},
|
|
8551
|
+
solIconText: {
|
|
8552
|
+
fontSize: 18,
|
|
8553
|
+
color: "#a78bfa",
|
|
8554
|
+
fontWeight: "700"
|
|
8555
|
+
},
|
|
8556
|
+
betInput: {
|
|
8557
|
+
flex: 1,
|
|
8558
|
+
fontSize: 24,
|
|
8559
|
+
fontWeight: "700",
|
|
8560
|
+
color: "#FFFFFF",
|
|
8561
|
+
padding: 0
|
|
8562
|
+
},
|
|
8563
|
+
betInputSuffix: {
|
|
8564
|
+
fontSize: 14,
|
|
8565
|
+
fontWeight: "500",
|
|
8566
|
+
color: "#6b6b6b"
|
|
8567
|
+
},
|
|
8568
|
+
quickBetRow: {
|
|
8569
|
+
flexDirection: "row",
|
|
8570
|
+
gap: 8,
|
|
8571
|
+
marginTop: 10
|
|
8572
|
+
},
|
|
8573
|
+
quickBetBtn: {
|
|
8574
|
+
flex: 1,
|
|
8575
|
+
paddingVertical: 12,
|
|
8576
|
+
borderRadius: 10,
|
|
8577
|
+
borderWidth: 1,
|
|
8578
|
+
borderColor: "#2a2a3a",
|
|
8579
|
+
backgroundColor: "#08080e",
|
|
8580
|
+
alignItems: "center"
|
|
8581
|
+
},
|
|
8582
|
+
quickBetText: {
|
|
8583
|
+
fontSize: 13,
|
|
8584
|
+
fontWeight: "600",
|
|
8585
|
+
color: "#FFFFFF"
|
|
8586
|
+
},
|
|
8587
|
+
// Error
|
|
8588
|
+
errorBox: {
|
|
8589
|
+
marginTop: 12,
|
|
8590
|
+
borderRadius: 12,
|
|
8591
|
+
borderWidth: 1,
|
|
8592
|
+
borderColor: "#3A1515",
|
|
8593
|
+
backgroundColor: "#1A0A0A",
|
|
8594
|
+
padding: 12
|
|
8595
|
+
},
|
|
8596
|
+
errorText: { fontSize: 13, fontWeight: "500", color: "#F87171" },
|
|
8597
|
+
// Place Bet CTA
|
|
8598
|
+
placeBetBtn: {
|
|
8599
|
+
marginTop: 16,
|
|
8600
|
+
height: 56,
|
|
8601
|
+
borderRadius: 14,
|
|
8602
|
+
justifyContent: "center",
|
|
8603
|
+
alignItems: "center",
|
|
8604
|
+
backgroundColor: "#22c55e",
|
|
8605
|
+
shadowColor: "#22c55e",
|
|
8606
|
+
shadowOffset: { width: 0, height: 4 },
|
|
8607
|
+
shadowOpacity: 0.25,
|
|
8608
|
+
shadowRadius: 12,
|
|
8609
|
+
elevation: 6
|
|
8610
|
+
},
|
|
8611
|
+
placeBetBtnDisabled: {
|
|
8612
|
+
backgroundColor: "#1e1e2a",
|
|
8613
|
+
shadowOpacity: 0,
|
|
8614
|
+
elevation: 0
|
|
8615
|
+
},
|
|
8616
|
+
placeBetBtnSuccess: {
|
|
8617
|
+
backgroundColor: "#16a34a"
|
|
8618
|
+
},
|
|
8619
|
+
placeBetText: { color: "#FFFFFF", fontSize: 16, fontWeight: "700" },
|
|
8620
|
+
placeBetLoading: { flexDirection: "row", alignItems: "center", gap: 10 },
|
|
8621
|
+
// Last winner
|
|
8622
|
+
lastWinnerSection: {
|
|
8623
|
+
marginTop: 14,
|
|
8624
|
+
paddingTop: 14,
|
|
8625
|
+
borderTopWidth: 1,
|
|
8626
|
+
borderTopColor: "#1e1e2a"
|
|
8627
|
+
},
|
|
8628
|
+
lastWinnerLabel: {
|
|
8629
|
+
fontSize: 11,
|
|
8630
|
+
fontWeight: "600",
|
|
8631
|
+
color: "#6b6b6b",
|
|
8632
|
+
letterSpacing: 1,
|
|
8633
|
+
textTransform: "uppercase",
|
|
8634
|
+
marginBottom: 4
|
|
8635
|
+
},
|
|
8636
|
+
lastWinnerRow: {
|
|
8637
|
+
flexDirection: "row",
|
|
8638
|
+
alignItems: "center",
|
|
8639
|
+
gap: 6
|
|
8640
|
+
},
|
|
8641
|
+
lastWinnerWallet: {
|
|
8642
|
+
fontSize: 13,
|
|
8643
|
+
fontWeight: "500",
|
|
8644
|
+
color: "#a0a0a0"
|
|
8645
|
+
},
|
|
8646
|
+
lastWinnerAmount: {
|
|
8647
|
+
fontSize: 13,
|
|
8648
|
+
fontWeight: "600",
|
|
8649
|
+
color: "#22c55e"
|
|
8650
|
+
}
|
|
8651
|
+
});
|
|
8652
|
+
|
|
8653
|
+
// src/ui/jackpot/JackpotWidget.tsx
|
|
8654
|
+
import { useState as useState40, useEffect as useEffect28 } from "react";
|
|
8655
|
+
import { Fragment as Fragment7, jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
8656
|
+
function JackpotWidget({
|
|
8657
|
+
style,
|
|
8658
|
+
minEntry,
|
|
8659
|
+
maxEntry,
|
|
8660
|
+
onEntry,
|
|
8661
|
+
onError
|
|
8662
|
+
}) {
|
|
8663
|
+
const [sheetVisible, setSheetVisible] = useState40(false);
|
|
8664
|
+
const { round, lastWinner } = useJackpot();
|
|
8665
|
+
const { client } = useDubs();
|
|
8666
|
+
const [entries, setEntries] = useState40([]);
|
|
8667
|
+
useEffect28(() => {
|
|
8668
|
+
client.getJackpotEntries().then((res) => setEntries(res.entries)).catch(() => {
|
|
8669
|
+
});
|
|
8670
|
+
}, [client, round?.entryCount]);
|
|
8671
|
+
return /* @__PURE__ */ jsxs23(Fragment7, { children: [
|
|
8672
|
+
/* @__PURE__ */ jsx26(
|
|
8673
|
+
JackpotCard,
|
|
8674
|
+
{
|
|
8675
|
+
round,
|
|
8676
|
+
lastWinner,
|
|
8677
|
+
entries,
|
|
8678
|
+
onPress: () => setSheetVisible(true),
|
|
8679
|
+
style
|
|
8680
|
+
}
|
|
8681
|
+
),
|
|
8682
|
+
/* @__PURE__ */ jsx26(
|
|
8683
|
+
JackpotSheet,
|
|
8684
|
+
{
|
|
8685
|
+
visible: sheetVisible,
|
|
8686
|
+
onDismiss: () => setSheetVisible(false),
|
|
8687
|
+
onSuccess: (result) => {
|
|
8688
|
+
onEntry?.(result);
|
|
8689
|
+
client.getJackpotEntries().then((res) => setEntries(res.entries)).catch(() => {
|
|
8690
|
+
});
|
|
8691
|
+
},
|
|
8692
|
+
onError,
|
|
8693
|
+
minEntry,
|
|
8694
|
+
maxEntry
|
|
8695
|
+
}
|
|
8696
|
+
)
|
|
8697
|
+
] });
|
|
8698
|
+
}
|
|
8699
|
+
|
|
8700
|
+
// src/chat/provider.tsx
|
|
8701
|
+
import { createContext as createContext5, useContext as useContext5, useEffect as useEffect29, useRef as useRef17, useState as useState41, useCallback as useCallback35, useMemo as useMemo11 } from "react";
|
|
8702
|
+
import { AppState } from "react-native";
|
|
8703
|
+
|
|
8704
|
+
// src/chat/socket.ts
|
|
8705
|
+
import { io } from "socket.io-client";
|
|
8706
|
+
var ChatSocket = class {
|
|
8707
|
+
constructor() {
|
|
8708
|
+
this.socket = null;
|
|
8709
|
+
this.listeners = {};
|
|
8710
|
+
}
|
|
8711
|
+
/** Set event listeners. Call before or after connect. */
|
|
8712
|
+
setListeners(listeners) {
|
|
8713
|
+
this.listeners = listeners;
|
|
8714
|
+
}
|
|
8715
|
+
/** Connect to the /chat namespace */
|
|
8716
|
+
connect(config) {
|
|
8717
|
+
if (this.socket?.connected) {
|
|
8718
|
+
console.log("[Dubs:ChatSocket] Already connected");
|
|
8719
|
+
return;
|
|
8720
|
+
}
|
|
8721
|
+
this.listeners.onConnectionChange?.("connecting");
|
|
8722
|
+
console.log(`[Dubs:ChatSocket] Connecting to ${config.host}/chat`);
|
|
8723
|
+
this.socket = io(`${config.host}/chat`, {
|
|
8724
|
+
auth: { token: config.token },
|
|
8725
|
+
transports: ["websocket"],
|
|
8726
|
+
reconnection: true,
|
|
8727
|
+
reconnectionDelay: 1e3,
|
|
8728
|
+
reconnectionAttempts: 10
|
|
8729
|
+
});
|
|
8730
|
+
this.socket.on("connect", () => {
|
|
8731
|
+
console.log("[Dubs:ChatSocket] Connected");
|
|
8732
|
+
this.listeners.onConnectionChange?.("connected");
|
|
8733
|
+
});
|
|
8734
|
+
this.socket.on("disconnect", (reason) => {
|
|
8735
|
+
console.log("[Dubs:ChatSocket] Disconnected:", reason);
|
|
8736
|
+
this.listeners.onConnectionChange?.("disconnected");
|
|
8737
|
+
});
|
|
8738
|
+
this.socket.on("connect_error", (error) => {
|
|
8739
|
+
console.error("[Dubs:ChatSocket] Connection error:", error.message);
|
|
8740
|
+
this.listeners.onConnectionChange?.("error");
|
|
8741
|
+
});
|
|
8742
|
+
this.socket.on("new_message", (msg) => this.listeners.onNewMessage?.(msg));
|
|
8743
|
+
this.socket.on("online_users", (users) => this.listeners.onOnlineUsers?.(users));
|
|
8744
|
+
this.socket.on("online_count", (count) => this.listeners.onOnlineCount?.(count));
|
|
8745
|
+
this.socket.on("user_typing", (data) => this.listeners.onTyping?.(data));
|
|
8746
|
+
this.socket.on("reaction_added", (data) => this.listeners.onReactionAdded?.(data));
|
|
8747
|
+
this.socket.on("reaction_removed", (data) => this.listeners.onReactionRemoved?.(data));
|
|
8748
|
+
this.socket.on("notification", (n) => this.listeners.onNotification?.(n));
|
|
8749
|
+
this.socket.on("unread_count", (count) => this.listeners.onUnreadCount?.(count));
|
|
8750
|
+
this.socket.on("dm:new_message", (msg) => this.listeners.onDMNewMessage?.(msg));
|
|
8751
|
+
this.socket.on("dm:message_sent", (msg) => this.listeners.onDMMessageSent?.(msg));
|
|
8752
|
+
this.socket.on("dm:notification", (data) => this.listeners.onDMNotification?.(data));
|
|
8753
|
+
this.socket.on("dm:messages_read", (data) => this.listeners.onDMMessagesRead?.(data));
|
|
8754
|
+
this.socket.on("friend_request_accepted", (data) => this.listeners.onFriendRequestAccepted?.(data));
|
|
8755
|
+
this.socket.on("friend_request_declined", (data) => this.listeners.onFriendRequestDeclined?.(data));
|
|
8756
|
+
this.socket.on("friend_removed", (data) => this.listeners.onFriendRemoved?.(data));
|
|
8757
|
+
this.socket.on("error", (err) => this.listeners.onError?.(err));
|
|
8758
|
+
}
|
|
8759
|
+
/** Disconnect from the chat namespace */
|
|
8760
|
+
disconnect() {
|
|
8761
|
+
if (this.socket) {
|
|
8762
|
+
console.log("[Dubs:ChatSocket] Disconnecting");
|
|
8763
|
+
this.socket.removeAllListeners();
|
|
8764
|
+
this.socket.disconnect();
|
|
8765
|
+
this.socket = null;
|
|
8766
|
+
}
|
|
8767
|
+
}
|
|
8768
|
+
/** Whether the socket is currently connected */
|
|
8769
|
+
isConnected() {
|
|
8770
|
+
return this.socket?.connected ?? false;
|
|
8771
|
+
}
|
|
8772
|
+
// ── Global Chat Actions ──
|
|
8773
|
+
/** Send a message to global chat */
|
|
8774
|
+
sendMessage(params) {
|
|
8775
|
+
this.socket?.emit("send_message", params);
|
|
8776
|
+
}
|
|
8777
|
+
/** Emit typing indicator */
|
|
8778
|
+
sendTyping(isTyping) {
|
|
8779
|
+
this.socket?.emit("typing", isTyping);
|
|
8780
|
+
}
|
|
8781
|
+
/** Add an emoji reaction to a message */
|
|
8782
|
+
addReaction(messageId, reaction) {
|
|
8783
|
+
this.socket?.emit("add_reaction", { messageId, reaction });
|
|
8784
|
+
}
|
|
8785
|
+
/** Remove an emoji reaction from a message */
|
|
8786
|
+
removeReaction(messageId, reaction) {
|
|
8787
|
+
this.socket?.emit("remove_reaction", { messageId, reaction });
|
|
8788
|
+
}
|
|
8789
|
+
// ── DM Actions ──
|
|
8790
|
+
/** Join a DM room to receive messages in real-time */
|
|
8791
|
+
joinDM(recipientWallet) {
|
|
8792
|
+
this.socket?.emit("dm:join", { recipientWallet });
|
|
8793
|
+
}
|
|
8794
|
+
/** Leave a DM room */
|
|
8795
|
+
leaveDM(recipientWallet) {
|
|
8796
|
+
this.socket?.emit("dm:leave", { recipientWallet });
|
|
8797
|
+
}
|
|
8798
|
+
/** Send a direct message via socket */
|
|
8799
|
+
sendDM(params) {
|
|
8800
|
+
this.socket?.emit("dm:send", params);
|
|
8801
|
+
}
|
|
8802
|
+
/** Mark DMs from a sender as read */
|
|
8803
|
+
markDMRead(senderWallet) {
|
|
8804
|
+
this.socket?.emit("dm:mark_read", { senderWallet });
|
|
8805
|
+
}
|
|
8806
|
+
};
|
|
8807
|
+
|
|
8808
|
+
// src/chat/provider.tsx
|
|
8809
|
+
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
8810
|
+
var ChatContext = createContext5(null);
|
|
8811
|
+
function ChatProvider({ children, autoConnect = true }) {
|
|
8812
|
+
const { client } = useDubs();
|
|
8813
|
+
const socketRef = useRef17(new ChatSocket());
|
|
8814
|
+
const [status, setStatus] = useState41("disconnected");
|
|
8815
|
+
const [messages, setMessages] = useState41([]);
|
|
8816
|
+
const [onlineUsers, setOnlineUsers] = useState41([]);
|
|
8817
|
+
const [onlineCount, setOnlineCount] = useState41(0);
|
|
8818
|
+
const [unreadCount, setUnreadCount] = useState41(0);
|
|
8819
|
+
const [conversations, setConversations] = useState41([]);
|
|
8820
|
+
const [friends, setFriends] = useState41([]);
|
|
8821
|
+
const [pendingRequests, setPendingRequests] = useState41([]);
|
|
8822
|
+
const refreshMessages = useCallback35(async () => {
|
|
8823
|
+
try {
|
|
8824
|
+
const res = await client.getChatMessages({ limit: 30 });
|
|
8825
|
+
setMessages(res.messages);
|
|
8826
|
+
} catch (err) {
|
|
8827
|
+
console.error("[Dubs:ChatProvider] Failed to load messages:", err);
|
|
8828
|
+
}
|
|
8829
|
+
}, [client]);
|
|
8830
|
+
const refreshConversations = useCallback35(async () => {
|
|
8831
|
+
try {
|
|
8832
|
+
const res = await client.getConversations();
|
|
8833
|
+
setConversations(res.conversations);
|
|
8834
|
+
} catch (_) {
|
|
8835
|
+
}
|
|
8836
|
+
}, [client]);
|
|
8837
|
+
const refreshFriends = useCallback35(async () => {
|
|
8838
|
+
try {
|
|
8839
|
+
const res = await client.getFriends();
|
|
8840
|
+
setFriends(res.friends);
|
|
8841
|
+
} catch (_) {
|
|
8842
|
+
}
|
|
8843
|
+
}, [client]);
|
|
8844
|
+
const refreshPendingRequests = useCallback35(async () => {
|
|
8845
|
+
try {
|
|
8846
|
+
const res = await client.getPendingFriendRequests();
|
|
8847
|
+
setPendingRequests(res.requests);
|
|
8848
|
+
} catch (_) {
|
|
8849
|
+
}
|
|
8850
|
+
}, [client]);
|
|
8851
|
+
useEffect29(() => {
|
|
8852
|
+
const token = client.getToken();
|
|
8853
|
+
if (!autoConnect || !token) return;
|
|
8854
|
+
const chatSocket = socketRef.current;
|
|
8855
|
+
const baseUrl = client.baseUrl;
|
|
8856
|
+
const host = new URL(baseUrl).origin;
|
|
8857
|
+
chatSocket.setListeners({
|
|
8858
|
+
onConnectionChange: setStatus,
|
|
8859
|
+
// Global chat
|
|
8860
|
+
onNewMessage: (msg) => {
|
|
8861
|
+
setMessages((prev) => {
|
|
8862
|
+
if (prev.some((m) => m.id === msg.id)) return prev;
|
|
8863
|
+
return [msg, ...prev];
|
|
8864
|
+
});
|
|
8865
|
+
},
|
|
8866
|
+
onOnlineUsers: setOnlineUsers,
|
|
8867
|
+
onOnlineCount: setOnlineCount,
|
|
8868
|
+
onUnreadCount: setUnreadCount,
|
|
8869
|
+
// Notifications trigger conversation refresh
|
|
8870
|
+
onDMNotification: () => {
|
|
8871
|
+
refreshConversations();
|
|
8872
|
+
},
|
|
8873
|
+
onNotification: (n) => {
|
|
8874
|
+
setUnreadCount((prev) => prev + 1);
|
|
8875
|
+
if (n.type === "friend_request") refreshPendingRequests();
|
|
8876
|
+
if (n.type === "friend_request_accepted") refreshFriends();
|
|
8877
|
+
},
|
|
8878
|
+
onFriendRequestAccepted: () => refreshFriends(),
|
|
8879
|
+
onFriendRemoved: () => refreshFriends()
|
|
8880
|
+
});
|
|
8881
|
+
chatSocket.connect({ host, token });
|
|
8882
|
+
refreshMessages();
|
|
8883
|
+
refreshFriends().catch(() => {
|
|
8884
|
+
});
|
|
8885
|
+
refreshPendingRequests().catch(() => {
|
|
8886
|
+
});
|
|
8887
|
+
return () => {
|
|
8888
|
+
chatSocket.disconnect();
|
|
8889
|
+
};
|
|
8890
|
+
}, [client, autoConnect, refreshMessages, refreshConversations, refreshFriends, refreshPendingRequests]);
|
|
8891
|
+
useEffect29(() => {
|
|
8892
|
+
const handleAppState = (nextState) => {
|
|
8893
|
+
if (nextState === "active") {
|
|
8894
|
+
const chatSocket = socketRef.current;
|
|
8895
|
+
if (!chatSocket.isConnected()) {
|
|
8896
|
+
const token = client.getToken();
|
|
8897
|
+
if (token) {
|
|
8898
|
+
const baseUrl = client.baseUrl;
|
|
8899
|
+
const host = new URL(baseUrl).origin;
|
|
8900
|
+
chatSocket.connect({ host, token });
|
|
8901
|
+
}
|
|
8902
|
+
}
|
|
8903
|
+
refreshMessages();
|
|
8904
|
+
}
|
|
8905
|
+
};
|
|
8906
|
+
const sub = AppState.addEventListener("change", handleAppState);
|
|
8907
|
+
return () => sub.remove();
|
|
8908
|
+
}, [client, refreshMessages, refreshConversations]);
|
|
8909
|
+
const value = useMemo11(
|
|
8910
|
+
() => ({
|
|
8911
|
+
socket: socketRef.current,
|
|
8912
|
+
status,
|
|
8913
|
+
messages,
|
|
8914
|
+
onlineUsers,
|
|
8915
|
+
onlineCount,
|
|
8916
|
+
unreadCount,
|
|
8917
|
+
conversations,
|
|
8918
|
+
friends,
|
|
8919
|
+
pendingRequests,
|
|
8920
|
+
refreshMessages,
|
|
8921
|
+
refreshConversations,
|
|
8922
|
+
refreshFriends,
|
|
8923
|
+
refreshPendingRequests
|
|
8924
|
+
}),
|
|
8925
|
+
[status, messages, onlineUsers, onlineCount, unreadCount, conversations, friends, pendingRequests, refreshMessages, refreshConversations, refreshFriends, refreshPendingRequests]
|
|
8926
|
+
);
|
|
8927
|
+
return /* @__PURE__ */ jsx27(ChatContext.Provider, { value, children });
|
|
8928
|
+
}
|
|
8929
|
+
function useChatContext() {
|
|
8930
|
+
const ctx = useContext5(ChatContext);
|
|
8931
|
+
if (!ctx) {
|
|
8932
|
+
throw new Error("useChatContext must be used inside a <ChatProvider>");
|
|
8933
|
+
}
|
|
8934
|
+
return ctx;
|
|
8935
|
+
}
|
|
8936
|
+
|
|
8937
|
+
// src/chat/hooks.ts
|
|
8938
|
+
import { useState as useState42, useCallback as useCallback36, useEffect as useEffect30, useRef as useRef18 } from "react";
|
|
8939
|
+
function useChatStatus() {
|
|
8940
|
+
return useChatContext().status;
|
|
8941
|
+
}
|
|
8942
|
+
function useChatMessages() {
|
|
8943
|
+
const { messages, refreshMessages } = useChatContext();
|
|
8944
|
+
const [loading, setLoading] = useState42(false);
|
|
8945
|
+
const refetch = useCallback36(async () => {
|
|
8946
|
+
setLoading(true);
|
|
8947
|
+
await refreshMessages();
|
|
8948
|
+
setLoading(false);
|
|
8949
|
+
}, [refreshMessages]);
|
|
8950
|
+
return { messages, loading, refetch };
|
|
8951
|
+
}
|
|
8952
|
+
function useSendMessage() {
|
|
8953
|
+
const { socket } = useChatContext();
|
|
8954
|
+
const { client } = useDubs();
|
|
8955
|
+
const send = useCallback36(
|
|
8956
|
+
(params) => {
|
|
8957
|
+
socket.sendMessage(params);
|
|
8958
|
+
},
|
|
8959
|
+
[socket]
|
|
8960
|
+
);
|
|
8961
|
+
const sendViaREST = useCallback36(
|
|
8962
|
+
async (params) => {
|
|
8963
|
+
await client.sendChatMessage(params);
|
|
8964
|
+
},
|
|
8965
|
+
[client]
|
|
8966
|
+
);
|
|
8967
|
+
return { send, sendViaREST };
|
|
8968
|
+
}
|
|
8969
|
+
function useOnlineUsers() {
|
|
8970
|
+
const { onlineUsers, onlineCount } = useChatContext();
|
|
8971
|
+
return { users: onlineUsers, count: onlineCount };
|
|
8972
|
+
}
|
|
8973
|
+
function useUnreadCount() {
|
|
8974
|
+
return useChatContext().unreadCount;
|
|
8975
|
+
}
|
|
8976
|
+
function useConversations() {
|
|
8977
|
+
const { conversations, refreshConversations } = useChatContext();
|
|
8978
|
+
const [loading, setLoading] = useState42(false);
|
|
8979
|
+
const refetch = useCallback36(async () => {
|
|
8980
|
+
setLoading(true);
|
|
8981
|
+
await refreshConversations();
|
|
8982
|
+
setLoading(false);
|
|
8983
|
+
}, [refreshConversations]);
|
|
8984
|
+
return { conversations, loading, refetch };
|
|
8985
|
+
}
|
|
8986
|
+
function useDirectMessages(recipientWallet) {
|
|
8987
|
+
const { client } = useDubs();
|
|
8988
|
+
const { socket, refreshConversations } = useChatContext();
|
|
8989
|
+
const [messages, setMessages] = useState42([]);
|
|
8990
|
+
const [otherUser, setOtherUser] = useState42(null);
|
|
8991
|
+
const [loading, setLoading] = useState42(true);
|
|
8992
|
+
const refetch = useCallback36(async () => {
|
|
8993
|
+
try {
|
|
8994
|
+
setLoading(true);
|
|
8995
|
+
const res = await client.getConversation(recipientWallet);
|
|
8996
|
+
setMessages(res.messages);
|
|
8997
|
+
setOtherUser(res.otherUser);
|
|
8998
|
+
} catch (err) {
|
|
8999
|
+
console.error("[Dubs:useDirectMessages] Error loading:", err);
|
|
9000
|
+
} finally {
|
|
9001
|
+
setLoading(false);
|
|
9002
|
+
}
|
|
9003
|
+
}, [client, recipientWallet]);
|
|
9004
|
+
useEffect30(() => {
|
|
9005
|
+
refetch();
|
|
9006
|
+
socket.joinDM(recipientWallet);
|
|
9007
|
+
return () => {
|
|
9008
|
+
socket.leaveDM(recipientWallet);
|
|
9009
|
+
};
|
|
9010
|
+
}, [recipientWallet, refetch, socket]);
|
|
9011
|
+
const socketRef = useRef18(socket);
|
|
9012
|
+
socketRef.current = socket;
|
|
9013
|
+
useEffect30(() => {
|
|
9014
|
+
const currentSocket = socketRef.current;
|
|
9015
|
+
const prevListeners = currentSocket.listeners;
|
|
9016
|
+
const originalOnDMNew = prevListeners?.onDMNewMessage;
|
|
9017
|
+
currentSocket.setListeners({
|
|
9018
|
+
...prevListeners,
|
|
9019
|
+
onDMNewMessage: (msg) => {
|
|
9020
|
+
originalOnDMNew?.(msg);
|
|
9021
|
+
if (msg.senderWallet === recipientWallet || msg.isOwn) {
|
|
9022
|
+
setMessages((prev) => {
|
|
9023
|
+
if (prev.some((m) => m.id === msg.id)) return prev;
|
|
9024
|
+
return [...prev, msg];
|
|
9025
|
+
});
|
|
9026
|
+
}
|
|
9027
|
+
},
|
|
9028
|
+
onDMMessageSent: (msg) => {
|
|
9029
|
+
setMessages((prev) => {
|
|
9030
|
+
if (prev.some((m) => m.id === msg.id)) return prev;
|
|
9031
|
+
return [...prev, { ...msg, isOwn: true }];
|
|
9032
|
+
});
|
|
9033
|
+
}
|
|
9034
|
+
});
|
|
9035
|
+
}, [recipientWallet]);
|
|
9036
|
+
const send = useCallback36(
|
|
9037
|
+
(message) => {
|
|
9038
|
+
socket.sendDM({ recipientWallet, message });
|
|
9039
|
+
},
|
|
9040
|
+
[socket, recipientWallet]
|
|
9041
|
+
);
|
|
9042
|
+
const sendViaREST = useCallback36(
|
|
9043
|
+
async (message) => {
|
|
9044
|
+
await client.sendDirectMessage({ recipientWallet, message });
|
|
9045
|
+
await refetch();
|
|
9046
|
+
await refreshConversations();
|
|
9047
|
+
},
|
|
9048
|
+
[client, recipientWallet, refetch, refreshConversations]
|
|
9049
|
+
);
|
|
9050
|
+
const markRead = useCallback36(() => {
|
|
9051
|
+
socket.markDMRead(recipientWallet);
|
|
9052
|
+
}, [socket, recipientWallet]);
|
|
9053
|
+
return { messages, loading, otherUser, send, sendViaREST, markRead, refetch };
|
|
9054
|
+
}
|
|
9055
|
+
function useFriends() {
|
|
9056
|
+
const { friends, refreshFriends } = useChatContext();
|
|
9057
|
+
const [loading, setLoading] = useState42(false);
|
|
9058
|
+
const refetch = useCallback36(async () => {
|
|
9059
|
+
setLoading(true);
|
|
9060
|
+
await refreshFriends();
|
|
9061
|
+
setLoading(false);
|
|
9062
|
+
}, [refreshFriends]);
|
|
9063
|
+
return { friends, loading, refetch };
|
|
9064
|
+
}
|
|
9065
|
+
function useFriendRequests() {
|
|
9066
|
+
const { pendingRequests, refreshPendingRequests } = useChatContext();
|
|
9067
|
+
const [loading, setLoading] = useState42(false);
|
|
9068
|
+
const refetch = useCallback36(async () => {
|
|
9069
|
+
setLoading(true);
|
|
9070
|
+
await refreshPendingRequests();
|
|
9071
|
+
setLoading(false);
|
|
9072
|
+
}, [refreshPendingRequests]);
|
|
9073
|
+
return { requests: pendingRequests, loading, refetch };
|
|
9074
|
+
}
|
|
9075
|
+
function useSearchUsers() {
|
|
9076
|
+
const { client } = useDubs();
|
|
9077
|
+
const [results, setResults] = useState42([]);
|
|
9078
|
+
const [loading, setLoading] = useState42(false);
|
|
9079
|
+
const search = useCallback36(
|
|
9080
|
+
async (query) => {
|
|
9081
|
+
setLoading(true);
|
|
9082
|
+
try {
|
|
9083
|
+
const res = await client.searchUsers(query);
|
|
9084
|
+
setResults(res.results);
|
|
9085
|
+
} catch (err) {
|
|
9086
|
+
console.error("[Dubs:useSearchUsers] Error:", err);
|
|
9087
|
+
} finally {
|
|
9088
|
+
setLoading(false);
|
|
9089
|
+
}
|
|
9090
|
+
},
|
|
9091
|
+
[client]
|
|
9092
|
+
);
|
|
9093
|
+
const clear = useCallback36(() => setResults([]), []);
|
|
9094
|
+
return { results, loading, search, clear };
|
|
9095
|
+
}
|
|
9096
|
+
function useSendFriendRequest() {
|
|
9097
|
+
const { client } = useDubs();
|
|
9098
|
+
const { refreshPendingRequests } = useChatContext();
|
|
9099
|
+
const [loading, setLoading] = useState42(false);
|
|
9100
|
+
const send = useCallback36(
|
|
9101
|
+
async (targetUserId) => {
|
|
9102
|
+
setLoading(true);
|
|
9103
|
+
try {
|
|
9104
|
+
await client.sendFriendRequest(targetUserId);
|
|
9105
|
+
} finally {
|
|
9106
|
+
setLoading(false);
|
|
9107
|
+
}
|
|
9108
|
+
},
|
|
9109
|
+
[client, refreshPendingRequests]
|
|
9110
|
+
);
|
|
9111
|
+
return { send, loading };
|
|
9112
|
+
}
|
|
9113
|
+
function useRespondToFriendRequest() {
|
|
9114
|
+
const { client } = useDubs();
|
|
9115
|
+
const { refreshFriends, refreshPendingRequests } = useChatContext();
|
|
9116
|
+
const [loading, setLoading] = useState42(false);
|
|
9117
|
+
const accept = useCallback36(
|
|
9118
|
+
async (requestId) => {
|
|
9119
|
+
setLoading(true);
|
|
9120
|
+
try {
|
|
9121
|
+
await client.acceptFriendRequest(requestId);
|
|
9122
|
+
await Promise.all([refreshFriends(), refreshPendingRequests()]);
|
|
9123
|
+
} finally {
|
|
9124
|
+
setLoading(false);
|
|
9125
|
+
}
|
|
9126
|
+
},
|
|
9127
|
+
[client, refreshFriends, refreshPendingRequests]
|
|
9128
|
+
);
|
|
9129
|
+
const reject = useCallback36(
|
|
9130
|
+
async (requestId) => {
|
|
9131
|
+
setLoading(true);
|
|
9132
|
+
try {
|
|
9133
|
+
await client.rejectFriendRequest(requestId);
|
|
9134
|
+
await refreshPendingRequests();
|
|
9135
|
+
} finally {
|
|
9136
|
+
setLoading(false);
|
|
9137
|
+
}
|
|
9138
|
+
},
|
|
9139
|
+
[client, refreshPendingRequests]
|
|
9140
|
+
);
|
|
9141
|
+
return { accept, reject, loading };
|
|
9142
|
+
}
|
|
7235
9143
|
export {
|
|
7236
9144
|
ArcadeLeaderboardSheet,
|
|
7237
9145
|
AuthGate,
|
|
9146
|
+
ChatProvider,
|
|
9147
|
+
ChatSocket,
|
|
7238
9148
|
ClaimButton,
|
|
7239
9149
|
ClaimPrizeSheet,
|
|
7240
9150
|
ConnectWalletButton,
|
|
@@ -7248,6 +9158,9 @@ export {
|
|
|
7248
9158
|
DubsProvider,
|
|
7249
9159
|
EnterArcadePoolSheet,
|
|
7250
9160
|
GamePoster,
|
|
9161
|
+
JackpotCard,
|
|
9162
|
+
JackpotSheet,
|
|
9163
|
+
JackpotWidget,
|
|
7251
9164
|
JoinGameButton,
|
|
7252
9165
|
JoinGameSheet,
|
|
7253
9166
|
LivePoolsCard,
|
|
@@ -7276,22 +9189,38 @@ export {
|
|
|
7276
9189
|
useArcadePool,
|
|
7277
9190
|
useArcadePools,
|
|
7278
9191
|
useAuth,
|
|
9192
|
+
useChatContext,
|
|
9193
|
+
useChatMessages,
|
|
9194
|
+
useChatStatus,
|
|
7279
9195
|
useClaim,
|
|
9196
|
+
useConversations,
|
|
7280
9197
|
useCreateCustomGame,
|
|
7281
9198
|
useCreateGame,
|
|
9199
|
+
useDirectMessages,
|
|
7282
9200
|
useDubs,
|
|
7283
9201
|
useDubsTheme,
|
|
7284
9202
|
useEnterArcadePool,
|
|
9203
|
+
useEnterJackpot,
|
|
7285
9204
|
useEvents,
|
|
9205
|
+
useFriendRequests,
|
|
9206
|
+
useFriends,
|
|
7286
9207
|
useGame,
|
|
7287
9208
|
useGames,
|
|
7288
9209
|
useHasClaimed,
|
|
7289
9210
|
useHighlights,
|
|
9211
|
+
useJackpot,
|
|
9212
|
+
useJackpotHistory,
|
|
7290
9213
|
useJoinGame,
|
|
7291
9214
|
useNetworkGames,
|
|
9215
|
+
useOnlineUsers,
|
|
7292
9216
|
usePushNotifications,
|
|
9217
|
+
useRespondToFriendRequest,
|
|
9218
|
+
useSearchUsers,
|
|
9219
|
+
useSendFriendRequest,
|
|
9220
|
+
useSendMessage,
|
|
7293
9221
|
useShorts,
|
|
7294
9222
|
useUFCFightCard,
|
|
7295
|
-
useUFCFighterDetail
|
|
9223
|
+
useUFCFighterDetail,
|
|
9224
|
+
useUnreadCount
|
|
7296
9225
|
};
|
|
7297
9226
|
//# sourceMappingURL=index.mjs.map
|