Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 85 additions & 10 deletions src/apps/golf/components/GolfGame.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,62 @@
flex-shrink: 0;
}

.leaveGameLink {
background: none;
border: none;
color: rgba(255, 255, 255, 0.35);
cursor: pointer;
font-size: 0.9rem;
padding: 0.25rem 0.5rem;
flex-shrink: 0;
line-height: 1;
}

.leaveGameLink:hover {
color: rgba(255, 255, 255, 0.7);
}

.leaveConfirm {
display: flex;
align-items: center;
justify-content: center;
gap: 0.75rem;
margin-top: 0.5rem;
padding: 0.5rem 0.75rem;
background: rgba(255, 80, 80, 0.15);
border-radius: 0.4rem;
font-size: 0.85rem;
color: rgba(255, 255, 255, 0.9);
}

.leaveConfirmYes {
background: rgba(255, 80, 80, 0.6);
border: none;
border-radius: 0.3rem;
color: white;
padding: 0.25rem 0.75rem;
cursor: pointer;
font-size: 0.8rem;
}

.leaveConfirmYes:hover {
background: rgba(255, 80, 80, 0.8);
}

.leaveConfirmNo {
background: rgba(255, 255, 255, 0.15);
border: none;
border-radius: 0.3rem;
color: rgba(255, 255, 255, 0.8);
padding: 0.25rem 0.75rem;
cursor: pointer;
font-size: 0.8rem;
}

.leaveConfirmNo:hover {
background: rgba(255, 255, 255, 0.25);
}

.playerList {
display: flex;
gap: 1rem;
Expand Down Expand Up @@ -641,39 +697,58 @@
}

.gameHeader {
margin-bottom: 0.5rem;
padding: 0.5rem 0.75rem;
margin-bottom: 0.25rem;
padding: 0.35rem 0.5rem;
}

.gameHeader h2 {
font-size: 0.8rem;
font-size: 0.75rem;
margin: 0;
white-space: nowrap;
}

.gameHeaderTop {
flex-direction: row;
gap: 0.5rem;
gap: 0.4rem;
align-items: center;
}

.gameHeaderInfo {
display: flex;
align-items: center;
gap: 0.4rem;
text-align: left;
min-width: 0;
overflow: hidden;
}

.playerList {
flex-wrap: wrap;
gap: 0.2rem;
margin-top: 0.2rem;
flex-wrap: nowrap;
gap: 0.15rem;
margin-top: 0;
overflow: hidden;
}

.playerInfo {
font-size: 0.7rem;
padding: 0.15rem 0.35rem;
font-size: 0.65rem;
padding: 0.1rem 0.3rem;
white-space: nowrap;
}

.turnLabel {
font-size: 0.6rem;
font-size: 0.55rem;
}

.leaveGameLink {
font-size: 0.75rem;
padding: 0.2rem 0.35rem;
}

.leaveConfirm {
margin-top: 0.35rem;
padding: 0.35rem 0.5rem;
font-size: 0.75rem;
gap: 0.5rem;
}

.gameArea {
Expand Down
30 changes: 22 additions & 8 deletions src/apps/golf/components/GolfGame.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useEffect } from 'react'
import { useState, useEffect, useCallback } from 'react'
import styles from './GolfGame.module.css'
import { useGolfGame } from '@/hooks/useGolfGame'
import PermalinkDisplay from './PermalinkDisplay'
Expand Down Expand Up @@ -27,8 +27,7 @@ interface GolfGameProps {
const GolfGame = ({ onGameIdChange, onPlayerIdChange, onPlayerNameChange, onConnectionChange, permalinkParams }: GolfGameProps) => {
const [showRules, setShowRules] = useState(false)
const [showScores, setShowScores] = useState(false)

// Pass permalink parameters to useGolfGame hook for automatic joining
const [showLeaveConfirm, setShowLeaveConfirm] = useState(false)

// Helper function to get display name (now just use the ID directly)
const getDisplayName = (player: Player | null) => {
Expand Down Expand Up @@ -63,11 +62,16 @@ const GolfGame = ({ onGameIdChange, onPlayerIdChange, onPlayerNameChange, onConn
knock,
handleCardClick,
setRoomCode,
clearGameState,
leaveGame,
dismissNewGameNotification,
joinNewGame
} = useGolfGame({ onGameIdChange, onPlayerIdChange, onPlayerNameChange, onConnectionChange, permalinkParams })

const confirmLeave = useCallback(() => {
setShowLeaveConfirm(false)
leaveGame()
}, [leaveGame])

useEffect(() => {
if (gameState?.gamePhase === 'ended') {
const hideTimer = setTimeout(() => setShowScores(false), 0)
Expand Down Expand Up @@ -391,7 +395,17 @@ const GolfGame = ({ onGameIdChange, onPlayerIdChange, onPlayerNameChange, onConn
/>
</div>
)}
<button onClick={() => setShowLeaveConfirm(true)} className={styles.leaveGameLink}>
</button>
</div>
{showLeaveConfirm && (
<div className={styles.leaveConfirm}>
<span>Leave this game?</span>
<button onClick={confirmLeave} className={styles.leaveConfirmYes}>Leave</button>
<button onClick={() => setShowLeaveConfirm(false)} className={styles.leaveConfirmNo}>Stay</button>
</div>
)}
</div>

{gameState.gamePhase === 'waiting' && (
Expand All @@ -403,6 +417,9 @@ const GolfGame = ({ onGameIdChange, onPlayerIdChange, onPlayerNameChange, onConn
Start Game
</button>
)}
<button onClick={leaveGame} className={styles.textLink}>
Leave Game
</button>
</div>
)}

Expand Down Expand Up @@ -495,12 +512,9 @@ const GolfGame = ({ onGameIdChange, onPlayerIdChange, onPlayerNameChange, onConn
)}

<div className={styles.gameEndLinks}>
<button onClick={clearGameState} className={styles.textLink}>
<button onClick={leaveGame} className={styles.textLink}>
Back to Room
</button>
<button onClick={() => window.location.reload()} className={styles.textLink}>
Leave
</button>
</div>
</div>
</div>
Expand Down
12 changes: 11 additions & 1 deletion src/hooks/useGolfGame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ interface UseGolfGameReturn {
handleCardClick: (index: number) => void
setRoomCode: (code: string) => void
clearGameState: () => void
leaveGame: () => void

// Computed
currentPlayer: Player | undefined
Expand Down Expand Up @@ -283,6 +284,14 @@ export const useGolfGame = ({
setSelectedCardIndex(null)
}, [])

const leaveGame = useCallback(() => {
networkAdapterRef.current?.leaveGame()
setGameState(null)
setWinner(null)
setFinalScores(null)
setSelectedCardIndex(null)
}, [])

// Navigation helper functions
const navigateToRoom = useCallback((roomId: string) => {
const roomUrl = generateRoomPermalink(roomId)
Expand Down Expand Up @@ -803,7 +812,8 @@ export const useGolfGame = ({
handleCardClick,
setRoomCode,
clearGameState,

leaveGame,

// Navigation helpers
navigateToRoom,
navigateToGame,
Expand Down
10 changes: 9 additions & 1 deletion src/plugins/golfNetworkPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface GolfMessage extends BaseNetworkMessage {
type: 'authenticate' | 'authenticated' | 'createRoom' | 'joinRoom' | 'createGame' | 'joinGame' | 'roomJoined' | 'roomStateUpdate' | 'gameState' | 'error' |
'gameStarted' | 'turnChanged' | 'playerKnocked' | 'gameEnded' | 'newGameStarted' |
'startGame' | 'peekCard' | 'drawCard' | 'takeFromDiscard' |
'swapCard' | 'discardDrawn' | 'knock' | 'hideCards' | 'startNewGame'
'swapCard' | 'discardDrawn' | 'knock' | 'hideCards' | 'startNewGame' | 'leaveGame'
// Request fields
roomId?: string
gameId?: string
Expand Down Expand Up @@ -396,6 +396,14 @@ export class GolfNetworkPlugin implements GameNetworkPlugin {
console.log('📤 Sent start new game request')
}

leaveGame(context: NetworkContext): void {
context.send({
type: 'leaveGame',
timestamp: Date.now()
})
console.log('📤 Sent leave game request')
}

// Session token management
private storeSessionToken(token: string): void {
try {
Expand Down
4 changes: 4 additions & 0 deletions src/utils/networkAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@ export class GolfNetworkAdapter {
this.plugin.startNewGame(this.getContext())
}

leaveGame(): void {
this.plugin.leaveGame(this.getContext())
}

isMyTurn(): boolean {
return this.plugin.isMyTurn(this.getContext())
}
Expand Down
Loading