@dubsdotapp/expo 0.1.3 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -19
- package/dist/index.d.mts +207 -46
- package/dist/index.d.ts +207 -46
- package/dist/index.js +1266 -411
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1299 -444
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -2
- package/src/auth-context.ts +9 -0
- package/src/client.ts +30 -1
- package/src/constants.ts +15 -0
- package/src/hooks/useAuth.ts +13 -2
- package/src/hooks/useClaim.ts +11 -9
- package/src/hooks/useCreateGame.ts +15 -12
- package/src/hooks/useJoinGame.ts +18 -14
- package/src/index.ts +22 -3
- package/src/managed-wallet.tsx +158 -0
- package/src/provider.tsx +245 -9
- package/src/storage.ts +57 -0
- package/src/types.ts +47 -4
- package/src/ui/AuthGate.tsx +20 -11
- package/src/ui/ConnectWalletScreen.tsx +31 -5
- package/src/ui/game/GamePoster.tsx +182 -0
- package/src/ui/game/JoinGameButton.tsx +73 -0
- package/src/ui/game/LivePoolsCard.tsx +88 -0
- package/src/ui/game/PickWinnerCard.tsx +126 -0
- package/src/ui/game/PlayersCard.tsx +108 -0
- package/src/ui/game/index.ts +10 -0
- package/src/ui/index.ts +11 -1
- package/src/ui/theme.ts +5 -0
- package/src/utils/transaction.ts +8 -49
- package/src/wallet/mwa-adapter.ts +9 -6
- package/src/wallet/types.ts +6 -0
package/dist/index.js
CHANGED
|
@@ -37,12 +37,20 @@ __export(index_exports, {
|
|
|
37
37
|
DubsApiError: () => DubsApiError,
|
|
38
38
|
DubsClient: () => DubsClient,
|
|
39
39
|
DubsProvider: () => DubsProvider,
|
|
40
|
+
GamePoster: () => GamePoster,
|
|
41
|
+
JoinGameButton: () => JoinGameButton,
|
|
42
|
+
LivePoolsCard: () => LivePoolsCard,
|
|
40
43
|
MwaWalletAdapter: () => MwaWalletAdapter,
|
|
44
|
+
NETWORK_CONFIG: () => NETWORK_CONFIG,
|
|
45
|
+
PickWinnerCard: () => PickWinnerCard,
|
|
46
|
+
PlayersCard: () => PlayersCard,
|
|
41
47
|
SOLANA_PROGRAM_ERRORS: () => SOLANA_PROGRAM_ERRORS,
|
|
48
|
+
STORAGE_KEYS: () => STORAGE_KEYS,
|
|
42
49
|
SettingsSheet: () => SettingsSheet,
|
|
43
50
|
UserProfileCard: () => UserProfileCard,
|
|
51
|
+
createSecureStoreStorage: () => createSecureStoreStorage,
|
|
52
|
+
mergeTheme: () => mergeTheme,
|
|
44
53
|
parseSolanaError: () => parseSolanaError,
|
|
45
|
-
pollTransactionConfirmation: () => pollTransactionConfirmation,
|
|
46
54
|
signAndSendBase64Transaction: () => signAndSendBase64Transaction,
|
|
47
55
|
useAuth: () => useAuth,
|
|
48
56
|
useClaim: () => useClaim,
|
|
@@ -60,6 +68,18 @@ module.exports = __toCommonJS(index_exports);
|
|
|
60
68
|
// src/constants.ts
|
|
61
69
|
var DEFAULT_BASE_URL = "https://dubs-server-prod-9c91d3f01199.herokuapp.com/api/developer/v1";
|
|
62
70
|
var DEFAULT_RPC_URL = "https://api.mainnet-beta.solana.com";
|
|
71
|
+
var NETWORK_CONFIG = {
|
|
72
|
+
"mainnet-beta": {
|
|
73
|
+
baseUrl: DEFAULT_BASE_URL,
|
|
74
|
+
rpcUrl: DEFAULT_RPC_URL,
|
|
75
|
+
cluster: "mainnet-beta"
|
|
76
|
+
},
|
|
77
|
+
devnet: {
|
|
78
|
+
baseUrl: "https://dubs-server-dev-55d1fba09a97.herokuapp.com/api/developer/v1",
|
|
79
|
+
rpcUrl: "https://api.devnet.solana.com",
|
|
80
|
+
cluster: "devnet"
|
|
81
|
+
}
|
|
82
|
+
};
|
|
63
83
|
|
|
64
84
|
// src/errors.ts
|
|
65
85
|
var DubsApiError = class extends Error {
|
|
@@ -193,12 +213,20 @@ var DubsClient = class {
|
|
|
193
213
|
if (this._token) {
|
|
194
214
|
headers["Authorization"] = `Bearer ${this._token}`;
|
|
195
215
|
}
|
|
216
|
+
console.log(`[DubsClient] ${method} ${url}`, body ? JSON.stringify(body).slice(0, 200) : "");
|
|
196
217
|
const res = await fetch(url, {
|
|
197
218
|
method,
|
|
198
219
|
headers,
|
|
199
220
|
body: body ? JSON.stringify(body) : void 0
|
|
200
221
|
});
|
|
201
|
-
const
|
|
222
|
+
const text = await res.text();
|
|
223
|
+
console.log(`[DubsClient] ${method} ${path} \u2192 ${res.status}`, text.slice(0, 300));
|
|
224
|
+
let json;
|
|
225
|
+
try {
|
|
226
|
+
json = JSON.parse(text);
|
|
227
|
+
} catch {
|
|
228
|
+
throw new DubsApiError("parse_error", `Invalid JSON response: ${text.slice(0, 100)}`, res.status);
|
|
229
|
+
}
|
|
202
230
|
if (!json.success) {
|
|
203
231
|
const err = json.error;
|
|
204
232
|
if (typeof err === "object" && err !== null) {
|
|
@@ -318,6 +346,13 @@ var DubsClient = class {
|
|
|
318
346
|
);
|
|
319
347
|
return res.game;
|
|
320
348
|
}
|
|
349
|
+
async getLiveScore(gameId) {
|
|
350
|
+
const res = await this.request(
|
|
351
|
+
"GET",
|
|
352
|
+
`/games/${encodeURIComponent(gameId)}/live-score`
|
|
353
|
+
);
|
|
354
|
+
return res.liveScore;
|
|
355
|
+
}
|
|
321
356
|
async getGames(params) {
|
|
322
357
|
const qs = new URLSearchParams();
|
|
323
358
|
if (params?.wallet) qs.set("wallet", params.wallet);
|
|
@@ -335,6 +370,7 @@ var DubsClient = class {
|
|
|
335
370
|
async getNetworkGames(params) {
|
|
336
371
|
const qs = new URLSearchParams();
|
|
337
372
|
if (params?.league) qs.set("league", params.league);
|
|
373
|
+
if (params?.exclude_wallet) qs.set("exclude_wallet", params.exclude_wallet);
|
|
338
374
|
if (params?.limit != null) qs.set("limit", String(params.limit));
|
|
339
375
|
if (params?.offset != null) qs.set("offset", String(params.offset));
|
|
340
376
|
const query = qs.toString();
|
|
@@ -441,37 +477,64 @@ var DubsClient = class {
|
|
|
441
477
|
getErrorCodesLocal() {
|
|
442
478
|
return { ...SOLANA_PROGRAM_ERRORS };
|
|
443
479
|
}
|
|
480
|
+
// ── App Config ──
|
|
481
|
+
/** Fetch the app's UI customization config (accent color, icon, tagline) */
|
|
482
|
+
async getAppConfig() {
|
|
483
|
+
const res = await this.request("GET", "/apps/config");
|
|
484
|
+
return res.uiConfig || {};
|
|
485
|
+
}
|
|
444
486
|
};
|
|
445
487
|
|
|
446
|
-
// src/
|
|
447
|
-
var
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
function
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
488
|
+
// src/storage.ts
|
|
489
|
+
var STORAGE_KEYS = {
|
|
490
|
+
MWA_AUTH_TOKEN: "dubs_mwa_auth_token",
|
|
491
|
+
JWT_TOKEN: "dubs_jwt_token"
|
|
492
|
+
};
|
|
493
|
+
function createSecureStoreStorage() {
|
|
494
|
+
let SecureStore = null;
|
|
495
|
+
function getStore() {
|
|
496
|
+
if (!SecureStore) {
|
|
497
|
+
try {
|
|
498
|
+
SecureStore = require("expo-secure-store");
|
|
499
|
+
} catch {
|
|
500
|
+
throw new Error(
|
|
501
|
+
"@dubsdotapp/expo: expo-secure-store is required for default token storage. Install it with: npx expo install expo-secure-store \u2014 or pass a custom tokenStorage prop to <DubsProvider>."
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return SecureStore;
|
|
463
506
|
}
|
|
464
|
-
return
|
|
507
|
+
return {
|
|
508
|
+
async getItem(key) {
|
|
509
|
+
const store = getStore();
|
|
510
|
+
return store.getItemAsync(key);
|
|
511
|
+
},
|
|
512
|
+
async setItem(key, value) {
|
|
513
|
+
const store = getStore();
|
|
514
|
+
await store.setItemAsync(key, value);
|
|
515
|
+
},
|
|
516
|
+
async deleteItem(key) {
|
|
517
|
+
const store = getStore();
|
|
518
|
+
await store.deleteItemAsync(key);
|
|
519
|
+
}
|
|
520
|
+
};
|
|
465
521
|
}
|
|
466
522
|
|
|
523
|
+
// src/provider.tsx
|
|
524
|
+
var import_react12 = require("react");
|
|
525
|
+
var import_web33 = require("@solana/web3.js");
|
|
526
|
+
|
|
527
|
+
// src/managed-wallet.tsx
|
|
528
|
+
var import_react = require("react");
|
|
529
|
+
|
|
467
530
|
// src/wallet/mwa-adapter.ts
|
|
468
|
-
var
|
|
531
|
+
var import_web3 = require("@solana/web3.js");
|
|
469
532
|
function toPublicKey(address) {
|
|
470
533
|
if (address instanceof Uint8Array) {
|
|
471
|
-
return new
|
|
534
|
+
return new import_web3.PublicKey(address);
|
|
472
535
|
}
|
|
473
536
|
const bytes = Uint8Array.from(atob(address), (c) => c.charCodeAt(0));
|
|
474
|
-
return new
|
|
537
|
+
return new import_web3.PublicKey(bytes);
|
|
475
538
|
}
|
|
476
539
|
var MwaWalletAdapter = class {
|
|
477
540
|
constructor(config) {
|
|
@@ -487,6 +550,12 @@ var MwaWalletAdapter = class {
|
|
|
487
550
|
get connected() {
|
|
488
551
|
return this._connected;
|
|
489
552
|
}
|
|
553
|
+
get authToken() {
|
|
554
|
+
return this._authToken;
|
|
555
|
+
}
|
|
556
|
+
setAuthToken(token) {
|
|
557
|
+
this._authToken = token;
|
|
558
|
+
}
|
|
490
559
|
/**
|
|
491
560
|
* Connect to a mobile wallet. Call this before any signing.
|
|
492
561
|
*/
|
|
@@ -550,17 +619,299 @@ var MwaWalletAdapter = class {
|
|
|
550
619
|
return result[0];
|
|
551
620
|
});
|
|
552
621
|
if (signature instanceof Uint8Array) {
|
|
553
|
-
|
|
554
|
-
return new import_web32.PublicKey(signature).toBase58();
|
|
555
|
-
}).catch(() => {
|
|
556
|
-
return Buffer.from(signature).toString("base64");
|
|
557
|
-
});
|
|
558
|
-
return bs582;
|
|
622
|
+
return new import_web3.PublicKey(signature).toBase58();
|
|
559
623
|
}
|
|
560
624
|
return String(signature);
|
|
561
625
|
}
|
|
562
626
|
};
|
|
563
627
|
|
|
628
|
+
// src/ui/ConnectWalletScreen.tsx
|
|
629
|
+
var import_react_native2 = require("react-native");
|
|
630
|
+
|
|
631
|
+
// src/ui/theme.ts
|
|
632
|
+
var import_react_native = require("react-native");
|
|
633
|
+
var dark = {
|
|
634
|
+
background: "#08080D",
|
|
635
|
+
surface: "#111118",
|
|
636
|
+
surfaceActive: "#7C3AED",
|
|
637
|
+
border: "#1A1A24",
|
|
638
|
+
text: "#FFFFFF",
|
|
639
|
+
textSecondary: "#E0E0EE",
|
|
640
|
+
textMuted: "#666666",
|
|
641
|
+
textDim: "#555555",
|
|
642
|
+
accent: "#7C3AED",
|
|
643
|
+
success: "#22C55E",
|
|
644
|
+
live: "#EF4444",
|
|
645
|
+
errorText: "#F87171",
|
|
646
|
+
errorBg: "#1A0A0A",
|
|
647
|
+
errorBorder: "#3A1515"
|
|
648
|
+
};
|
|
649
|
+
var light = {
|
|
650
|
+
background: "#FFFFFF",
|
|
651
|
+
surface: "#F0F0F5",
|
|
652
|
+
surfaceActive: "#7C3AED",
|
|
653
|
+
border: "#E0E0E8",
|
|
654
|
+
text: "#111118",
|
|
655
|
+
textSecondary: "#333333",
|
|
656
|
+
textMuted: "#888888",
|
|
657
|
+
textDim: "#999999",
|
|
658
|
+
accent: "#7C3AED",
|
|
659
|
+
success: "#16A34A",
|
|
660
|
+
live: "#DC2626",
|
|
661
|
+
errorText: "#DC2626",
|
|
662
|
+
errorBg: "#FEF2F2",
|
|
663
|
+
errorBorder: "#FECACA"
|
|
664
|
+
};
|
|
665
|
+
function useDubsTheme() {
|
|
666
|
+
const scheme = (0, import_react_native.useColorScheme)();
|
|
667
|
+
return scheme === "light" ? light : dark;
|
|
668
|
+
}
|
|
669
|
+
function mergeTheme(base, overrides) {
|
|
670
|
+
return { ...base, ...overrides };
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// src/ui/ConnectWalletScreen.tsx
|
|
674
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
675
|
+
function ConnectWalletScreen({
|
|
676
|
+
onConnect,
|
|
677
|
+
connecting = false,
|
|
678
|
+
error = null,
|
|
679
|
+
appName = "Dubs",
|
|
680
|
+
accentColor,
|
|
681
|
+
appIcon,
|
|
682
|
+
tagline
|
|
683
|
+
}) {
|
|
684
|
+
const t = useDubsTheme();
|
|
685
|
+
const accent = accentColor || t.accent;
|
|
686
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: [styles.container, { backgroundColor: t.background }], children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.content, children: [
|
|
687
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.brandingSection, children: [
|
|
688
|
+
appIcon ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
689
|
+
import_react_native2.Image,
|
|
690
|
+
{
|
|
691
|
+
source: { uri: appIcon },
|
|
692
|
+
style: styles.logoImage
|
|
693
|
+
}
|
|
694
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: [styles.logoCircle, { backgroundColor: accent }], children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.logoText, children: appName.charAt(0).toUpperCase() }) }),
|
|
695
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [styles.appName, { color: t.text }], children: appName }),
|
|
696
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [styles.subtitle, { color: t.textMuted }], children: tagline || "Connect your Solana wallet to get started" })
|
|
697
|
+
] }),
|
|
698
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.actionSection, children: [
|
|
699
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
700
|
+
import_react_native2.View,
|
|
701
|
+
{
|
|
702
|
+
style: [
|
|
703
|
+
styles.errorBox,
|
|
704
|
+
{ backgroundColor: t.errorBg, borderColor: t.errorBorder }
|
|
705
|
+
],
|
|
706
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [styles.errorText, { color: t.errorText }], children: error })
|
|
707
|
+
}
|
|
708
|
+
) : null,
|
|
709
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
710
|
+
import_react_native2.TouchableOpacity,
|
|
711
|
+
{
|
|
712
|
+
style: [styles.connectButton, { backgroundColor: accent }],
|
|
713
|
+
onPress: onConnect,
|
|
714
|
+
disabled: connecting,
|
|
715
|
+
activeOpacity: 0.8,
|
|
716
|
+
children: connecting ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.ActivityIndicator, { color: "#FFFFFF", size: "small" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.connectButtonText, children: "Connect Wallet" })
|
|
717
|
+
}
|
|
718
|
+
),
|
|
719
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [styles.hint, { color: t.textDim }], children: "Phantom, Solflare, or any Solana wallet" })
|
|
720
|
+
] })
|
|
721
|
+
] }) });
|
|
722
|
+
}
|
|
723
|
+
var styles = import_react_native2.StyleSheet.create({
|
|
724
|
+
container: {
|
|
725
|
+
flex: 1,
|
|
726
|
+
justifyContent: "center"
|
|
727
|
+
},
|
|
728
|
+
content: {
|
|
729
|
+
flex: 1,
|
|
730
|
+
justifyContent: "space-between",
|
|
731
|
+
paddingHorizontal: 32,
|
|
732
|
+
paddingTop: 120,
|
|
733
|
+
paddingBottom: 80
|
|
734
|
+
},
|
|
735
|
+
brandingSection: {
|
|
736
|
+
alignItems: "center",
|
|
737
|
+
gap: 12
|
|
738
|
+
},
|
|
739
|
+
logoCircle: {
|
|
740
|
+
width: 80,
|
|
741
|
+
height: 80,
|
|
742
|
+
borderRadius: 40,
|
|
743
|
+
justifyContent: "center",
|
|
744
|
+
alignItems: "center",
|
|
745
|
+
marginBottom: 8
|
|
746
|
+
},
|
|
747
|
+
logoImage: {
|
|
748
|
+
width: 80,
|
|
749
|
+
height: 80,
|
|
750
|
+
borderRadius: 16,
|
|
751
|
+
marginBottom: 8
|
|
752
|
+
},
|
|
753
|
+
logoText: {
|
|
754
|
+
fontSize: 36,
|
|
755
|
+
fontWeight: "800",
|
|
756
|
+
color: "#FFFFFF"
|
|
757
|
+
},
|
|
758
|
+
appName: {
|
|
759
|
+
fontSize: 32,
|
|
760
|
+
fontWeight: "800"
|
|
761
|
+
},
|
|
762
|
+
subtitle: {
|
|
763
|
+
fontSize: 16,
|
|
764
|
+
textAlign: "center",
|
|
765
|
+
lineHeight: 22
|
|
766
|
+
},
|
|
767
|
+
actionSection: {
|
|
768
|
+
gap: 16
|
|
769
|
+
},
|
|
770
|
+
errorBox: {
|
|
771
|
+
borderWidth: 1,
|
|
772
|
+
borderRadius: 12,
|
|
773
|
+
paddingHorizontal: 16,
|
|
774
|
+
paddingVertical: 12
|
|
775
|
+
},
|
|
776
|
+
errorText: {
|
|
777
|
+
fontSize: 14,
|
|
778
|
+
textAlign: "center"
|
|
779
|
+
},
|
|
780
|
+
connectButton: {
|
|
781
|
+
height: 56,
|
|
782
|
+
borderRadius: 16,
|
|
783
|
+
justifyContent: "center",
|
|
784
|
+
alignItems: "center"
|
|
785
|
+
},
|
|
786
|
+
connectButtonText: {
|
|
787
|
+
color: "#FFFFFF",
|
|
788
|
+
fontSize: 18,
|
|
789
|
+
fontWeight: "700"
|
|
790
|
+
},
|
|
791
|
+
hint: {
|
|
792
|
+
fontSize: 13,
|
|
793
|
+
textAlign: "center"
|
|
794
|
+
}
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
// src/managed-wallet.tsx
|
|
798
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
799
|
+
var DisconnectContext = (0, import_react.createContext)(null);
|
|
800
|
+
function useDisconnect() {
|
|
801
|
+
return (0, import_react.useContext)(DisconnectContext);
|
|
802
|
+
}
|
|
803
|
+
function ManagedWalletProvider({
|
|
804
|
+
appName,
|
|
805
|
+
cluster,
|
|
806
|
+
storage,
|
|
807
|
+
renderConnectScreen,
|
|
808
|
+
accentColor,
|
|
809
|
+
appIcon,
|
|
810
|
+
tagline,
|
|
811
|
+
children
|
|
812
|
+
}) {
|
|
813
|
+
const [connected, setConnected] = (0, import_react.useState)(false);
|
|
814
|
+
const [connecting, setConnecting] = (0, import_react.useState)(false);
|
|
815
|
+
const [isReady, setIsReady] = (0, import_react.useState)(false);
|
|
816
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
817
|
+
const adapterRef = (0, import_react.useRef)(null);
|
|
818
|
+
const transactRef = (0, import_react.useRef)(null);
|
|
819
|
+
if (!adapterRef.current) {
|
|
820
|
+
adapterRef.current = new MwaWalletAdapter({
|
|
821
|
+
transact: (...args) => {
|
|
822
|
+
if (!transactRef.current) {
|
|
823
|
+
throw new Error(
|
|
824
|
+
"@dubsdotapp/expo: @solana-mobile/mobile-wallet-adapter-protocol-web3js is required. Install it with: npm install @solana-mobile/mobile-wallet-adapter-protocol-web3js"
|
|
825
|
+
);
|
|
826
|
+
}
|
|
827
|
+
return transactRef.current(...args);
|
|
828
|
+
},
|
|
829
|
+
appIdentity: { name: appName },
|
|
830
|
+
cluster,
|
|
831
|
+
onAuthTokenChange: (token) => {
|
|
832
|
+
if (token) {
|
|
833
|
+
storage.setItem(STORAGE_KEYS.MWA_AUTH_TOKEN, token).catch(() => {
|
|
834
|
+
});
|
|
835
|
+
} else {
|
|
836
|
+
storage.deleteItem(STORAGE_KEYS.MWA_AUTH_TOKEN).catch(() => {
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
const adapter = adapterRef.current;
|
|
843
|
+
(0, import_react.useEffect)(() => {
|
|
844
|
+
let cancelled = false;
|
|
845
|
+
(async () => {
|
|
846
|
+
try {
|
|
847
|
+
const mwa = await import("@solana-mobile/mobile-wallet-adapter-protocol-web3js");
|
|
848
|
+
if (cancelled) return;
|
|
849
|
+
transactRef.current = mwa.transact;
|
|
850
|
+
} catch {
|
|
851
|
+
}
|
|
852
|
+
try {
|
|
853
|
+
const savedToken = await storage.getItem(STORAGE_KEYS.MWA_AUTH_TOKEN);
|
|
854
|
+
if (savedToken && !cancelled) {
|
|
855
|
+
adapter.setAuthToken(savedToken);
|
|
856
|
+
await adapter.connect();
|
|
857
|
+
if (!cancelled) setConnected(true);
|
|
858
|
+
}
|
|
859
|
+
} catch {
|
|
860
|
+
} finally {
|
|
861
|
+
if (!cancelled) setIsReady(true);
|
|
862
|
+
}
|
|
863
|
+
})();
|
|
864
|
+
return () => {
|
|
865
|
+
cancelled = true;
|
|
866
|
+
};
|
|
867
|
+
}, [adapter, storage]);
|
|
868
|
+
const handleConnect = (0, import_react.useCallback)(async () => {
|
|
869
|
+
setConnecting(true);
|
|
870
|
+
setError(null);
|
|
871
|
+
try {
|
|
872
|
+
await adapter.connect();
|
|
873
|
+
setConnected(true);
|
|
874
|
+
} catch (err) {
|
|
875
|
+
const message = err instanceof Error ? err.message : "Connection failed";
|
|
876
|
+
setError(message);
|
|
877
|
+
} finally {
|
|
878
|
+
setConnecting(false);
|
|
879
|
+
}
|
|
880
|
+
}, [adapter]);
|
|
881
|
+
const disconnect = (0, import_react.useCallback)(async () => {
|
|
882
|
+
adapter.disconnect();
|
|
883
|
+
await storage.deleteItem(STORAGE_KEYS.MWA_AUTH_TOKEN).catch(() => {
|
|
884
|
+
});
|
|
885
|
+
await storage.deleteItem(STORAGE_KEYS.JWT_TOKEN).catch(() => {
|
|
886
|
+
});
|
|
887
|
+
setConnected(false);
|
|
888
|
+
}, [adapter, storage]);
|
|
889
|
+
if (!isReady) return null;
|
|
890
|
+
if (!connected) {
|
|
891
|
+
if (renderConnectScreen === false) {
|
|
892
|
+
return null;
|
|
893
|
+
}
|
|
894
|
+
const connectProps = {
|
|
895
|
+
onConnect: handleConnect,
|
|
896
|
+
connecting,
|
|
897
|
+
error,
|
|
898
|
+
appName,
|
|
899
|
+
accentColor,
|
|
900
|
+
appIcon,
|
|
901
|
+
tagline
|
|
902
|
+
};
|
|
903
|
+
if (renderConnectScreen) {
|
|
904
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: renderConnectScreen(connectProps) });
|
|
905
|
+
}
|
|
906
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ConnectWalletScreen, { ...connectProps });
|
|
907
|
+
}
|
|
908
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DisconnectContext.Provider, { value: disconnect, children: children(adapter) });
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
// src/ui/AuthGate.tsx
|
|
912
|
+
var import_react11 = __toESM(require("react"));
|
|
913
|
+
var import_react_native3 = require("react-native");
|
|
914
|
+
|
|
564
915
|
// src/hooks/useEvents.ts
|
|
565
916
|
var import_react2 = require("react");
|
|
566
917
|
function useEvents(params) {
|
|
@@ -669,44 +1020,24 @@ function useNetworkGames(params) {
|
|
|
669
1020
|
var import_react6 = require("react");
|
|
670
1021
|
|
|
671
1022
|
// src/utils/transaction.ts
|
|
672
|
-
var
|
|
673
|
-
async function signAndSendBase64Transaction(base64Tx, wallet
|
|
1023
|
+
var import_web32 = require("@solana/web3.js");
|
|
1024
|
+
async function signAndSendBase64Transaction(base64Tx, wallet) {
|
|
674
1025
|
if (!wallet.publicKey) throw new Error("Wallet not connected");
|
|
675
|
-
const
|
|
676
|
-
const
|
|
1026
|
+
const binaryStr = atob(base64Tx);
|
|
1027
|
+
const bytes = new Uint8Array(binaryStr.length);
|
|
1028
|
+
for (let i = 0; i < binaryStr.length; i++) {
|
|
1029
|
+
bytes[i] = binaryStr.charCodeAt(i);
|
|
1030
|
+
}
|
|
1031
|
+
const transaction = import_web32.Transaction.from(bytes);
|
|
677
1032
|
if (wallet.signAndSendTransaction) {
|
|
678
1033
|
return wallet.signAndSendTransaction(transaction);
|
|
679
1034
|
}
|
|
680
|
-
|
|
681
|
-
const signature = await connection.sendRawTransaction(signed.serialize(), {
|
|
682
|
-
skipPreflight: true
|
|
683
|
-
});
|
|
684
|
-
return signature;
|
|
685
|
-
}
|
|
686
|
-
async function pollTransactionConfirmation(signature, connection, commitment = "confirmed", timeout = 6e4, interval = 1500) {
|
|
687
|
-
const start = Date.now();
|
|
688
|
-
const confirmationOrder = ["processed", "confirmed", "finalized"];
|
|
689
|
-
const targetIndex = confirmationOrder.indexOf(commitment);
|
|
690
|
-
while (Date.now() - start < timeout) {
|
|
691
|
-
const statuses = await connection.getSignatureStatuses([signature]);
|
|
692
|
-
const status = statuses?.value?.[0];
|
|
693
|
-
if (status?.err) {
|
|
694
|
-
throw new Error(`Transaction failed: ${JSON.stringify(status.err)}`);
|
|
695
|
-
}
|
|
696
|
-
if (status?.confirmationStatus) {
|
|
697
|
-
const currentIndex = confirmationOrder.indexOf(status.confirmationStatus);
|
|
698
|
-
if (currentIndex >= targetIndex) {
|
|
699
|
-
return;
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
await new Promise((resolve) => setTimeout(resolve, interval));
|
|
703
|
-
}
|
|
704
|
-
throw new Error(`Transaction confirmation timeout after ${timeout}ms`);
|
|
1035
|
+
throw new Error("Wallet does not support signAndSendTransaction");
|
|
705
1036
|
}
|
|
706
1037
|
|
|
707
1038
|
// src/hooks/useCreateGame.ts
|
|
708
1039
|
function useCreateGame() {
|
|
709
|
-
const { client, wallet
|
|
1040
|
+
const { client, wallet } = useDubs();
|
|
710
1041
|
const [status, setStatus] = (0, import_react6.useState)("idle");
|
|
711
1042
|
const [error, setError] = (0, import_react6.useState)(null);
|
|
712
1043
|
const [data, setData] = (0, import_react6.useState)(null);
|
|
@@ -720,17 +1051,18 @@ function useCreateGame() {
|
|
|
720
1051
|
setError(null);
|
|
721
1052
|
setData(null);
|
|
722
1053
|
try {
|
|
1054
|
+
console.log("[useCreateGame] Step 1: Building transaction...");
|
|
723
1055
|
const createResult = await client.createGame(params);
|
|
1056
|
+
console.log("[useCreateGame] Step 1 done:", { gameId: createResult.gameId, gameAddress: createResult.gameAddress });
|
|
724
1057
|
setStatus("signing");
|
|
1058
|
+
console.log("[useCreateGame] Step 2: Signing and sending...");
|
|
725
1059
|
const signature = await signAndSendBase64Transaction(
|
|
726
1060
|
createResult.transaction,
|
|
727
|
-
wallet
|
|
728
|
-
connection
|
|
1061
|
+
wallet
|
|
729
1062
|
);
|
|
1063
|
+
console.log("[useCreateGame] Step 2 done. Signature:", signature);
|
|
730
1064
|
setStatus("confirming");
|
|
731
|
-
|
|
732
|
-
setStatus("saving");
|
|
733
|
-
const explorerUrl = `https://solscan.io/tx/${signature}`;
|
|
1065
|
+
console.log("[useCreateGame] Step 3: Confirming with backend...");
|
|
734
1066
|
await client.confirmGame({
|
|
735
1067
|
gameId: createResult.gameId,
|
|
736
1068
|
playerWallet: params.playerWallet,
|
|
@@ -740,6 +1072,8 @@ function useCreateGame() {
|
|
|
740
1072
|
role: "creator",
|
|
741
1073
|
gameAddress: createResult.gameAddress
|
|
742
1074
|
});
|
|
1075
|
+
console.log("[useCreateGame] Step 3 done.");
|
|
1076
|
+
const explorerUrl = `https://solscan.io/tx/${signature}`;
|
|
743
1077
|
const result = {
|
|
744
1078
|
gameId: createResult.gameId,
|
|
745
1079
|
gameAddress: createResult.gameAddress,
|
|
@@ -748,21 +1082,23 @@ function useCreateGame() {
|
|
|
748
1082
|
};
|
|
749
1083
|
setData(result);
|
|
750
1084
|
setStatus("success");
|
|
1085
|
+
console.log("[useCreateGame] Complete!");
|
|
751
1086
|
return result;
|
|
752
1087
|
} catch (err) {
|
|
1088
|
+
console.error("[useCreateGame] FAILED:", err);
|
|
753
1089
|
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
754
1090
|
setError(error2);
|
|
755
1091
|
setStatus("error");
|
|
756
1092
|
throw error2;
|
|
757
1093
|
}
|
|
758
|
-
}, [client, wallet
|
|
1094
|
+
}, [client, wallet]);
|
|
759
1095
|
return { execute, status, error, data, reset };
|
|
760
1096
|
}
|
|
761
1097
|
|
|
762
1098
|
// src/hooks/useJoinGame.ts
|
|
763
1099
|
var import_react7 = require("react");
|
|
764
1100
|
function useJoinGame() {
|
|
765
|
-
const { client, wallet
|
|
1101
|
+
const { client, wallet } = useDubs();
|
|
766
1102
|
const [status, setStatus] = (0, import_react7.useState)("idle");
|
|
767
1103
|
const [error, setError] = (0, import_react7.useState)(null);
|
|
768
1104
|
const [data, setData] = (0, import_react7.useState)(null);
|
|
@@ -776,18 +1112,18 @@ function useJoinGame() {
|
|
|
776
1112
|
setError(null);
|
|
777
1113
|
setData(null);
|
|
778
1114
|
try {
|
|
1115
|
+
console.log("[useJoinGame] Step 1: Building transaction...", { gameId: params.gameId, playerWallet: params.playerWallet, teamChoice: params.teamChoice, amount: params.amount });
|
|
779
1116
|
const joinResult = await client.joinGame(params);
|
|
1117
|
+
console.log("[useJoinGame] Step 1 done:", { gameId: joinResult.gameId, gameAddress: joinResult.gameAddress, hasTx: !!joinResult.transaction });
|
|
780
1118
|
setStatus("signing");
|
|
1119
|
+
console.log("[useJoinGame] Step 2: Signing and sending transaction...");
|
|
781
1120
|
const signature = await signAndSendBase64Transaction(
|
|
782
1121
|
joinResult.transaction,
|
|
783
|
-
wallet
|
|
784
|
-
connection
|
|
1122
|
+
wallet
|
|
785
1123
|
);
|
|
1124
|
+
console.log("[useJoinGame] Step 2 done. Signature:", signature);
|
|
786
1125
|
setStatus("confirming");
|
|
787
|
-
|
|
788
|
-
setStatus("saving");
|
|
789
|
-
const explorerUrl = `https://solscan.io/tx/${signature}`;
|
|
790
|
-
await client.confirmGame({
|
|
1126
|
+
const confirmParams = {
|
|
791
1127
|
gameId: params.gameId,
|
|
792
1128
|
playerWallet: params.playerWallet,
|
|
793
1129
|
signature,
|
|
@@ -795,7 +1131,11 @@ function useJoinGame() {
|
|
|
795
1131
|
wagerAmount: params.amount,
|
|
796
1132
|
role: "joiner",
|
|
797
1133
|
gameAddress: joinResult.gameAddress
|
|
798
|
-
}
|
|
1134
|
+
};
|
|
1135
|
+
console.log("[useJoinGame] Step 3: Confirming with backend...", confirmParams);
|
|
1136
|
+
await client.confirmGame(confirmParams);
|
|
1137
|
+
console.log("[useJoinGame] Step 3 done. Backend confirmed.");
|
|
1138
|
+
const explorerUrl = `https://solscan.io/tx/${signature}`;
|
|
799
1139
|
const result = {
|
|
800
1140
|
gameId: params.gameId,
|
|
801
1141
|
gameAddress: joinResult.gameAddress,
|
|
@@ -804,21 +1144,23 @@ function useJoinGame() {
|
|
|
804
1144
|
};
|
|
805
1145
|
setData(result);
|
|
806
1146
|
setStatus("success");
|
|
1147
|
+
console.log("[useJoinGame] Complete!");
|
|
807
1148
|
return result;
|
|
808
1149
|
} catch (err) {
|
|
1150
|
+
console.error("[useJoinGame] FAILED at status:", status, err);
|
|
809
1151
|
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
810
1152
|
setError(error2);
|
|
811
1153
|
setStatus("error");
|
|
812
1154
|
throw error2;
|
|
813
1155
|
}
|
|
814
|
-
}, [client, wallet
|
|
1156
|
+
}, [client, wallet]);
|
|
815
1157
|
return { execute, status, error, data, reset };
|
|
816
1158
|
}
|
|
817
1159
|
|
|
818
1160
|
// src/hooks/useClaim.ts
|
|
819
1161
|
var import_react8 = require("react");
|
|
820
1162
|
function useClaim() {
|
|
821
|
-
const { client, wallet
|
|
1163
|
+
const { client, wallet } = useDubs();
|
|
822
1164
|
const [status, setStatus] = (0, import_react8.useState)("idle");
|
|
823
1165
|
const [error, setError] = (0, import_react8.useState)(null);
|
|
824
1166
|
const [data, setData] = (0, import_react8.useState)(null);
|
|
@@ -832,15 +1174,16 @@ function useClaim() {
|
|
|
832
1174
|
setError(null);
|
|
833
1175
|
setData(null);
|
|
834
1176
|
try {
|
|
1177
|
+
console.log("[useClaim] Step 1: Building claim transaction...");
|
|
835
1178
|
const claimResult = await client.buildClaimTransaction(params);
|
|
1179
|
+
console.log("[useClaim] Step 1 done.");
|
|
836
1180
|
setStatus("signing");
|
|
1181
|
+
console.log("[useClaim] Step 2: Signing and sending...");
|
|
837
1182
|
const signature = await signAndSendBase64Transaction(
|
|
838
1183
|
claimResult.transaction,
|
|
839
|
-
wallet
|
|
840
|
-
connection
|
|
1184
|
+
wallet
|
|
841
1185
|
);
|
|
842
|
-
|
|
843
|
-
await pollTransactionConfirmation(signature, connection);
|
|
1186
|
+
console.log("[useClaim] Step 2 done. Signature:", signature);
|
|
844
1187
|
const explorerUrl = `https://solscan.io/tx/${signature}`;
|
|
845
1188
|
const result = {
|
|
846
1189
|
gameId: params.gameId,
|
|
@@ -849,28 +1192,37 @@ function useClaim() {
|
|
|
849
1192
|
};
|
|
850
1193
|
setData(result);
|
|
851
1194
|
setStatus("success");
|
|
1195
|
+
console.log("[useClaim] Complete!");
|
|
852
1196
|
return result;
|
|
853
1197
|
} catch (err) {
|
|
1198
|
+
console.error("[useClaim] FAILED:", err);
|
|
854
1199
|
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
855
1200
|
setError(error2);
|
|
856
1201
|
setStatus("error");
|
|
857
1202
|
throw error2;
|
|
858
1203
|
}
|
|
859
|
-
}, [client, wallet
|
|
1204
|
+
}, [client, wallet]);
|
|
860
1205
|
return { execute, status, error, data, reset };
|
|
861
1206
|
}
|
|
862
1207
|
|
|
863
1208
|
// src/hooks/useAuth.ts
|
|
864
|
-
var
|
|
1209
|
+
var import_react10 = require("react");
|
|
865
1210
|
var import_bs58 = __toESM(require("bs58"));
|
|
1211
|
+
|
|
1212
|
+
// src/auth-context.ts
|
|
1213
|
+
var import_react9 = require("react");
|
|
1214
|
+
var AuthContext = (0, import_react9.createContext)(null);
|
|
1215
|
+
|
|
1216
|
+
// src/hooks/useAuth.ts
|
|
866
1217
|
function useAuth() {
|
|
1218
|
+
const sharedAuth = (0, import_react10.useContext)(AuthContext);
|
|
867
1219
|
const { client, wallet } = useDubs();
|
|
868
|
-
const [status, setStatus] = (0,
|
|
869
|
-
const [user, setUser] = (0,
|
|
870
|
-
const [token, setToken] = (0,
|
|
871
|
-
const [error, setError] = (0,
|
|
872
|
-
const pendingAuth = (0,
|
|
873
|
-
const reset = (0,
|
|
1220
|
+
const [status, setStatus] = (0, import_react10.useState)("idle");
|
|
1221
|
+
const [user, setUser] = (0, import_react10.useState)(null);
|
|
1222
|
+
const [token, setToken] = (0, import_react10.useState)(null);
|
|
1223
|
+
const [error, setError] = (0, import_react10.useState)(null);
|
|
1224
|
+
const pendingAuth = (0, import_react10.useRef)(null);
|
|
1225
|
+
const reset = (0, import_react10.useCallback)(() => {
|
|
874
1226
|
setStatus("idle");
|
|
875
1227
|
setUser(null);
|
|
876
1228
|
setToken(null);
|
|
@@ -878,7 +1230,7 @@ function useAuth() {
|
|
|
878
1230
|
pendingAuth.current = null;
|
|
879
1231
|
client.setToken(null);
|
|
880
1232
|
}, [client]);
|
|
881
|
-
const authenticate = (0,
|
|
1233
|
+
const authenticate = (0, import_react10.useCallback)(async () => {
|
|
882
1234
|
try {
|
|
883
1235
|
if (!wallet.publicKey) {
|
|
884
1236
|
throw new Error("Wallet not connected");
|
|
@@ -909,7 +1261,7 @@ function useAuth() {
|
|
|
909
1261
|
setStatus("error");
|
|
910
1262
|
}
|
|
911
1263
|
}, [client, wallet]);
|
|
912
|
-
const register = (0,
|
|
1264
|
+
const register = (0, import_react10.useCallback)(async (username, referralCode, avatarUrl) => {
|
|
913
1265
|
try {
|
|
914
1266
|
const pending = pendingAuth.current;
|
|
915
1267
|
if (!pending) {
|
|
@@ -926,7 +1278,8 @@ function useAuth() {
|
|
|
926
1278
|
avatarUrl
|
|
927
1279
|
});
|
|
928
1280
|
pendingAuth.current = null;
|
|
929
|
-
|
|
1281
|
+
const user2 = avatarUrl && !result.user.avatar ? { ...result.user, avatar: avatarUrl } : result.user;
|
|
1282
|
+
setUser(user2);
|
|
930
1283
|
setToken(result.token);
|
|
931
1284
|
setStatus("authenticated");
|
|
932
1285
|
} catch (err) {
|
|
@@ -934,7 +1287,7 @@ function useAuth() {
|
|
|
934
1287
|
setStatus("error");
|
|
935
1288
|
}
|
|
936
1289
|
}, [client]);
|
|
937
|
-
const logout = (0,
|
|
1290
|
+
const logout = (0, import_react10.useCallback)(async () => {
|
|
938
1291
|
try {
|
|
939
1292
|
await client.logout();
|
|
940
1293
|
} catch {
|
|
@@ -945,7 +1298,7 @@ function useAuth() {
|
|
|
945
1298
|
setError(null);
|
|
946
1299
|
pendingAuth.current = null;
|
|
947
1300
|
}, [client]);
|
|
948
|
-
const restoreSession = (0,
|
|
1301
|
+
const restoreSession = (0, import_react10.useCallback)(async (savedToken) => {
|
|
949
1302
|
try {
|
|
950
1303
|
client.setToken(savedToken);
|
|
951
1304
|
const me = await client.getMe();
|
|
@@ -961,6 +1314,7 @@ function useAuth() {
|
|
|
961
1314
|
return false;
|
|
962
1315
|
}
|
|
963
1316
|
}, [client]);
|
|
1317
|
+
if (sharedAuth) return sharedAuth;
|
|
964
1318
|
return {
|
|
965
1319
|
status,
|
|
966
1320
|
user,
|
|
@@ -976,50 +1330,7 @@ function useAuth() {
|
|
|
976
1330
|
}
|
|
977
1331
|
|
|
978
1332
|
// src/ui/AuthGate.tsx
|
|
979
|
-
var
|
|
980
|
-
var import_react_native2 = require("react-native");
|
|
981
|
-
|
|
982
|
-
// src/ui/theme.ts
|
|
983
|
-
var import_react_native = require("react-native");
|
|
984
|
-
var dark = {
|
|
985
|
-
background: "#08080D",
|
|
986
|
-
surface: "#111118",
|
|
987
|
-
surfaceActive: "#7C3AED",
|
|
988
|
-
border: "#1A1A24",
|
|
989
|
-
text: "#FFFFFF",
|
|
990
|
-
textSecondary: "#E0E0EE",
|
|
991
|
-
textMuted: "#666666",
|
|
992
|
-
textDim: "#555555",
|
|
993
|
-
accent: "#7C3AED",
|
|
994
|
-
success: "#22C55E",
|
|
995
|
-
live: "#EF4444",
|
|
996
|
-
errorText: "#F87171",
|
|
997
|
-
errorBg: "#1A0A0A",
|
|
998
|
-
errorBorder: "#3A1515"
|
|
999
|
-
};
|
|
1000
|
-
var light = {
|
|
1001
|
-
background: "#FFFFFF",
|
|
1002
|
-
surface: "#F0F0F5",
|
|
1003
|
-
surfaceActive: "#7C3AED",
|
|
1004
|
-
border: "#E0E0E8",
|
|
1005
|
-
text: "#111118",
|
|
1006
|
-
textSecondary: "#333333",
|
|
1007
|
-
textMuted: "#888888",
|
|
1008
|
-
textDim: "#999999",
|
|
1009
|
-
accent: "#7C3AED",
|
|
1010
|
-
success: "#16A34A",
|
|
1011
|
-
live: "#DC2626",
|
|
1012
|
-
errorText: "#DC2626",
|
|
1013
|
-
errorBg: "#FEF2F2",
|
|
1014
|
-
errorBorder: "#FECACA"
|
|
1015
|
-
};
|
|
1016
|
-
function useDubsTheme() {
|
|
1017
|
-
const scheme = (0, import_react_native.useColorScheme)();
|
|
1018
|
-
return scheme === "light" ? light : dark;
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
// src/ui/AuthGate.tsx
|
|
1022
|
-
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1333
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1023
1334
|
var DICEBEAR_STYLES = [
|
|
1024
1335
|
"adventurer",
|
|
1025
1336
|
"avataaars",
|
|
@@ -1041,13 +1352,14 @@ function AuthGate({
|
|
|
1041
1352
|
renderLoading,
|
|
1042
1353
|
renderError,
|
|
1043
1354
|
renderRegistration,
|
|
1044
|
-
appName = "Dubs"
|
|
1355
|
+
appName = "Dubs",
|
|
1356
|
+
accentColor
|
|
1045
1357
|
}) {
|
|
1046
1358
|
const { client } = useDubs();
|
|
1047
1359
|
const auth = useAuth();
|
|
1048
|
-
const [phase, setPhase] = (0,
|
|
1049
|
-
const [registrationPhase, setRegistrationPhase] = (0,
|
|
1050
|
-
(0,
|
|
1360
|
+
const [phase, setPhase] = (0, import_react11.useState)("init");
|
|
1361
|
+
const [registrationPhase, setRegistrationPhase] = (0, import_react11.useState)(false);
|
|
1362
|
+
(0, import_react11.useEffect)(() => {
|
|
1051
1363
|
let cancelled = false;
|
|
1052
1364
|
(async () => {
|
|
1053
1365
|
try {
|
|
@@ -1073,51 +1385,54 @@ function AuthGate({
|
|
|
1073
1385
|
cancelled = true;
|
|
1074
1386
|
};
|
|
1075
1387
|
}, []);
|
|
1076
|
-
(0,
|
|
1388
|
+
(0, import_react11.useEffect)(() => {
|
|
1077
1389
|
if (auth.status === "needsRegistration") setRegistrationPhase(true);
|
|
1078
1390
|
}, [auth.status]);
|
|
1079
|
-
(0,
|
|
1391
|
+
(0, import_react11.useEffect)(() => {
|
|
1080
1392
|
if (auth.token) onSaveToken(auth.token);
|
|
1081
1393
|
}, [auth.token]);
|
|
1082
|
-
const retry = (0,
|
|
1394
|
+
const retry = (0, import_react11.useCallback)(() => {
|
|
1083
1395
|
setRegistrationPhase(false);
|
|
1084
1396
|
auth.reset();
|
|
1085
1397
|
auth.authenticate();
|
|
1086
1398
|
}, [auth]);
|
|
1087
|
-
const handleRegister = (0,
|
|
1399
|
+
const handleRegister = (0, import_react11.useCallback)(
|
|
1088
1400
|
(username, referralCode, avatarUrl) => {
|
|
1089
1401
|
auth.register(username, referralCode, avatarUrl);
|
|
1090
1402
|
},
|
|
1091
1403
|
[auth]
|
|
1092
1404
|
);
|
|
1093
1405
|
if (phase === "init") {
|
|
1094
|
-
if (renderLoading) return /* @__PURE__ */ (0,
|
|
1095
|
-
return /* @__PURE__ */ (0,
|
|
1406
|
+
if (renderLoading) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: renderLoading("authenticating") });
|
|
1407
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DefaultLoadingScreen, { status: "authenticating", appName });
|
|
1408
|
+
}
|
|
1409
|
+
if (auth.status === "authenticated") {
|
|
1410
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AuthContext.Provider, { value: auth, children });
|
|
1096
1411
|
}
|
|
1097
|
-
if (auth.status === "authenticated") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
|
|
1098
1412
|
if (registrationPhase) {
|
|
1099
1413
|
const isRegistering = auth.status === "registering";
|
|
1100
1414
|
const regError = auth.status === "error" ? auth.error : null;
|
|
1101
1415
|
if (renderRegistration) {
|
|
1102
|
-
return /* @__PURE__ */ (0,
|
|
1416
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: renderRegistration({ onRegister: handleRegister, registering: isRegistering, error: regError, client }) });
|
|
1103
1417
|
}
|
|
1104
|
-
return /* @__PURE__ */ (0,
|
|
1418
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1105
1419
|
DefaultRegistrationScreen,
|
|
1106
1420
|
{
|
|
1107
1421
|
onRegister: handleRegister,
|
|
1108
1422
|
registering: isRegistering,
|
|
1109
1423
|
error: regError,
|
|
1110
1424
|
client,
|
|
1111
|
-
appName
|
|
1425
|
+
appName,
|
|
1426
|
+
accentColor
|
|
1112
1427
|
}
|
|
1113
1428
|
);
|
|
1114
1429
|
}
|
|
1115
1430
|
if (auth.status === "error" && auth.error) {
|
|
1116
|
-
if (renderError) return /* @__PURE__ */ (0,
|
|
1117
|
-
return /* @__PURE__ */ (0,
|
|
1431
|
+
if (renderError) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: renderError(auth.error, retry) });
|
|
1432
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DefaultErrorScreen, { error: auth.error, onRetry: retry, appName });
|
|
1118
1433
|
}
|
|
1119
|
-
if (renderLoading) return /* @__PURE__ */ (0,
|
|
1120
|
-
return /* @__PURE__ */ (0,
|
|
1434
|
+
if (renderLoading) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: renderLoading(auth.status) });
|
|
1435
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DefaultLoadingScreen, { status: auth.status, appName });
|
|
1121
1436
|
}
|
|
1122
1437
|
function DefaultLoadingScreen({ status, appName }) {
|
|
1123
1438
|
const t = useDubsTheme();
|
|
@@ -1131,43 +1446,43 @@ function DefaultLoadingScreen({ status, appName }) {
|
|
|
1131
1446
|
authenticated: "Ready!",
|
|
1132
1447
|
error: "Something went wrong"
|
|
1133
1448
|
};
|
|
1134
|
-
return /* @__PURE__ */ (0,
|
|
1135
|
-
/* @__PURE__ */ (0,
|
|
1136
|
-
/* @__PURE__ */ (0,
|
|
1137
|
-
/* @__PURE__ */ (0,
|
|
1449
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [s.container, { backgroundColor: t.background }], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.centerContent, children: [
|
|
1450
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.brandingSection, children: [
|
|
1451
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [s.logoCircle, { backgroundColor: t.accent }], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: s.logoText, children: "D" }) }),
|
|
1452
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.appNameText, { color: t.text }], children: appName })
|
|
1138
1453
|
] }),
|
|
1139
|
-
/* @__PURE__ */ (0,
|
|
1140
|
-
/* @__PURE__ */ (0,
|
|
1141
|
-
/* @__PURE__ */ (0,
|
|
1454
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.loadingSection, children: [
|
|
1455
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.ActivityIndicator, { size: "large", color: t.accent }),
|
|
1456
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.statusText, { color: t.textMuted }], children: statusText[status] || "Loading..." })
|
|
1142
1457
|
] })
|
|
1143
1458
|
] }) });
|
|
1144
1459
|
}
|
|
1145
1460
|
function DefaultErrorScreen({ error, onRetry, appName }) {
|
|
1146
1461
|
const t = useDubsTheme();
|
|
1147
|
-
return /* @__PURE__ */ (0,
|
|
1148
|
-
/* @__PURE__ */ (0,
|
|
1149
|
-
/* @__PURE__ */ (0,
|
|
1150
|
-
/* @__PURE__ */ (0,
|
|
1462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [s.container, { backgroundColor: t.background }], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.spreadContent, children: [
|
|
1463
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.brandingSection, children: [
|
|
1464
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [s.logoCircle, { backgroundColor: t.accent }], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: s.logoText, children: "D" }) }),
|
|
1465
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.appNameText, { color: t.text }], children: appName })
|
|
1151
1466
|
] }),
|
|
1152
|
-
/* @__PURE__ */ (0,
|
|
1153
|
-
/* @__PURE__ */ (0,
|
|
1154
|
-
/* @__PURE__ */ (0,
|
|
1467
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: { gap: 16 }, children: [
|
|
1468
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [s.errorBox, { backgroundColor: t.errorBg, borderColor: t.errorBorder }], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.errorText, { color: t.errorText }], children: error.message }) }),
|
|
1469
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.TouchableOpacity, { style: [s.primaryBtn, { backgroundColor: t.accent }], onPress: onRetry, activeOpacity: 0.8, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: s.primaryBtnText, children: "Try Again" }) })
|
|
1155
1470
|
] })
|
|
1156
1471
|
] }) });
|
|
1157
1472
|
}
|
|
1158
1473
|
function StepIndicator({ currentStep }) {
|
|
1159
1474
|
const t = useDubsTheme();
|
|
1160
1475
|
const steps = [0, 1, 2, 3];
|
|
1161
|
-
return /* @__PURE__ */ (0,
|
|
1162
|
-
i > 0 && /* @__PURE__ */ (0,
|
|
1163
|
-
/* @__PURE__ */ (0,
|
|
1164
|
-
|
|
1476
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: s.stepRow, children: steps.map((i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react11.default.Fragment, { children: [
|
|
1477
|
+
i > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [s.stepLine, { backgroundColor: i <= currentStep ? t.success : t.border }] }),
|
|
1478
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1479
|
+
import_react_native3.View,
|
|
1165
1480
|
{
|
|
1166
1481
|
style: [
|
|
1167
1482
|
s.stepCircle,
|
|
1168
1483
|
i < currentStep ? { backgroundColor: t.success } : i === currentStep ? { backgroundColor: t.accent } : { backgroundColor: "transparent", borderWidth: 2, borderColor: t.border }
|
|
1169
1484
|
],
|
|
1170
|
-
children: i < currentStep ? /* @__PURE__ */ (0,
|
|
1485
|
+
children: i < currentStep ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: s.stepCheck, children: "\u2713" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.stepNum, { color: i === currentStep ? "#FFF" : t.textMuted }], children: i + 1 })
|
|
1171
1486
|
}
|
|
1172
1487
|
)
|
|
1173
1488
|
] }, i)) });
|
|
@@ -1177,22 +1492,24 @@ function DefaultRegistrationScreen({
|
|
|
1177
1492
|
registering,
|
|
1178
1493
|
error,
|
|
1179
1494
|
client,
|
|
1180
|
-
appName
|
|
1495
|
+
appName,
|
|
1496
|
+
accentColor
|
|
1181
1497
|
}) {
|
|
1182
1498
|
const t = useDubsTheme();
|
|
1183
|
-
const
|
|
1184
|
-
const [
|
|
1185
|
-
const [
|
|
1186
|
-
const [
|
|
1187
|
-
const [
|
|
1188
|
-
const [
|
|
1189
|
-
const [
|
|
1190
|
-
const [
|
|
1191
|
-
const
|
|
1192
|
-
const
|
|
1193
|
-
const
|
|
1499
|
+
const accent = accentColor || t.accent;
|
|
1500
|
+
const [step, setStep] = (0, import_react11.useState)(0);
|
|
1501
|
+
const [avatarSeed, setAvatarSeed] = (0, import_react11.useState)(generateSeed);
|
|
1502
|
+
const [avatarStyle, setAvatarStyle] = (0, import_react11.useState)("adventurer");
|
|
1503
|
+
const [showStyles, setShowStyles] = (0, import_react11.useState)(false);
|
|
1504
|
+
const [username, setUsername] = (0, import_react11.useState)("");
|
|
1505
|
+
const [referralCode, setReferralCode] = (0, import_react11.useState)("");
|
|
1506
|
+
const [checking, setChecking] = (0, import_react11.useState)(false);
|
|
1507
|
+
const [availability, setAvailability] = (0, import_react11.useState)(null);
|
|
1508
|
+
const debounceRef = (0, import_react11.useRef)(null);
|
|
1509
|
+
const fadeAnim = (0, import_react11.useRef)(new import_react_native3.Animated.Value(1)).current;
|
|
1510
|
+
const slideAnim = (0, import_react11.useRef)(new import_react_native3.Animated.Value(0)).current;
|
|
1194
1511
|
const avatarUrl = getAvatarUrl(avatarStyle, avatarSeed);
|
|
1195
|
-
(0,
|
|
1512
|
+
(0, import_react11.useEffect)(() => {
|
|
1196
1513
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
1197
1514
|
const trimmed = username.trim();
|
|
1198
1515
|
if (trimmed.length < 3) {
|
|
@@ -1215,96 +1532,96 @@ function DefaultRegistrationScreen({
|
|
|
1215
1532
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
1216
1533
|
};
|
|
1217
1534
|
}, [username, client]);
|
|
1218
|
-
const animateToStep = (0,
|
|
1535
|
+
const animateToStep = (0, import_react11.useCallback)((newStep) => {
|
|
1219
1536
|
const dir = newStep > step ? 1 : -1;
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1537
|
+
import_react_native3.Keyboard.dismiss();
|
|
1538
|
+
import_react_native3.Animated.parallel([
|
|
1539
|
+
import_react_native3.Animated.timing(fadeAnim, { toValue: 0, duration: 120, useNativeDriver: true }),
|
|
1540
|
+
import_react_native3.Animated.timing(slideAnim, { toValue: -dir * 40, duration: 120, useNativeDriver: true })
|
|
1224
1541
|
]).start(() => {
|
|
1225
1542
|
setStep(newStep);
|
|
1226
1543
|
slideAnim.setValue(dir * 40);
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1544
|
+
import_react_native3.Animated.parallel([
|
|
1545
|
+
import_react_native3.Animated.timing(fadeAnim, { toValue: 1, duration: 200, useNativeDriver: true }),
|
|
1546
|
+
import_react_native3.Animated.timing(slideAnim, { toValue: 0, duration: 200, useNativeDriver: true })
|
|
1230
1547
|
]).start();
|
|
1231
1548
|
});
|
|
1232
1549
|
}, [step, fadeAnim, slideAnim]);
|
|
1233
1550
|
const canContinueUsername = username.trim().length >= 3 && availability?.available === true && !checking;
|
|
1234
1551
|
const handleSubmit = () => {
|
|
1235
|
-
|
|
1552
|
+
import_react_native3.Keyboard.dismiss();
|
|
1236
1553
|
onRegister(username.trim(), referralCode.trim() || void 0, avatarUrl);
|
|
1237
1554
|
};
|
|
1238
|
-
const renderAvatarStep = () => /* @__PURE__ */ (0,
|
|
1239
|
-
/* @__PURE__ */ (0,
|
|
1240
|
-
/* @__PURE__ */ (0,
|
|
1241
|
-
/* @__PURE__ */ (0,
|
|
1242
|
-
/* @__PURE__ */ (0,
|
|
1243
|
-
/* @__PURE__ */ (0,
|
|
1244
|
-
/* @__PURE__ */ (0,
|
|
1245
|
-
/* @__PURE__ */ (0,
|
|
1555
|
+
const renderAvatarStep = () => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.stepContainer, children: [
|
|
1556
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.stepTop, children: [
|
|
1557
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.title, { color: t.text }], children: "Choose Your Avatar" }),
|
|
1558
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.subtitle, { color: t.textMuted }], children: "Pick a look that represents you" }),
|
|
1559
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StepIndicator, { currentStep: 0 }),
|
|
1560
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: s.avatarCenter, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: [s.avatarFrame, { borderColor: accent }], children: [
|
|
1561
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Image, { source: { uri: avatarUrl }, style: s.avatarLarge }),
|
|
1562
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [s.checkBadge, { backgroundColor: t.success }], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: s.checkBadgeText, children: "\u2713" }) })
|
|
1246
1563
|
] }) }),
|
|
1247
|
-
/* @__PURE__ */ (0,
|
|
1248
|
-
/* @__PURE__ */ (0,
|
|
1249
|
-
|
|
1564
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.avatarActions, children: [
|
|
1565
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1566
|
+
import_react_native3.TouchableOpacity,
|
|
1250
1567
|
{
|
|
1251
1568
|
style: [s.outlineBtn, { borderColor: t.border }],
|
|
1252
1569
|
onPress: () => setAvatarSeed(generateSeed()),
|
|
1253
1570
|
activeOpacity: 0.7,
|
|
1254
|
-
children: /* @__PURE__ */ (0,
|
|
1571
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.outlineBtnText, { color: t.text }], children: "\u21BB Shuffle" })
|
|
1255
1572
|
}
|
|
1256
1573
|
),
|
|
1257
|
-
/* @__PURE__ */ (0,
|
|
1258
|
-
|
|
1574
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1575
|
+
import_react_native3.TouchableOpacity,
|
|
1259
1576
|
{
|
|
1260
|
-
style: [s.outlineBtn, { borderColor:
|
|
1577
|
+
style: [s.outlineBtn, { borderColor: accent, backgroundColor: accent + "15" }],
|
|
1261
1578
|
onPress: () => setShowStyles(!showStyles),
|
|
1262
1579
|
activeOpacity: 0.7,
|
|
1263
|
-
children: /* @__PURE__ */ (0,
|
|
1580
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.outlineBtnText, { color: accent }], children: "\u263A Customize" })
|
|
1264
1581
|
}
|
|
1265
1582
|
)
|
|
1266
1583
|
] }),
|
|
1267
|
-
showStyles && /* @__PURE__ */ (0,
|
|
1268
|
-
|
|
1584
|
+
showStyles && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, style: s.styleScroll, children: DICEBEAR_STYLES.map((st) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1585
|
+
import_react_native3.TouchableOpacity,
|
|
1269
1586
|
{
|
|
1270
1587
|
onPress: () => setAvatarStyle(st),
|
|
1271
|
-
style: [s.styleThumbWrap, { borderColor: st === avatarStyle ?
|
|
1272
|
-
children: /* @__PURE__ */ (0,
|
|
1588
|
+
style: [s.styleThumbWrap, { borderColor: st === avatarStyle ? accent : t.border }],
|
|
1589
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Image, { source: { uri: getAvatarUrl(st, avatarSeed, 80) }, style: s.styleThumb })
|
|
1273
1590
|
},
|
|
1274
1591
|
st
|
|
1275
1592
|
)) })
|
|
1276
1593
|
] }),
|
|
1277
|
-
/* @__PURE__ */ (0,
|
|
1278
|
-
|
|
1594
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: s.bottomRow, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1595
|
+
import_react_native3.TouchableOpacity,
|
|
1279
1596
|
{
|
|
1280
|
-
style: [s.primaryBtn, { backgroundColor:
|
|
1597
|
+
style: [s.primaryBtn, { backgroundColor: accent, flex: 1 }],
|
|
1281
1598
|
onPress: () => animateToStep(1),
|
|
1282
1599
|
activeOpacity: 0.8,
|
|
1283
|
-
children: /* @__PURE__ */ (0,
|
|
1600
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: s.primaryBtnText, children: "Continue \u203A" })
|
|
1284
1601
|
}
|
|
1285
1602
|
) })
|
|
1286
1603
|
] });
|
|
1287
|
-
const renderUsernameStep = () => /* @__PURE__ */ (0,
|
|
1288
|
-
/* @__PURE__ */ (0,
|
|
1289
|
-
/* @__PURE__ */ (0,
|
|
1290
|
-
/* @__PURE__ */ (0,
|
|
1291
|
-
/* @__PURE__ */ (0,
|
|
1604
|
+
const renderUsernameStep = () => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.stepContainer, children: [
|
|
1605
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.stepTop, children: [
|
|
1606
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.headerRow, children: [
|
|
1607
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.TouchableOpacity, { onPress: () => animateToStep(0), hitSlop: { top: 12, bottom: 12, left: 12, right: 12 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.backChevron, { color: t.text }], children: "\u2039" }) }),
|
|
1608
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.titleInline, { color: t.text }], children: "Pick a Username" })
|
|
1292
1609
|
] }),
|
|
1293
|
-
/* @__PURE__ */ (0,
|
|
1294
|
-
/* @__PURE__ */ (0,
|
|
1295
|
-
/* @__PURE__ */ (0,
|
|
1296
|
-
/* @__PURE__ */ (0,
|
|
1297
|
-
/* @__PURE__ */ (0,
|
|
1610
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.subtitle, { color: t.textMuted }], children: "This is how others will see you" }),
|
|
1611
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StepIndicator, { currentStep: 1 }),
|
|
1612
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: s.avatarCenter, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: [s.avatarFrameSmall, { borderColor: accent }], children: [
|
|
1613
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Image, { source: { uri: avatarUrl }, style: s.avatarSmall }),
|
|
1614
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [s.checkBadgeSm, { backgroundColor: t.success }], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: s.checkBadgeTextSm, children: "\u2713" }) })
|
|
1298
1615
|
] }) }),
|
|
1299
|
-
/* @__PURE__ */ (0,
|
|
1300
|
-
/* @__PURE__ */ (0,
|
|
1616
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.inputGroup, children: [
|
|
1617
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.Text, { style: [s.inputLabel, { color: t.text }], children: [
|
|
1301
1618
|
"Username ",
|
|
1302
|
-
/* @__PURE__ */ (0,
|
|
1619
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: { color: t.errorText }, children: "*" })
|
|
1303
1620
|
] }),
|
|
1304
|
-
/* @__PURE__ */ (0,
|
|
1305
|
-
|
|
1621
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1622
|
+
import_react_native3.TextInput,
|
|
1306
1623
|
{
|
|
1307
|
-
style: [s.input, { backgroundColor: t.surface, color: t.text, borderColor:
|
|
1624
|
+
style: [s.input, { backgroundColor: t.surface, color: t.text, borderColor: accent }],
|
|
1308
1625
|
placeholder: "Enter username",
|
|
1309
1626
|
placeholderTextColor: t.textDim,
|
|
1310
1627
|
value: username,
|
|
@@ -1314,63 +1631,63 @@ function DefaultRegistrationScreen({
|
|
|
1314
1631
|
autoFocus: true
|
|
1315
1632
|
}
|
|
1316
1633
|
),
|
|
1317
|
-
checking ? /* @__PURE__ */ (0,
|
|
1634
|
+
checking ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.hint, { color: t.textDim }], children: "Checking..." }) : availability ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.hint, { color: availability.available ? t.success : t.errorText }], children: availability.available ? "\u2713 Available!" : availability.reason || "Username taken" }) : username.trim().length > 0 && username.trim().length < 3 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.hint, { color: t.textDim }], children: "At least 3 characters" }) : null
|
|
1318
1635
|
] })
|
|
1319
1636
|
] }),
|
|
1320
|
-
/* @__PURE__ */ (0,
|
|
1321
|
-
/* @__PURE__ */ (0,
|
|
1322
|
-
|
|
1637
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.bottomRow, children: [
|
|
1638
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1639
|
+
import_react_native3.TouchableOpacity,
|
|
1323
1640
|
{
|
|
1324
1641
|
style: [s.secondaryBtn, { borderColor: t.border }],
|
|
1325
1642
|
onPress: () => animateToStep(0),
|
|
1326
1643
|
activeOpacity: 0.7,
|
|
1327
|
-
children: /* @__PURE__ */ (0,
|
|
1644
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.secondaryBtnText, { color: t.text }], children: "\u2039 Back" })
|
|
1328
1645
|
}
|
|
1329
1646
|
),
|
|
1330
|
-
/* @__PURE__ */ (0,
|
|
1331
|
-
|
|
1647
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1648
|
+
import_react_native3.TouchableOpacity,
|
|
1332
1649
|
{
|
|
1333
|
-
style: [s.primaryBtn, { backgroundColor:
|
|
1650
|
+
style: [s.primaryBtn, { backgroundColor: accent, flex: 1, opacity: canContinueUsername ? 1 : 0.4 }],
|
|
1334
1651
|
onPress: () => animateToStep(2),
|
|
1335
1652
|
disabled: !canContinueUsername,
|
|
1336
1653
|
activeOpacity: 0.8,
|
|
1337
|
-
children: /* @__PURE__ */ (0,
|
|
1654
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: s.primaryBtnText, children: "Continue \u203A" })
|
|
1338
1655
|
}
|
|
1339
1656
|
)
|
|
1340
1657
|
] })
|
|
1341
1658
|
] });
|
|
1342
|
-
const renderReferralStep = () => /* @__PURE__ */ (0,
|
|
1343
|
-
/* @__PURE__ */ (0,
|
|
1344
|
-
/* @__PURE__ */ (0,
|
|
1345
|
-
/* @__PURE__ */ (0,
|
|
1346
|
-
/* @__PURE__ */ (0,
|
|
1659
|
+
const renderReferralStep = () => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.stepContainer, children: [
|
|
1660
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.stepTop, children: [
|
|
1661
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.headerRow, children: [
|
|
1662
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.TouchableOpacity, { onPress: () => animateToStep(1), hitSlop: { top: 12, bottom: 12, left: 12, right: 12 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.backChevron, { color: t.text }], children: "\u2039" }) }),
|
|
1663
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.titleInline, { color: t.text }], children: "Almost There!" })
|
|
1347
1664
|
] }),
|
|
1348
|
-
/* @__PURE__ */ (0,
|
|
1349
|
-
/* @__PURE__ */ (0,
|
|
1350
|
-
/* @__PURE__ */ (0,
|
|
1351
|
-
/* @__PURE__ */ (0,
|
|
1352
|
-
/* @__PURE__ */ (0,
|
|
1353
|
-
/* @__PURE__ */ (0,
|
|
1354
|
-
/* @__PURE__ */ (0,
|
|
1355
|
-
/* @__PURE__ */ (0,
|
|
1665
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.subtitle, { color: t.textMuted }], children: "Got a referral code? (optional)" }),
|
|
1666
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StepIndicator, { currentStep: 2 }),
|
|
1667
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: [s.profileCard, { borderColor: t.border }], children: [
|
|
1668
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.profileLabel, { color: t.textMuted }], children: "Your Profile" }),
|
|
1669
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.profileRow, children: [
|
|
1670
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Image, { source: { uri: avatarUrl }, style: s.profileAvatar }),
|
|
1671
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: { gap: 4 }, children: [
|
|
1672
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.Text, { style: [s.profileUsername, { color: t.text }], children: [
|
|
1356
1673
|
"@",
|
|
1357
1674
|
username
|
|
1358
1675
|
] }),
|
|
1359
|
-
/* @__PURE__ */ (0,
|
|
1676
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.Text, { style: [s.profileReady, { color: t.success }], children: [
|
|
1360
1677
|
"\u2713",
|
|
1361
1678
|
" Ready to go!"
|
|
1362
1679
|
] })
|
|
1363
1680
|
] })
|
|
1364
1681
|
] })
|
|
1365
1682
|
] }),
|
|
1366
|
-
error ? /* @__PURE__ */ (0,
|
|
1367
|
-
/* @__PURE__ */ (0,
|
|
1368
|
-
/* @__PURE__ */ (0,
|
|
1683
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [s.errorBox, { backgroundColor: t.errorBg, borderColor: t.errorBorder }], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.errorText, { color: t.errorText }], children: error.message }) }) : null,
|
|
1684
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.inputGroup, children: [
|
|
1685
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.Text, { style: [s.inputLabel, { color: t.text }], children: [
|
|
1369
1686
|
"Referral Code ",
|
|
1370
|
-
/* @__PURE__ */ (0,
|
|
1687
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: { color: t.textMuted }, children: "(optional)" })
|
|
1371
1688
|
] }),
|
|
1372
|
-
/* @__PURE__ */ (0,
|
|
1373
|
-
|
|
1689
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1690
|
+
import_react_native3.TextInput,
|
|
1374
1691
|
{
|
|
1375
1692
|
style: [s.input, { backgroundColor: t.surface, color: t.text, borderColor: t.border }],
|
|
1376
1693
|
placeholder: "Enter referral code",
|
|
@@ -1382,31 +1699,31 @@ function DefaultRegistrationScreen({
|
|
|
1382
1699
|
editable: !registering
|
|
1383
1700
|
}
|
|
1384
1701
|
),
|
|
1385
|
-
/* @__PURE__ */ (0,
|
|
1702
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.Text, { style: [s.hint, { color: t.textMuted }], children: [
|
|
1386
1703
|
"\u{1F381}",
|
|
1387
1704
|
" If a friend invited you, enter their code to give them credit!"
|
|
1388
1705
|
] })
|
|
1389
1706
|
] })
|
|
1390
1707
|
] }),
|
|
1391
|
-
/* @__PURE__ */ (0,
|
|
1392
|
-
/* @__PURE__ */ (0,
|
|
1393
|
-
|
|
1708
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: s.bottomRow, children: [
|
|
1709
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1710
|
+
import_react_native3.TouchableOpacity,
|
|
1394
1711
|
{
|
|
1395
1712
|
style: [s.secondaryBtn, { borderColor: t.border }],
|
|
1396
1713
|
onPress: () => animateToStep(1),
|
|
1397
1714
|
disabled: registering,
|
|
1398
1715
|
activeOpacity: 0.7,
|
|
1399
|
-
children: /* @__PURE__ */ (0,
|
|
1716
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: [s.secondaryBtnText, { color: t.text }], children: "\u2039 Back" })
|
|
1400
1717
|
}
|
|
1401
1718
|
),
|
|
1402
|
-
/* @__PURE__ */ (0,
|
|
1403
|
-
|
|
1719
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1720
|
+
import_react_native3.TouchableOpacity,
|
|
1404
1721
|
{
|
|
1405
|
-
style: [s.primaryBtn, { backgroundColor:
|
|
1722
|
+
style: [s.primaryBtn, { backgroundColor: accent, flex: 1, opacity: registering ? 0.7 : 1 }],
|
|
1406
1723
|
onPress: handleSubmit,
|
|
1407
1724
|
disabled: registering,
|
|
1408
1725
|
activeOpacity: 0.8,
|
|
1409
|
-
children: registering ? /* @__PURE__ */ (0,
|
|
1726
|
+
children: registering ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.ActivityIndicator, { color: "#FFFFFF", size: "small" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: s.primaryBtnText, children: "Create Account" })
|
|
1410
1727
|
}
|
|
1411
1728
|
)
|
|
1412
1729
|
] })
|
|
@@ -1423,19 +1740,19 @@ function DefaultRegistrationScreen({
|
|
|
1423
1740
|
return null;
|
|
1424
1741
|
}
|
|
1425
1742
|
};
|
|
1426
|
-
return /* @__PURE__ */ (0,
|
|
1427
|
-
|
|
1743
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1744
|
+
import_react_native3.KeyboardAvoidingView,
|
|
1428
1745
|
{
|
|
1429
1746
|
style: [s.container, { backgroundColor: t.background }],
|
|
1430
|
-
behavior:
|
|
1431
|
-
children: /* @__PURE__ */ (0,
|
|
1432
|
-
|
|
1747
|
+
behavior: import_react_native3.Platform.OS === "ios" ? "padding" : void 0,
|
|
1748
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1749
|
+
import_react_native3.ScrollView,
|
|
1433
1750
|
{
|
|
1434
1751
|
contentContainerStyle: { flexGrow: 1 },
|
|
1435
1752
|
keyboardShouldPersistTaps: "handled",
|
|
1436
1753
|
bounces: false,
|
|
1437
|
-
children: /* @__PURE__ */ (0,
|
|
1438
|
-
|
|
1754
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1755
|
+
import_react_native3.Animated.View,
|
|
1439
1756
|
{
|
|
1440
1757
|
style: [
|
|
1441
1758
|
{ flex: 1 },
|
|
@@ -1449,7 +1766,7 @@ function DefaultRegistrationScreen({
|
|
|
1449
1766
|
}
|
|
1450
1767
|
);
|
|
1451
1768
|
}
|
|
1452
|
-
var s =
|
|
1769
|
+
var s = import_react_native3.StyleSheet.create({
|
|
1453
1770
|
container: { flex: 1 },
|
|
1454
1771
|
// Loading / Error
|
|
1455
1772
|
centerContent: { flex: 1, justifyContent: "center", alignItems: "center", paddingHorizontal: 32, gap: 48 },
|
|
@@ -1512,119 +1829,179 @@ var s = import_react_native2.StyleSheet.create({
|
|
|
1512
1829
|
secondaryBtnText: { fontSize: 16, fontWeight: "600" }
|
|
1513
1830
|
});
|
|
1514
1831
|
|
|
1515
|
-
// src/
|
|
1516
|
-
var
|
|
1517
|
-
var
|
|
1518
|
-
function
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1832
|
+
// src/provider.tsx
|
|
1833
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1834
|
+
var DubsContext = (0, import_react12.createContext)(null);
|
|
1835
|
+
function DubsProvider({
|
|
1836
|
+
apiKey,
|
|
1837
|
+
children,
|
|
1838
|
+
appName = "Dubs",
|
|
1839
|
+
network = "mainnet-beta",
|
|
1840
|
+
wallet: externalWallet,
|
|
1841
|
+
tokenStorage,
|
|
1842
|
+
baseUrl: baseUrlOverride,
|
|
1843
|
+
rpcUrl: rpcUrlOverride,
|
|
1844
|
+
renderConnectScreen,
|
|
1845
|
+
renderLoading,
|
|
1846
|
+
renderError,
|
|
1847
|
+
renderRegistration,
|
|
1848
|
+
managed = true
|
|
1523
1849
|
}) {
|
|
1524
|
-
const
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1850
|
+
const config = NETWORK_CONFIG[network];
|
|
1851
|
+
const baseUrl = baseUrlOverride || config.baseUrl;
|
|
1852
|
+
const rpcUrl = rpcUrlOverride || config.rpcUrl;
|
|
1853
|
+
const cluster = config.cluster;
|
|
1854
|
+
const client = (0, import_react12.useMemo)(() => new DubsClient({ apiKey, baseUrl }), [apiKey, baseUrl]);
|
|
1855
|
+
const connection = (0, import_react12.useMemo)(() => new import_web33.Connection(rpcUrl, { commitment: "confirmed" }), [rpcUrl]);
|
|
1856
|
+
const storage = (0, import_react12.useMemo)(() => tokenStorage || createSecureStoreStorage(), [tokenStorage]);
|
|
1857
|
+
const [uiConfig, setUiConfig] = (0, import_react12.useState)({});
|
|
1858
|
+
(0, import_react12.useEffect)(() => {
|
|
1859
|
+
client.getAppConfig().then(setUiConfig).catch(() => {
|
|
1860
|
+
});
|
|
1861
|
+
}, [client]);
|
|
1862
|
+
if (externalWallet) {
|
|
1863
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1864
|
+
ExternalWalletProvider,
|
|
1865
|
+
{
|
|
1866
|
+
client,
|
|
1867
|
+
connection,
|
|
1868
|
+
wallet: externalWallet,
|
|
1869
|
+
appName: uiConfig.appName || appName,
|
|
1870
|
+
network,
|
|
1871
|
+
storage,
|
|
1872
|
+
managed,
|
|
1873
|
+
renderLoading,
|
|
1874
|
+
renderError,
|
|
1875
|
+
renderRegistration,
|
|
1876
|
+
accentColor: uiConfig.accentColor,
|
|
1877
|
+
children
|
|
1878
|
+
}
|
|
1879
|
+
);
|
|
1880
|
+
}
|
|
1881
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1882
|
+
ManagedWalletProvider,
|
|
1883
|
+
{
|
|
1884
|
+
appName: uiConfig.appName || appName,
|
|
1885
|
+
cluster,
|
|
1886
|
+
storage,
|
|
1887
|
+
renderConnectScreen,
|
|
1888
|
+
accentColor: uiConfig.accentColor,
|
|
1889
|
+
appIcon: uiConfig.appIcon,
|
|
1890
|
+
tagline: uiConfig.tagline,
|
|
1891
|
+
children: (adapter) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1892
|
+
ManagedInner,
|
|
1544
1893
|
{
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1894
|
+
client,
|
|
1895
|
+
connection,
|
|
1896
|
+
wallet: adapter,
|
|
1897
|
+
appName: uiConfig.appName || appName,
|
|
1898
|
+
network,
|
|
1899
|
+
storage,
|
|
1900
|
+
renderLoading,
|
|
1901
|
+
renderError,
|
|
1902
|
+
renderRegistration,
|
|
1903
|
+
accentColor: uiConfig.accentColor,
|
|
1904
|
+
children
|
|
1550
1905
|
}
|
|
1551
|
-
)
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
] }) });
|
|
1906
|
+
)
|
|
1907
|
+
}
|
|
1908
|
+
);
|
|
1555
1909
|
}
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
}
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1910
|
+
function ManagedInner({
|
|
1911
|
+
client,
|
|
1912
|
+
connection,
|
|
1913
|
+
wallet,
|
|
1914
|
+
appName,
|
|
1915
|
+
network,
|
|
1916
|
+
storage,
|
|
1917
|
+
renderLoading,
|
|
1918
|
+
renderError,
|
|
1919
|
+
renderRegistration,
|
|
1920
|
+
accentColor,
|
|
1921
|
+
children
|
|
1922
|
+
}) {
|
|
1923
|
+
const managedDisconnect = useDisconnect();
|
|
1924
|
+
const disconnect = (0, import_react12.useCallback)(async () => {
|
|
1925
|
+
client.setToken(null);
|
|
1926
|
+
await managedDisconnect?.();
|
|
1927
|
+
}, [client, managedDisconnect]);
|
|
1928
|
+
const value = (0, import_react12.useMemo)(
|
|
1929
|
+
() => ({ client, wallet, connection, appName, network, disconnect }),
|
|
1930
|
+
[client, wallet, connection, appName, network, disconnect]
|
|
1931
|
+
);
|
|
1932
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DubsContext.Provider, { value, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1933
|
+
AuthGate,
|
|
1934
|
+
{
|
|
1935
|
+
onSaveToken: (token) => {
|
|
1936
|
+
if (token) return storage.setItem(STORAGE_KEYS.JWT_TOKEN, token);
|
|
1937
|
+
return storage.deleteItem(STORAGE_KEYS.JWT_TOKEN);
|
|
1938
|
+
},
|
|
1939
|
+
onLoadToken: () => storage.getItem(STORAGE_KEYS.JWT_TOKEN),
|
|
1940
|
+
renderLoading,
|
|
1941
|
+
renderError,
|
|
1942
|
+
renderRegistration,
|
|
1943
|
+
appName,
|
|
1944
|
+
accentColor,
|
|
1945
|
+
children
|
|
1946
|
+
}
|
|
1947
|
+
) });
|
|
1948
|
+
}
|
|
1949
|
+
function ExternalWalletProvider({
|
|
1950
|
+
client,
|
|
1951
|
+
connection,
|
|
1952
|
+
wallet,
|
|
1953
|
+
appName,
|
|
1954
|
+
network,
|
|
1955
|
+
storage,
|
|
1956
|
+
managed,
|
|
1957
|
+
renderLoading,
|
|
1958
|
+
renderError,
|
|
1959
|
+
renderRegistration,
|
|
1960
|
+
accentColor,
|
|
1961
|
+
children
|
|
1962
|
+
}) {
|
|
1963
|
+
const disconnect = (0, import_react12.useCallback)(async () => {
|
|
1964
|
+
client.setToken(null);
|
|
1965
|
+
await storage.deleteItem(STORAGE_KEYS.JWT_TOKEN).catch(() => {
|
|
1966
|
+
});
|
|
1967
|
+
await wallet.disconnect?.();
|
|
1968
|
+
}, [client, storage, wallet]);
|
|
1969
|
+
const value = (0, import_react12.useMemo)(
|
|
1970
|
+
() => ({ client, wallet, connection, appName, network, disconnect }),
|
|
1971
|
+
[client, wallet, connection, appName, network, disconnect]
|
|
1972
|
+
);
|
|
1973
|
+
if (!managed) {
|
|
1974
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DubsContext.Provider, { value, children });
|
|
1621
1975
|
}
|
|
1622
|
-
|
|
1976
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DubsContext.Provider, { value, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1977
|
+
AuthGate,
|
|
1978
|
+
{
|
|
1979
|
+
onSaveToken: (token) => {
|
|
1980
|
+
if (token) return storage.setItem(STORAGE_KEYS.JWT_TOKEN, token);
|
|
1981
|
+
return storage.deleteItem(STORAGE_KEYS.JWT_TOKEN);
|
|
1982
|
+
},
|
|
1983
|
+
onLoadToken: () => storage.getItem(STORAGE_KEYS.JWT_TOKEN),
|
|
1984
|
+
renderLoading,
|
|
1985
|
+
renderError,
|
|
1986
|
+
renderRegistration,
|
|
1987
|
+
appName,
|
|
1988
|
+
accentColor,
|
|
1989
|
+
children
|
|
1990
|
+
}
|
|
1991
|
+
) });
|
|
1992
|
+
}
|
|
1993
|
+
function useDubs() {
|
|
1994
|
+
const ctx = (0, import_react12.useContext)(DubsContext);
|
|
1995
|
+
if (!ctx) {
|
|
1996
|
+
throw new Error("useDubs must be used within a <DubsProvider>");
|
|
1997
|
+
}
|
|
1998
|
+
return ctx;
|
|
1999
|
+
}
|
|
1623
2000
|
|
|
1624
2001
|
// src/ui/UserProfileCard.tsx
|
|
1625
|
-
var
|
|
2002
|
+
var import_react13 = require("react");
|
|
1626
2003
|
var import_react_native4 = require("react-native");
|
|
1627
|
-
var
|
|
2004
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1628
2005
|
function truncateAddress(address, chars = 4) {
|
|
1629
2006
|
if (address.length <= chars * 2 + 3) return address;
|
|
1630
2007
|
return `${address.slice(0, chars)}...${address.slice(-chars)}`;
|
|
@@ -1642,16 +2019,16 @@ function UserProfileCard({
|
|
|
1642
2019
|
memberSince
|
|
1643
2020
|
}) {
|
|
1644
2021
|
const t = useDubsTheme();
|
|
1645
|
-
const imageUri = (0,
|
|
2022
|
+
const imageUri = (0, import_react13.useMemo)(
|
|
1646
2023
|
() => avatarUrl || `https://api.dicebear.com/9.x/avataaars/png?seed=${walletAddress}&size=128`,
|
|
1647
2024
|
[avatarUrl, walletAddress]
|
|
1648
2025
|
);
|
|
1649
|
-
return /* @__PURE__ */ (0,
|
|
1650
|
-
/* @__PURE__ */ (0,
|
|
1651
|
-
/* @__PURE__ */ (0,
|
|
1652
|
-
username ? /* @__PURE__ */ (0,
|
|
1653
|
-
/* @__PURE__ */ (0,
|
|
1654
|
-
memberSince ? /* @__PURE__ */ (0,
|
|
2026
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { style: [styles2.card, { backgroundColor: t.surface, borderColor: t.border }], children: [
|
|
2027
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native4.Image, { source: { uri: imageUri }, style: styles2.avatar }),
|
|
2028
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { style: styles2.info, children: [
|
|
2029
|
+
username ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native4.Text, { style: [styles2.username, { color: t.text }], children: username }) : null,
|
|
2030
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native4.Text, { style: [styles2.address, { color: t.textMuted }], children: truncateAddress(walletAddress) }),
|
|
2031
|
+
memberSince ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native4.Text, { style: [styles2.memberSince, { color: t.textDim }], children: formatMemberSince(memberSince) }) : null
|
|
1655
2032
|
] })
|
|
1656
2033
|
] });
|
|
1657
2034
|
}
|
|
@@ -1690,7 +2067,7 @@ var styles2 = import_react_native4.StyleSheet.create({
|
|
|
1690
2067
|
|
|
1691
2068
|
// src/ui/SettingsSheet.tsx
|
|
1692
2069
|
var import_react_native5 = require("react-native");
|
|
1693
|
-
var
|
|
2070
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1694
2071
|
function truncateAddress2(address, chars = 4) {
|
|
1695
2072
|
if (address.length <= chars * 2 + 3) return address;
|
|
1696
2073
|
return `${address.slice(0, chars)}...${address.slice(-chars)}`;
|
|
@@ -1707,13 +2084,13 @@ function SettingsSheet({
|
|
|
1707
2084
|
loggingOut = false
|
|
1708
2085
|
}) {
|
|
1709
2086
|
const t = useDubsTheme();
|
|
1710
|
-
return /* @__PURE__ */ (0,
|
|
2087
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1711
2088
|
import_react_native5.ScrollView,
|
|
1712
2089
|
{
|
|
1713
2090
|
style: [styles3.container, { backgroundColor: t.background }],
|
|
1714
2091
|
contentContainerStyle: styles3.content,
|
|
1715
2092
|
children: [
|
|
1716
|
-
/* @__PURE__ */ (0,
|
|
2093
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1717
2094
|
UserProfileCard,
|
|
1718
2095
|
{
|
|
1719
2096
|
walletAddress,
|
|
@@ -1722,49 +2099,49 @@ function SettingsSheet({
|
|
|
1722
2099
|
memberSince
|
|
1723
2100
|
}
|
|
1724
2101
|
),
|
|
1725
|
-
/* @__PURE__ */ (0,
|
|
1726
|
-
onCopyAddress ? /* @__PURE__ */ (0,
|
|
2102
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native5.View, { style: [styles3.actionsCard, { backgroundColor: t.surface, borderColor: t.border }], children: [
|
|
2103
|
+
onCopyAddress ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1727
2104
|
import_react_native5.TouchableOpacity,
|
|
1728
2105
|
{
|
|
1729
2106
|
style: styles3.actionRow,
|
|
1730
2107
|
onPress: onCopyAddress,
|
|
1731
2108
|
activeOpacity: 0.7,
|
|
1732
2109
|
children: [
|
|
1733
|
-
/* @__PURE__ */ (0,
|
|
1734
|
-
/* @__PURE__ */ (0,
|
|
1735
|
-
/* @__PURE__ */ (0,
|
|
2110
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native5.View, { style: styles3.actionRowLeft, children: [
|
|
2111
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native5.Text, { style: [styles3.actionLabel, { color: t.text }], children: "Wallet Address" }),
|
|
2112
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native5.Text, { style: [styles3.actionValue, { color: t.textMuted }], children: truncateAddress2(walletAddress) })
|
|
1736
2113
|
] }),
|
|
1737
|
-
/* @__PURE__ */ (0,
|
|
2114
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native5.Text, { style: [styles3.copyLabel, { color: t.accent }], children: "Copy" })
|
|
1738
2115
|
]
|
|
1739
2116
|
}
|
|
1740
2117
|
) : null,
|
|
1741
|
-
onSupport ? /* @__PURE__ */ (0,
|
|
1742
|
-
onCopyAddress ? /* @__PURE__ */ (0,
|
|
1743
|
-
/* @__PURE__ */ (0,
|
|
2118
|
+
onSupport ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2119
|
+
onCopyAddress ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native5.View, { style: [styles3.separator, { backgroundColor: t.border }] }) : null,
|
|
2120
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1744
2121
|
import_react_native5.TouchableOpacity,
|
|
1745
2122
|
{
|
|
1746
2123
|
style: styles3.actionRow,
|
|
1747
2124
|
onPress: onSupport,
|
|
1748
2125
|
activeOpacity: 0.7,
|
|
1749
2126
|
children: [
|
|
1750
|
-
/* @__PURE__ */ (0,
|
|
1751
|
-
/* @__PURE__ */ (0,
|
|
2127
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native5.Text, { style: [styles3.actionLabel, { color: t.text }], children: "Help & Support" }),
|
|
2128
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native5.Text, { style: [styles3.chevron, { color: t.textMuted }], children: "\u203A" })
|
|
1752
2129
|
]
|
|
1753
2130
|
}
|
|
1754
2131
|
)
|
|
1755
2132
|
] }) : null
|
|
1756
2133
|
] }),
|
|
1757
|
-
/* @__PURE__ */ (0,
|
|
2134
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1758
2135
|
import_react_native5.TouchableOpacity,
|
|
1759
2136
|
{
|
|
1760
2137
|
style: [styles3.logoutButton, { borderColor: t.live }],
|
|
1761
2138
|
onPress: onLogout,
|
|
1762
2139
|
disabled: loggingOut,
|
|
1763
2140
|
activeOpacity: 0.7,
|
|
1764
|
-
children: loggingOut ? /* @__PURE__ */ (0,
|
|
2141
|
+
children: loggingOut ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native5.ActivityIndicator, { color: t.live, size: "small" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native5.Text, { style: [styles3.logoutText, { color: t.live }], children: "Log Out" })
|
|
1765
2142
|
}
|
|
1766
2143
|
),
|
|
1767
|
-
appVersion ? /* @__PURE__ */ (0,
|
|
2144
|
+
appVersion ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native5.Text, { style: [styles3.version, { color: t.textDim }], children: [
|
|
1768
2145
|
"v",
|
|
1769
2146
|
appVersion
|
|
1770
2147
|
] }) : null
|
|
@@ -1833,6 +2210,476 @@ var styles3 = import_react_native5.StyleSheet.create({
|
|
|
1833
2210
|
textAlign: "center"
|
|
1834
2211
|
}
|
|
1835
2212
|
});
|
|
2213
|
+
|
|
2214
|
+
// src/ui/game/GamePoster.tsx
|
|
2215
|
+
var import_react14 = require("react");
|
|
2216
|
+
var import_react_native6 = require("react-native");
|
|
2217
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
2218
|
+
function computeCountdown(lockTimestamp) {
|
|
2219
|
+
if (!lockTimestamp) return "";
|
|
2220
|
+
const ts = typeof lockTimestamp === "string" ? parseInt(lockTimestamp) : lockTimestamp;
|
|
2221
|
+
const diff = ts * 1e3 - Date.now();
|
|
2222
|
+
if (diff <= 0) return "LIVE";
|
|
2223
|
+
const days = Math.floor(diff / 864e5);
|
|
2224
|
+
const hours = Math.floor(diff % 864e5 / 36e5);
|
|
2225
|
+
const mins = Math.floor(diff % 36e5 / 6e4);
|
|
2226
|
+
if (days > 0) return `${days}d ${hours}h`;
|
|
2227
|
+
if (hours > 0) return `${hours}h ${mins}m`;
|
|
2228
|
+
return `${mins}m`;
|
|
2229
|
+
}
|
|
2230
|
+
function GamePoster({ game, ImageComponent }) {
|
|
2231
|
+
const t = useDubsTheme();
|
|
2232
|
+
const Img = ImageComponent || require("react-native").Image;
|
|
2233
|
+
const opponents = game.opponents || [];
|
|
2234
|
+
const home = opponents[0];
|
|
2235
|
+
const away = opponents[1];
|
|
2236
|
+
const countdown = computeCountdown(game.lockTimestamp);
|
|
2237
|
+
const isLive = countdown === "LIVE";
|
|
2238
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native6.View, { style: styles4.container, children: [
|
|
2239
|
+
game.media?.poster ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2240
|
+
Img,
|
|
2241
|
+
{
|
|
2242
|
+
source: { uri: game.media.poster },
|
|
2243
|
+
style: styles4.image,
|
|
2244
|
+
resizeMode: "cover"
|
|
2245
|
+
}
|
|
2246
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native6.View, { style: [styles4.image, { backgroundColor: t.surface }], children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native6.View, { style: styles4.fallback, children: [
|
|
2247
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TeamLogoInternal, { url: home?.imageUrl, size: 56, Img }),
|
|
2248
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native6.Text, { style: styles4.vs, children: "VS" }),
|
|
2249
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TeamLogoInternal, { url: away?.imageUrl, size: 56, Img })
|
|
2250
|
+
] }) }),
|
|
2251
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native6.View, { style: styles4.overlay }),
|
|
2252
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native6.View, { style: styles4.teamNames, children: [
|
|
2253
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native6.Text, { style: styles4.teamNameText, numberOfLines: 1, children: home?.name || "Home" }),
|
|
2254
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native6.Text, { style: styles4.teamNameVs, children: "vs" }),
|
|
2255
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native6.Text, { style: styles4.teamNameText, numberOfLines: 1, children: away?.name || "Away" })
|
|
2256
|
+
] }),
|
|
2257
|
+
countdown ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native6.View, { style: styles4.countdownPill, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native6.Text, { style: [styles4.countdownText, isLive && styles4.countdownLive], children: countdown }) }) : null,
|
|
2258
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native6.View, { style: styles4.poolPill, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native6.Text, { style: styles4.poolText, children: [
|
|
2259
|
+
game.totalPool || 0,
|
|
2260
|
+
" SOL"
|
|
2261
|
+
] }) })
|
|
2262
|
+
] });
|
|
2263
|
+
}
|
|
2264
|
+
function TeamLogoInternal({ url, size, Img }) {
|
|
2265
|
+
const [failed, setFailed] = (0, import_react14.useState)(false);
|
|
2266
|
+
if (!url || failed) {
|
|
2267
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native6.View, { style: [styles4.logoPlaceholder, { width: size, height: size, borderRadius: size / 2 }] });
|
|
2268
|
+
}
|
|
2269
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2270
|
+
Img,
|
|
2271
|
+
{
|
|
2272
|
+
source: { uri: url },
|
|
2273
|
+
style: { width: size, height: size, borderRadius: size / 2 },
|
|
2274
|
+
resizeMode: "contain",
|
|
2275
|
+
onError: () => setFailed(true)
|
|
2276
|
+
}
|
|
2277
|
+
);
|
|
2278
|
+
}
|
|
2279
|
+
var styles4 = import_react_native6.StyleSheet.create({
|
|
2280
|
+
container: {
|
|
2281
|
+
height: 200,
|
|
2282
|
+
borderRadius: 16,
|
|
2283
|
+
overflow: "hidden",
|
|
2284
|
+
position: "relative"
|
|
2285
|
+
},
|
|
2286
|
+
image: {
|
|
2287
|
+
...import_react_native6.StyleSheet.absoluteFillObject,
|
|
2288
|
+
justifyContent: "center",
|
|
2289
|
+
alignItems: "center"
|
|
2290
|
+
},
|
|
2291
|
+
overlay: {
|
|
2292
|
+
...import_react_native6.StyleSheet.absoluteFillObject,
|
|
2293
|
+
backgroundColor: "rgba(0,0,0,0.35)"
|
|
2294
|
+
},
|
|
2295
|
+
fallback: {
|
|
2296
|
+
flexDirection: "row",
|
|
2297
|
+
alignItems: "center",
|
|
2298
|
+
gap: 24,
|
|
2299
|
+
zIndex: 2
|
|
2300
|
+
},
|
|
2301
|
+
vs: {
|
|
2302
|
+
color: "#FFF",
|
|
2303
|
+
fontSize: 24,
|
|
2304
|
+
fontWeight: "900",
|
|
2305
|
+
zIndex: 2
|
|
2306
|
+
},
|
|
2307
|
+
logoPlaceholder: {
|
|
2308
|
+
backgroundColor: "rgba(255,255,255,0.15)",
|
|
2309
|
+
zIndex: 2
|
|
2310
|
+
},
|
|
2311
|
+
teamNames: {
|
|
2312
|
+
position: "absolute",
|
|
2313
|
+
top: 12,
|
|
2314
|
+
left: 12,
|
|
2315
|
+
right: 12,
|
|
2316
|
+
flexDirection: "row",
|
|
2317
|
+
alignItems: "center",
|
|
2318
|
+
justifyContent: "center",
|
|
2319
|
+
gap: 8
|
|
2320
|
+
},
|
|
2321
|
+
teamNameText: {
|
|
2322
|
+
color: "#FFF",
|
|
2323
|
+
fontSize: 14,
|
|
2324
|
+
fontWeight: "700",
|
|
2325
|
+
maxWidth: "40%"
|
|
2326
|
+
},
|
|
2327
|
+
teamNameVs: {
|
|
2328
|
+
color: "rgba(255,255,255,0.6)",
|
|
2329
|
+
fontSize: 12,
|
|
2330
|
+
fontWeight: "600"
|
|
2331
|
+
},
|
|
2332
|
+
countdownPill: {
|
|
2333
|
+
position: "absolute",
|
|
2334
|
+
bottom: 12,
|
|
2335
|
+
left: 12,
|
|
2336
|
+
backgroundColor: "rgba(0,0,0,0.65)",
|
|
2337
|
+
borderRadius: 8,
|
|
2338
|
+
paddingHorizontal: 10,
|
|
2339
|
+
paddingVertical: 5
|
|
2340
|
+
},
|
|
2341
|
+
countdownText: {
|
|
2342
|
+
color: "#FFF",
|
|
2343
|
+
fontSize: 13,
|
|
2344
|
+
fontWeight: "700"
|
|
2345
|
+
},
|
|
2346
|
+
countdownLive: {
|
|
2347
|
+
color: "#EF4444"
|
|
2348
|
+
},
|
|
2349
|
+
poolPill: {
|
|
2350
|
+
position: "absolute",
|
|
2351
|
+
bottom: 12,
|
|
2352
|
+
right: 12,
|
|
2353
|
+
backgroundColor: "#7C3AED",
|
|
2354
|
+
borderRadius: 8,
|
|
2355
|
+
paddingHorizontal: 12,
|
|
2356
|
+
paddingVertical: 5
|
|
2357
|
+
},
|
|
2358
|
+
poolText: {
|
|
2359
|
+
color: "#FFF",
|
|
2360
|
+
fontSize: 13,
|
|
2361
|
+
fontWeight: "800"
|
|
2362
|
+
}
|
|
2363
|
+
});
|
|
2364
|
+
|
|
2365
|
+
// src/ui/game/LivePoolsCard.tsx
|
|
2366
|
+
var import_react15 = require("react");
|
|
2367
|
+
var import_react_native7 = require("react-native");
|
|
2368
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
2369
|
+
function LivePoolsCard({
|
|
2370
|
+
game,
|
|
2371
|
+
shortName,
|
|
2372
|
+
homeColor = "#3B82F6",
|
|
2373
|
+
awayColor = "#EF4444"
|
|
2374
|
+
}) {
|
|
2375
|
+
const t = useDubsTheme();
|
|
2376
|
+
const opponents = game.opponents || [];
|
|
2377
|
+
const homeName = shortName ? shortName(opponents[0]?.name) : opponents[0]?.name || "Home";
|
|
2378
|
+
const awayName = shortName ? shortName(opponents[1]?.name) : opponents[1]?.name || "Away";
|
|
2379
|
+
const homePool = game.homePool || 0;
|
|
2380
|
+
const awayPool = game.awayPool || 0;
|
|
2381
|
+
const totalPool = game.totalPool || 0;
|
|
2382
|
+
const { homePercent, awayPercent, homeOdds, awayOdds } = (0, import_react15.useMemo)(() => {
|
|
2383
|
+
return {
|
|
2384
|
+
homePercent: totalPool > 0 ? homePool / totalPool * 100 : 50,
|
|
2385
|
+
awayPercent: totalPool > 0 ? awayPool / totalPool * 100 : 50,
|
|
2386
|
+
homeOdds: homePool > 0 ? (totalPool / homePool).toFixed(2) : "\u2014",
|
|
2387
|
+
awayOdds: awayPool > 0 ? (totalPool / awayPool).toFixed(2) : "\u2014"
|
|
2388
|
+
};
|
|
2389
|
+
}, [homePool, awayPool, totalPool]);
|
|
2390
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native7.View, { style: [styles5.card, { backgroundColor: t.surface, borderColor: t.border }], children: [
|
|
2391
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native7.Text, { style: [styles5.title, { color: t.text }], children: "Live Pools" }),
|
|
2392
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native7.Text, { style: [styles5.total, { color: t.accent }], children: [
|
|
2393
|
+
totalPool,
|
|
2394
|
+
" SOL total"
|
|
2395
|
+
] }),
|
|
2396
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native7.View, { style: styles5.bars, children: [
|
|
2397
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PoolBar, { name: homeName, amount: homePool, percent: homePercent, color: homeColor, t }),
|
|
2398
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PoolBar, { name: awayName, amount: awayPool, percent: awayPercent, color: awayColor, t })
|
|
2399
|
+
] }),
|
|
2400
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native7.View, { style: styles5.oddsRow, children: [
|
|
2401
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native7.Text, { style: [styles5.oddsText, { color: t.textMuted }], children: [
|
|
2402
|
+
homeName,
|
|
2403
|
+
": ",
|
|
2404
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native7.Text, { style: { color: t.text, fontWeight: "700" }, children: [
|
|
2405
|
+
homeOdds,
|
|
2406
|
+
"x"
|
|
2407
|
+
] })
|
|
2408
|
+
] }),
|
|
2409
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native7.Text, { style: [styles5.oddsText, { color: t.textMuted }], children: [
|
|
2410
|
+
awayName,
|
|
2411
|
+
": ",
|
|
2412
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native7.Text, { style: { color: t.text, fontWeight: "700" }, children: [
|
|
2413
|
+
awayOdds,
|
|
2414
|
+
"x"
|
|
2415
|
+
] })
|
|
2416
|
+
] })
|
|
2417
|
+
] })
|
|
2418
|
+
] });
|
|
2419
|
+
}
|
|
2420
|
+
function PoolBar({ name, amount, percent, color, t }) {
|
|
2421
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native7.View, { style: styles5.barRow, children: [
|
|
2422
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native7.Text, { style: [styles5.barLabel, { color: t.textSecondary }], numberOfLines: 1, children: name }),
|
|
2423
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native7.View, { style: [styles5.barTrack, { backgroundColor: t.border }], children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native7.View, { style: [styles5.barFill, { width: `${Math.max(percent, 2)}%`, backgroundColor: color }] }) }),
|
|
2424
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native7.Text, { style: [styles5.barAmount, { color: t.text }], children: [
|
|
2425
|
+
amount,
|
|
2426
|
+
" SOL"
|
|
2427
|
+
] })
|
|
2428
|
+
] });
|
|
2429
|
+
}
|
|
2430
|
+
var styles5 = import_react_native7.StyleSheet.create({
|
|
2431
|
+
card: { borderRadius: 16, borderWidth: 1, padding: 16 },
|
|
2432
|
+
title: { fontSize: 17, fontWeight: "700", marginBottom: 4 },
|
|
2433
|
+
total: { fontSize: 14, fontWeight: "600", marginBottom: 14 },
|
|
2434
|
+
bars: { gap: 10 },
|
|
2435
|
+
barRow: { flexDirection: "row", alignItems: "center", gap: 10 },
|
|
2436
|
+
barLabel: { width: 80, fontSize: 13, fontWeight: "600" },
|
|
2437
|
+
barTrack: { flex: 1, height: 10, borderRadius: 5, overflow: "hidden" },
|
|
2438
|
+
barFill: { height: "100%", borderRadius: 5 },
|
|
2439
|
+
barAmount: { width: 70, textAlign: "right", fontSize: 13, fontWeight: "700" },
|
|
2440
|
+
oddsRow: { flexDirection: "row", justifyContent: "space-between", marginTop: 12 },
|
|
2441
|
+
oddsText: { fontSize: 12 }
|
|
2442
|
+
});
|
|
2443
|
+
|
|
2444
|
+
// src/ui/game/PickWinnerCard.tsx
|
|
2445
|
+
var import_react16 = require("react");
|
|
2446
|
+
var import_react_native8 = require("react-native");
|
|
2447
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
2448
|
+
function PickWinnerCard({
|
|
2449
|
+
game,
|
|
2450
|
+
selectedTeam,
|
|
2451
|
+
onSelect,
|
|
2452
|
+
shortName,
|
|
2453
|
+
homeColor = "#3B82F6",
|
|
2454
|
+
awayColor = "#EF4444",
|
|
2455
|
+
ImageComponent
|
|
2456
|
+
}) {
|
|
2457
|
+
const t = useDubsTheme();
|
|
2458
|
+
const opponents = game.opponents || [];
|
|
2459
|
+
const bettors = game.bettors || [];
|
|
2460
|
+
const totalPool = game.totalPool || 0;
|
|
2461
|
+
const homePool = game.homePool || 0;
|
|
2462
|
+
const awayPool = game.awayPool || 0;
|
|
2463
|
+
const { homeOdds, awayOdds, homeBets, awayBets } = (0, import_react16.useMemo)(() => ({
|
|
2464
|
+
homeOdds: homePool > 0 ? (totalPool / homePool).toFixed(2) : "\u2014",
|
|
2465
|
+
awayOdds: awayPool > 0 ? (totalPool / awayPool).toFixed(2) : "\u2014",
|
|
2466
|
+
homeBets: bettors.filter((b) => b.team === "home").length,
|
|
2467
|
+
awayBets: bettors.filter((b) => b.team === "away").length
|
|
2468
|
+
}), [totalPool, homePool, awayPool, bettors]);
|
|
2469
|
+
const homeName = shortName ? shortName(opponents[0]?.name) : opponents[0]?.name || "Home";
|
|
2470
|
+
const awayName = shortName ? shortName(opponents[1]?.name) : opponents[1]?.name || "Away";
|
|
2471
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native8.View, { style: [styles6.card, { backgroundColor: t.surface, borderColor: t.border }], children: [
|
|
2472
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native8.Text, { style: [styles6.title, { color: t.text }], children: "Pick Your Winner" }),
|
|
2473
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native8.View, { style: styles6.row, children: [
|
|
2474
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2475
|
+
TeamOption,
|
|
2476
|
+
{
|
|
2477
|
+
name: homeName,
|
|
2478
|
+
imageUrl: opponents[0]?.imageUrl,
|
|
2479
|
+
odds: homeOdds,
|
|
2480
|
+
bets: homeBets,
|
|
2481
|
+
color: homeColor,
|
|
2482
|
+
selected: selectedTeam === "home",
|
|
2483
|
+
onPress: () => onSelect("home"),
|
|
2484
|
+
ImageComponent,
|
|
2485
|
+
t
|
|
2486
|
+
}
|
|
2487
|
+
),
|
|
2488
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2489
|
+
TeamOption,
|
|
2490
|
+
{
|
|
2491
|
+
name: awayName,
|
|
2492
|
+
imageUrl: opponents[1]?.imageUrl,
|
|
2493
|
+
odds: awayOdds,
|
|
2494
|
+
bets: awayBets,
|
|
2495
|
+
color: awayColor,
|
|
2496
|
+
selected: selectedTeam === "away",
|
|
2497
|
+
onPress: () => onSelect("away"),
|
|
2498
|
+
ImageComponent,
|
|
2499
|
+
t
|
|
2500
|
+
}
|
|
2501
|
+
)
|
|
2502
|
+
] })
|
|
2503
|
+
] });
|
|
2504
|
+
}
|
|
2505
|
+
function TeamOption({
|
|
2506
|
+
name,
|
|
2507
|
+
imageUrl,
|
|
2508
|
+
odds,
|
|
2509
|
+
bets,
|
|
2510
|
+
color,
|
|
2511
|
+
selected,
|
|
2512
|
+
onPress,
|
|
2513
|
+
ImageComponent,
|
|
2514
|
+
t
|
|
2515
|
+
}) {
|
|
2516
|
+
const [imgFailed, setImgFailed] = (0, import_react16.useState)(false);
|
|
2517
|
+
const Img = ImageComponent || require("react-native").Image;
|
|
2518
|
+
const showImage = imageUrl && !imgFailed;
|
|
2519
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
2520
|
+
import_react_native8.TouchableOpacity,
|
|
2521
|
+
{
|
|
2522
|
+
style: [styles6.option, { borderColor: selected ? color : t.border, backgroundColor: selected ? color + "15" : t.background }],
|
|
2523
|
+
onPress,
|
|
2524
|
+
activeOpacity: 0.7,
|
|
2525
|
+
children: [
|
|
2526
|
+
showImage ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Img, { source: { uri: imageUrl }, style: styles6.logo, resizeMode: "contain", onError: () => setImgFailed(true) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native8.View, { style: [styles6.logo, styles6.logoPlaceholder] }),
|
|
2527
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native8.Text, { style: [styles6.name, { color: t.text }], numberOfLines: 1, children: name }),
|
|
2528
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native8.Text, { style: [styles6.odds, { color }], children: [
|
|
2529
|
+
odds,
|
|
2530
|
+
"x"
|
|
2531
|
+
] }),
|
|
2532
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native8.Text, { style: [styles6.bets, { color: t.textMuted }], children: [
|
|
2533
|
+
bets,
|
|
2534
|
+
" ",
|
|
2535
|
+
bets === 1 ? "bet" : "bets"
|
|
2536
|
+
] }),
|
|
2537
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native8.View, { style: [styles6.badge, { backgroundColor: color }], children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native8.Text, { style: styles6.badgeText, children: "Selected" }) })
|
|
2538
|
+
]
|
|
2539
|
+
}
|
|
2540
|
+
);
|
|
2541
|
+
}
|
|
2542
|
+
var styles6 = import_react_native8.StyleSheet.create({
|
|
2543
|
+
card: { borderRadius: 16, borderWidth: 1, padding: 16 },
|
|
2544
|
+
title: { fontSize: 17, fontWeight: "700", marginBottom: 12 },
|
|
2545
|
+
row: { flexDirection: "row", gap: 12 },
|
|
2546
|
+
option: { flex: 1, borderWidth: 2, borderRadius: 16, padding: 16, alignItems: "center", gap: 8 },
|
|
2547
|
+
logo: { width: 48, height: 48, borderRadius: 24 },
|
|
2548
|
+
logoPlaceholder: { backgroundColor: "rgba(128,128,128,0.2)" },
|
|
2549
|
+
name: { fontSize: 15, fontWeight: "700" },
|
|
2550
|
+
odds: { fontSize: 20, fontWeight: "800" },
|
|
2551
|
+
bets: { fontSize: 12 },
|
|
2552
|
+
badge: { borderRadius: 8, paddingHorizontal: 12, paddingVertical: 4, marginTop: 4 },
|
|
2553
|
+
badgeText: { color: "#FFF", fontSize: 12, fontWeight: "700" }
|
|
2554
|
+
});
|
|
2555
|
+
|
|
2556
|
+
// src/ui/game/PlayersCard.tsx
|
|
2557
|
+
var import_react17 = require("react");
|
|
2558
|
+
var import_react_native9 = require("react-native");
|
|
2559
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
2560
|
+
function truncateWallet(addr, chars) {
|
|
2561
|
+
if (addr.length <= chars * 2 + 3) return addr;
|
|
2562
|
+
return `${addr.slice(0, chars)}...${addr.slice(-chars)}`;
|
|
2563
|
+
}
|
|
2564
|
+
function PlayersCard({
|
|
2565
|
+
game,
|
|
2566
|
+
truncateChars = 4,
|
|
2567
|
+
homeColor = "#3B82F6",
|
|
2568
|
+
awayColor = "#EF4444",
|
|
2569
|
+
drawColor = "#A855F7",
|
|
2570
|
+
ImageComponent
|
|
2571
|
+
}) {
|
|
2572
|
+
const t = useDubsTheme();
|
|
2573
|
+
const bettors = game.bettors || [];
|
|
2574
|
+
const dotColor = (team) => {
|
|
2575
|
+
if (team === "home") return homeColor;
|
|
2576
|
+
if (team === "away") return awayColor;
|
|
2577
|
+
return drawColor;
|
|
2578
|
+
};
|
|
2579
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native9.View, { style: [styles7.card, { backgroundColor: t.surface, borderColor: t.border }], children: [
|
|
2580
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native9.Text, { style: [styles7.title, { color: t.text }], children: [
|
|
2581
|
+
"Players",
|
|
2582
|
+
bettors.length > 0 ? ` (${bettors.length})` : ""
|
|
2583
|
+
] }),
|
|
2584
|
+
bettors.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native9.Text, { style: [styles7.empty, { color: t.textMuted }], children: "No players yet \u2014 be the first!" }) : bettors.map((b, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2585
|
+
BettorRow,
|
|
2586
|
+
{
|
|
2587
|
+
bettor: b,
|
|
2588
|
+
dotColor: dotColor(b.team),
|
|
2589
|
+
truncateChars,
|
|
2590
|
+
isFirst: i === 0,
|
|
2591
|
+
ImageComponent,
|
|
2592
|
+
t
|
|
2593
|
+
},
|
|
2594
|
+
`${b.wallet}-${i}`
|
|
2595
|
+
))
|
|
2596
|
+
] });
|
|
2597
|
+
}
|
|
2598
|
+
function BettorRow({
|
|
2599
|
+
bettor,
|
|
2600
|
+
dotColor,
|
|
2601
|
+
truncateChars,
|
|
2602
|
+
isFirst,
|
|
2603
|
+
ImageComponent,
|
|
2604
|
+
t
|
|
2605
|
+
}) {
|
|
2606
|
+
const [imgFailed, setImgFailed] = (0, import_react17.useState)(false);
|
|
2607
|
+
const Img = ImageComponent || require("react-native").Image;
|
|
2608
|
+
const showAvatar = bettor.avatar && !imgFailed;
|
|
2609
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native9.View, { style: [styles7.row, !isFirst && { borderTopColor: t.border, borderTopWidth: 1 }], children: [
|
|
2610
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native9.View, { style: [styles7.dot, { backgroundColor: dotColor }] }),
|
|
2611
|
+
showAvatar ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Img, { source: { uri: bettor.avatar }, style: styles7.avatar, resizeMode: "cover", onError: () => setImgFailed(true) }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native9.View, { style: [styles7.avatar, styles7.avatarPlaceholder] }),
|
|
2612
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native9.View, { style: styles7.nameCol, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native9.Text, { style: [styles7.username, { color: t.text }], numberOfLines: 1, children: bettor.username || truncateWallet(bettor.wallet, truncateChars) }) }),
|
|
2613
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native9.Text, { style: [styles7.amount, { color: t.textSecondary }], children: [
|
|
2614
|
+
bettor.amount,
|
|
2615
|
+
" SOL"
|
|
2616
|
+
] })
|
|
2617
|
+
] });
|
|
2618
|
+
}
|
|
2619
|
+
var styles7 = import_react_native9.StyleSheet.create({
|
|
2620
|
+
card: { borderRadius: 16, borderWidth: 1, padding: 16 },
|
|
2621
|
+
title: { fontSize: 17, fontWeight: "700", marginBottom: 12 },
|
|
2622
|
+
empty: { fontSize: 14, textAlign: "center", paddingVertical: 16 },
|
|
2623
|
+
row: { flexDirection: "row", alignItems: "center", paddingVertical: 10, gap: 10 },
|
|
2624
|
+
dot: { width: 8, height: 8, borderRadius: 4 },
|
|
2625
|
+
avatar: { width: 28, height: 28, borderRadius: 14 },
|
|
2626
|
+
avatarPlaceholder: { backgroundColor: "rgba(128,128,128,0.2)" },
|
|
2627
|
+
nameCol: { flex: 1 },
|
|
2628
|
+
username: { fontSize: 14, fontWeight: "600" },
|
|
2629
|
+
amount: { fontSize: 13, fontWeight: "700" }
|
|
2630
|
+
});
|
|
2631
|
+
|
|
2632
|
+
// src/ui/game/JoinGameButton.tsx
|
|
2633
|
+
var import_react18 = require("react");
|
|
2634
|
+
var import_react_native10 = require("react-native");
|
|
2635
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2636
|
+
var STATUS_LABELS = {
|
|
2637
|
+
building: "Building transaction...",
|
|
2638
|
+
signing: "Approve in wallet...",
|
|
2639
|
+
confirming: "Confirming on-chain...",
|
|
2640
|
+
saving: "Saving..."
|
|
2641
|
+
};
|
|
2642
|
+
function JoinGameButton({ game, walletAddress, selectedTeam, status, onJoin }) {
|
|
2643
|
+
const t = useDubsTheme();
|
|
2644
|
+
const alreadyJoined = (0, import_react18.useMemo)(() => {
|
|
2645
|
+
if (!walletAddress) return false;
|
|
2646
|
+
return (game.bettors || []).some((b) => b.wallet === walletAddress);
|
|
2647
|
+
}, [game.bettors, walletAddress]);
|
|
2648
|
+
if (alreadyJoined || game.isLocked || game.isResolved) return null;
|
|
2649
|
+
const isJoining = status !== "idle" && status !== "success" && status !== "error";
|
|
2650
|
+
const statusLabel = STATUS_LABELS[status] || "";
|
|
2651
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native10.View, { style: [styles8.bar, { backgroundColor: t.background, borderTopColor: t.border }], children: [
|
|
2652
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native10.View, { style: styles8.buyInRow, children: [
|
|
2653
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native10.Text, { style: [styles8.buyInLabel, { color: t.textMuted }], children: "Buy-in" }),
|
|
2654
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native10.Text, { style: [styles8.buyInValue, { color: t.text }], children: [
|
|
2655
|
+
game.buyIn,
|
|
2656
|
+
" SOL"
|
|
2657
|
+
] })
|
|
2658
|
+
] }),
|
|
2659
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2660
|
+
import_react_native10.TouchableOpacity,
|
|
2661
|
+
{
|
|
2662
|
+
style: [styles8.button, { backgroundColor: selectedTeam ? "#22D3EE" : t.border }],
|
|
2663
|
+
disabled: !selectedTeam || isJoining,
|
|
2664
|
+
onPress: onJoin,
|
|
2665
|
+
activeOpacity: 0.8,
|
|
2666
|
+
children: isJoining ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native10.View, { style: styles8.joiningRow, children: [
|
|
2667
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native10.ActivityIndicator, { size: "small", color: "#000" }),
|
|
2668
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native10.Text, { style: styles8.buttonText, children: statusLabel })
|
|
2669
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native10.Text, { style: [styles8.buttonText, !selectedTeam && { color: t.textMuted }], children: selectedTeam ? `Join Bet \u2014 ${game.buyIn} SOL` : "Pick a team to bet" })
|
|
2670
|
+
}
|
|
2671
|
+
)
|
|
2672
|
+
] });
|
|
2673
|
+
}
|
|
2674
|
+
var styles8 = import_react_native10.StyleSheet.create({
|
|
2675
|
+
bar: { position: "absolute", bottom: 0, left: 0, right: 0, paddingHorizontal: 16, paddingTop: 12, paddingBottom: 36, borderTopWidth: 1 },
|
|
2676
|
+
buyInRow: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", marginBottom: 10 },
|
|
2677
|
+
buyInLabel: { fontSize: 13 },
|
|
2678
|
+
buyInValue: { fontSize: 15, fontWeight: "800" },
|
|
2679
|
+
button: { borderRadius: 14, paddingVertical: 16, alignItems: "center" },
|
|
2680
|
+
buttonText: { color: "#000", fontSize: 16, fontWeight: "800" },
|
|
2681
|
+
joiningRow: { flexDirection: "row", alignItems: "center", gap: 10 }
|
|
2682
|
+
});
|
|
1836
2683
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1837
2684
|
0 && (module.exports = {
|
|
1838
2685
|
AuthGate,
|
|
@@ -1842,12 +2689,20 @@ var styles3 = import_react_native5.StyleSheet.create({
|
|
|
1842
2689
|
DubsApiError,
|
|
1843
2690
|
DubsClient,
|
|
1844
2691
|
DubsProvider,
|
|
2692
|
+
GamePoster,
|
|
2693
|
+
JoinGameButton,
|
|
2694
|
+
LivePoolsCard,
|
|
1845
2695
|
MwaWalletAdapter,
|
|
2696
|
+
NETWORK_CONFIG,
|
|
2697
|
+
PickWinnerCard,
|
|
2698
|
+
PlayersCard,
|
|
1846
2699
|
SOLANA_PROGRAM_ERRORS,
|
|
2700
|
+
STORAGE_KEYS,
|
|
1847
2701
|
SettingsSheet,
|
|
1848
2702
|
UserProfileCard,
|
|
2703
|
+
createSecureStoreStorage,
|
|
2704
|
+
mergeTheme,
|
|
1849
2705
|
parseSolanaError,
|
|
1850
|
-
pollTransactionConfirmation,
|
|
1851
2706
|
signAndSendBase64Transaction,
|
|
1852
2707
|
useAuth,
|
|
1853
2708
|
useClaim,
|