@dubsdotapp/expo 0.5.14 → 0.5.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +299 -211
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +246 -160
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/hooks/index.ts +4 -0
- package/src/hooks/useHighlights.ts +38 -0
- package/src/hooks/useShorts.ts +36 -0
- package/src/index.ts +4 -0
- package/src/ui/game/JoinGameSheet.tsx +43 -11
- package/dist/index.d.mts +0 -1500
- package/dist/index.d.ts +0 -1500
package/package.json
CHANGED
package/src/hooks/index.ts
CHANGED
|
@@ -16,6 +16,10 @@ export { useAuth } from './useAuth';
|
|
|
16
16
|
export type { UseAuthResult } from './useAuth';
|
|
17
17
|
export { useUFCFightCard } from './useUFCFightCard';
|
|
18
18
|
export { useUFCFighterDetail } from './useUFCFighterDetail';
|
|
19
|
+
export { useHighlights } from './useHighlights';
|
|
20
|
+
export type { HighlightVideo } from './useHighlights';
|
|
21
|
+
export { useShorts } from './useShorts';
|
|
22
|
+
export type { ShortVideo } from './useShorts';
|
|
19
23
|
export { usePushNotifications } from './usePushNotifications';
|
|
20
24
|
export type { PushNotificationStatus } from './usePushNotifications';
|
|
21
25
|
export { useArcadePools } from './useArcadePools';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import { useDubs } from '../provider';
|
|
3
|
+
import type { QueryResult } from '../types';
|
|
4
|
+
|
|
5
|
+
export interface HighlightVideo {
|
|
6
|
+
videoId: string;
|
|
7
|
+
title: string;
|
|
8
|
+
channelTitle: string;
|
|
9
|
+
thumbnail: string;
|
|
10
|
+
publishedAt: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function useHighlights(league?: string, limit: number = 8): QueryResult<HighlightVideo[]> {
|
|
14
|
+
const { client } = useDubs();
|
|
15
|
+
const [data, setData] = useState<HighlightVideo[] | null>(null);
|
|
16
|
+
const [loading, setLoading] = useState(true);
|
|
17
|
+
const [error, setError] = useState<Error | null>(null);
|
|
18
|
+
|
|
19
|
+
const fetchData = useCallback(async () => {
|
|
20
|
+
setLoading(true);
|
|
21
|
+
setError(null);
|
|
22
|
+
try {
|
|
23
|
+
const qs = new URLSearchParams();
|
|
24
|
+
if (league) qs.set('league', league);
|
|
25
|
+
qs.set('limit', String(limit));
|
|
26
|
+
const res = await (client as any).request('GET', `/highlights?${qs.toString()}`);
|
|
27
|
+
setData(res.videos || []);
|
|
28
|
+
} catch (err) {
|
|
29
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
30
|
+
} finally {
|
|
31
|
+
setLoading(false);
|
|
32
|
+
}
|
|
33
|
+
}, [client, league, limit]);
|
|
34
|
+
|
|
35
|
+
useEffect(() => { fetchData(); }, [fetchData]);
|
|
36
|
+
|
|
37
|
+
return { data, loading, error, refetch: fetchData };
|
|
38
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import { useDubs } from '../provider';
|
|
3
|
+
import type { QueryResult } from '../types';
|
|
4
|
+
|
|
5
|
+
export interface ShortVideo {
|
|
6
|
+
videoId: string;
|
|
7
|
+
title: string;
|
|
8
|
+
channelTitle: string;
|
|
9
|
+
thumbnail: string;
|
|
10
|
+
publishedAt: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function useShorts(league: string = 'NBA', limit: number = 20): QueryResult<ShortVideo[]> {
|
|
14
|
+
const { client } = useDubs();
|
|
15
|
+
const [data, setData] = useState<ShortVideo[] | null>(null);
|
|
16
|
+
const [loading, setLoading] = useState(true);
|
|
17
|
+
const [error, setError] = useState<Error | null>(null);
|
|
18
|
+
|
|
19
|
+
const fetchData = useCallback(async () => {
|
|
20
|
+
setLoading(true);
|
|
21
|
+
setError(null);
|
|
22
|
+
try {
|
|
23
|
+
const qs = new URLSearchParams({ league, limit: String(limit) });
|
|
24
|
+
const res = await (client as any).request('GET', `/shorts?${qs.toString()}`);
|
|
25
|
+
setData(res.videos || []);
|
|
26
|
+
} catch (err) {
|
|
27
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
28
|
+
} finally {
|
|
29
|
+
setLoading(false);
|
|
30
|
+
}
|
|
31
|
+
}, [client, league, limit]);
|
|
32
|
+
|
|
33
|
+
useEffect(() => { fetchData(); }, [fetchData]);
|
|
34
|
+
|
|
35
|
+
return { data, loading, error, refetch: fetchData };
|
|
36
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -127,8 +127,12 @@ export type {
|
|
|
127
127
|
ArcadeCountdown,
|
|
128
128
|
UseArcadeBridgeOptions,
|
|
129
129
|
UseArcadeBridgeResult,
|
|
130
|
+
HighlightVideo,
|
|
131
|
+
ShortVideo,
|
|
130
132
|
} from './hooks';
|
|
131
133
|
|
|
134
|
+
export { useHighlights, useShorts } from './hooks';
|
|
135
|
+
|
|
132
136
|
// UI
|
|
133
137
|
export { AuthGate, ConnectWalletScreen, ConnectWalletButton, UserProfileCard, SettingsSheet, UserProfileSheet, useDubsTheme, mergeTheme } from './ui';
|
|
134
138
|
export type { AuthGateProps, RegistrationScreenProps, ConnectWalletScreenProps, ConnectWalletButtonProps, AuthGateConnectWalletProps, UserProfileCardProps, SettingsSheetProps, UserProfileSheetProps, DubsTheme } from './ui';
|
|
@@ -27,9 +27,10 @@ export interface JoinGameSheetProps {
|
|
|
27
27
|
ImageComponent?: React.ComponentType<any>;
|
|
28
28
|
/** Custom short-name function for team labels */
|
|
29
29
|
shortName?: (name: string | null) => string;
|
|
30
|
-
/** Override team colors (default blue/red) */
|
|
30
|
+
/** Override team colors (default blue/red/green) */
|
|
31
31
|
homeColor?: string;
|
|
32
32
|
awayColor?: string;
|
|
33
|
+
drawColor?: string;
|
|
33
34
|
/** Callbacks */
|
|
34
35
|
onSuccess?: (result: JoinGameMutationResult) => void;
|
|
35
36
|
onError?: (error: Error) => void;
|
|
@@ -72,6 +73,7 @@ export function JoinGameSheet({
|
|
|
72
73
|
shortName,
|
|
73
74
|
homeColor = '#3B82F6',
|
|
74
75
|
awayColor = '#EF4444',
|
|
76
|
+
drawColor = '#F59E0B',
|
|
75
77
|
onSuccess,
|
|
76
78
|
onError,
|
|
77
79
|
onTeamSelect,
|
|
@@ -151,21 +153,35 @@ export function JoinGameSheet({
|
|
|
151
153
|
const totalPool = game.totalPool || 0;
|
|
152
154
|
const homePool = game.homePool || 0;
|
|
153
155
|
const awayPool = game.awayPool || 0;
|
|
156
|
+
const drawPool = game.drawPool || 0;
|
|
154
157
|
const buyIn = game.buyIn;
|
|
155
158
|
|
|
159
|
+
// Show draw option if any bettor is on draw, or if the league supports it
|
|
160
|
+
const drawBettors = bettors.filter(b => b.team === 'draw');
|
|
161
|
+
const hasDrawOption = drawPool > 0 || drawBettors.length > 0 ||
|
|
162
|
+
(game.league && ['English Premier League', 'EPL', 'MLS', 'La Liga', 'Serie A', 'Bundesliga', 'Ligue 1'].some(l => (game.league || '').includes(l)));
|
|
163
|
+
|
|
156
164
|
const poolAfterJoin = totalPool + wager;
|
|
157
165
|
|
|
158
|
-
const { homeOdds, awayOdds, homeBets, awayBets } = useMemo(() => {
|
|
166
|
+
const { homeOdds, awayOdds, drawOdds, homeBets, awayBets, drawBets } = useMemo(() => {
|
|
167
|
+
const homeBetsCount = bettors.filter(b => b.team === 'home').length;
|
|
168
|
+
const awayBetsCount = bettors.filter(b => b.team === 'away').length;
|
|
169
|
+
const drawBetsCount = bettors.filter(b => b.team === 'draw').length;
|
|
159
170
|
const newPool = totalPool + wager;
|
|
171
|
+
const newHome = homePool + (selectedTeam === 'home' ? wager : 0);
|
|
172
|
+
const newAway = awayPool + (selectedTeam === 'away' ? wager : 0);
|
|
173
|
+
const newDraw = drawPool + (selectedTeam === 'draw' ? wager : 0);
|
|
160
174
|
return {
|
|
161
|
-
homeOdds:
|
|
162
|
-
awayOdds:
|
|
163
|
-
|
|
164
|
-
|
|
175
|
+
homeOdds: newHome > 0 ? (newPool / newHome).toFixed(2) : '—',
|
|
176
|
+
awayOdds: newAway > 0 ? (newPool / newAway).toFixed(2) : '—',
|
|
177
|
+
drawOdds: newDraw > 0 ? (newPool / newDraw).toFixed(2) : '—',
|
|
178
|
+
homeBets: homeBetsCount,
|
|
179
|
+
awayBets: awayBetsCount,
|
|
180
|
+
drawBets: drawBetsCount,
|
|
165
181
|
};
|
|
166
|
-
}, [totalPool, homePool, awayPool, bettors, wager, selectedTeam]);
|
|
182
|
+
}, [totalPool, homePool, awayPool, drawPool, bettors, wager, selectedTeam]);
|
|
167
183
|
|
|
168
|
-
const selectedOdds = selectedTeam === 'home' ? homeOdds : selectedTeam === 'away' ? awayOdds : '—';
|
|
184
|
+
const selectedOdds = selectedTeam === 'home' ? homeOdds : selectedTeam === 'away' ? awayOdds : selectedTeam === 'draw' ? drawOdds : '—';
|
|
169
185
|
const potentialWinnings = selectedOdds !== '—' ? formatSol(parseFloat(selectedOdds) * wager) : '—';
|
|
170
186
|
|
|
171
187
|
const homeName = shortName ? shortName(opponents[0]?.name) : (opponents[0]?.name || 'Home');
|
|
@@ -298,15 +314,28 @@ export function JoinGameSheet({
|
|
|
298
314
|
t={t}
|
|
299
315
|
/>
|
|
300
316
|
</View>
|
|
317
|
+
{hasDrawOption && (
|
|
318
|
+
<View style={styles.drawRow}>
|
|
319
|
+
<TeamButton
|
|
320
|
+
name="Draw"
|
|
321
|
+
odds={drawOdds}
|
|
322
|
+
bets={drawBets}
|
|
323
|
+
color={drawColor}
|
|
324
|
+
selected={selectedTeam === 'draw'}
|
|
325
|
+
onPress={() => { setSelectedTeam('draw' as any); onTeamSelect?.('draw' as any); }}
|
|
326
|
+
t={t}
|
|
327
|
+
/>
|
|
328
|
+
</View>
|
|
329
|
+
)}
|
|
301
330
|
</View>
|
|
302
331
|
)}
|
|
303
332
|
|
|
304
333
|
{/* Already joined — show which side */}
|
|
305
334
|
{alreadyJoined && myBet && (
|
|
306
|
-
<View style={[styles.myBetCard, { backgroundColor: (myBet.team === 'home' ? homeColor : awayColor) + '15', borderColor: myBet.team === 'home' ? homeColor : awayColor }]}>
|
|
307
|
-
<Text style={[styles.myBetLabel, { color: myBet.team === 'home' ? homeColor : awayColor }]}>YOUR BET</Text>
|
|
335
|
+
<View style={[styles.myBetCard, { backgroundColor: (myBet.team === 'home' ? homeColor : myBet.team === 'away' ? awayColor : drawColor) + '15', borderColor: myBet.team === 'home' ? homeColor : myBet.team === 'away' ? awayColor : drawColor }]}>
|
|
336
|
+
<Text style={[styles.myBetLabel, { color: myBet.team === 'home' ? homeColor : myBet.team === 'away' ? awayColor : drawColor }]}>YOUR BET</Text>
|
|
308
337
|
<Text style={[styles.myBetTeam, { color: t.text }]}>
|
|
309
|
-
{myBet.team === 'home' ? homeName : awayName}
|
|
338
|
+
{myBet.team === 'home' ? homeName : myBet.team === 'away' ? awayName : 'Draw'}
|
|
310
339
|
</Text>
|
|
311
340
|
<Text style={[styles.myBetAmount, { color: t.textMuted }]}>
|
|
312
341
|
{formatSol(myBet.amount)} SOL
|
|
@@ -536,6 +565,9 @@ const styles = StyleSheet.create({
|
|
|
536
565
|
flexDirection: 'row',
|
|
537
566
|
gap: 12,
|
|
538
567
|
},
|
|
568
|
+
drawRow: {
|
|
569
|
+
marginTop: 8,
|
|
570
|
+
},
|
|
539
571
|
summaryCard: {
|
|
540
572
|
marginTop: 20,
|
|
541
573
|
borderRadius: 16,
|