Add share link button for room invites
- Add 🔗 button next to room code copy button
- Copies full URL with ?room=XXXX parameter
- On page load, pre-fills room code from URL param
- Works with both logged-in users and guests
- Cleans up URL after extracting room code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
0b0873350c
commit
0c8d2b4a9c
@ -33,6 +33,20 @@ class GolfGame {
|
||||
this.initElements();
|
||||
this.initAudio();
|
||||
this.bindEvents();
|
||||
this.checkUrlParams();
|
||||
}
|
||||
|
||||
checkUrlParams() {
|
||||
// Handle ?room=XXXX share links
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const roomCode = params.get('room');
|
||||
if (roomCode) {
|
||||
this.roomCodeInput.value = roomCode.toUpperCase();
|
||||
// Focus name input so user can quickly enter name and join
|
||||
this.playerNameInput.focus();
|
||||
// Clean up URL without reloading
|
||||
window.history.replaceState({}, '', window.location.pathname);
|
||||
}
|
||||
}
|
||||
|
||||
initAudio() {
|
||||
@ -140,6 +154,7 @@ class GolfGame {
|
||||
// Waiting room elements
|
||||
this.displayRoomCode = document.getElementById('display-room-code');
|
||||
this.copyRoomCodeBtn = document.getElementById('copy-room-code');
|
||||
this.shareRoomLinkBtn = document.getElementById('share-room-link');
|
||||
this.playersList = document.getElementById('players-list');
|
||||
this.hostSettings = document.getElementById('host-settings');
|
||||
this.waitingMessage = document.getElementById('waiting-message');
|
||||
@ -234,6 +249,12 @@ class GolfGame {
|
||||
this.copyRoomCode();
|
||||
});
|
||||
|
||||
// Share room link
|
||||
this.shareRoomLinkBtn.addEventListener('click', () => {
|
||||
this.playSound('click');
|
||||
this.shareRoomLink();
|
||||
});
|
||||
|
||||
// Enter key handlers
|
||||
this.playerNameInput.addEventListener('keypress', (e) => {
|
||||
if (e.key === 'Enter') this.createRoomBtn.click();
|
||||
@ -511,22 +532,47 @@ class GolfGame {
|
||||
|
||||
copyRoomCode() {
|
||||
if (!this.roomCode) return;
|
||||
this.copyToClipboard(this.roomCode, this.copyRoomCodeBtn);
|
||||
}
|
||||
|
||||
navigator.clipboard.writeText(this.roomCode).then(() => {
|
||||
// Show brief visual feedback
|
||||
const originalText = this.copyRoomCodeBtn.textContent;
|
||||
this.copyRoomCodeBtn.textContent = '✓';
|
||||
shareRoomLink() {
|
||||
if (!this.roomCode) return;
|
||||
|
||||
// Build shareable URL with room code
|
||||
const url = new URL(window.location.href);
|
||||
url.search = ''; // Clear existing params
|
||||
url.hash = ''; // Clear hash
|
||||
url.searchParams.set('room', this.roomCode);
|
||||
const shareUrl = url.toString();
|
||||
|
||||
this.copyToClipboard(shareUrl, this.shareRoomLinkBtn);
|
||||
}
|
||||
|
||||
copyToClipboard(text, feedbackBtn) {
|
||||
// Use execCommand which is more reliable across contexts
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.value = text;
|
||||
textarea.style.position = 'fixed';
|
||||
textarea.style.left = '-9999px';
|
||||
document.body.appendChild(textarea);
|
||||
textarea.select();
|
||||
|
||||
let success = false;
|
||||
try {
|
||||
success = document.execCommand('copy');
|
||||
} catch (err) {
|
||||
console.error('Copy failed:', err);
|
||||
}
|
||||
document.body.removeChild(textarea);
|
||||
|
||||
// Show visual feedback
|
||||
if (success && feedbackBtn) {
|
||||
const originalText = feedbackBtn.textContent;
|
||||
feedbackBtn.textContent = '✓';
|
||||
setTimeout(() => {
|
||||
this.copyRoomCodeBtn.textContent = originalText;
|
||||
feedbackBtn.textContent = originalText;
|
||||
}, 1500);
|
||||
}).catch(err => {
|
||||
console.error('Failed to copy room code:', err);
|
||||
// Fallback: select the text for manual copy
|
||||
const range = document.createRange();
|
||||
range.selectNode(this.displayRoomCode);
|
||||
window.getSelection().removeAllRanges();
|
||||
window.getSelection().addRange(range);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
startGame() {
|
||||
|
||||
@ -53,7 +53,10 @@
|
||||
<div class="room-code-banner">
|
||||
<span class="room-code-label">ROOM CODE</span>
|
||||
<span class="room-code-value" id="display-room-code"></span>
|
||||
<button class="room-code-copy" id="copy-room-code" title="Copy to clipboard">📋</button>
|
||||
<div class="room-code-buttons">
|
||||
<button class="room-code-copy" id="copy-room-code" title="Copy code">📋</button>
|
||||
<button class="room-code-copy" id="share-room-link" title="Copy link">🌐</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="waiting-layout">
|
||||
|
||||
@ -275,50 +275,72 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
/* Room Code Banner - positioned top-left to avoid auth bar overlap */
|
||||
/* Room Code Banner - styled as a hanging ribbon/bookmark */
|
||||
.room-code-banner {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
left: 20px;
|
||||
z-index: 100;
|
||||
background: linear-gradient(135deg, rgba(244, 164, 96, 0.9) 0%, rgba(230, 140, 70, 0.95) 100%);
|
||||
padding: 10px 15px;
|
||||
border-radius: 0 0 12px 0;
|
||||
background: linear-gradient(180deg, #d4845a 0%, #c4723f 50%, #b8663a 100%);
|
||||
padding: 12px 16px 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
|
||||
gap: 4px;
|
||||
box-shadow: 2px 4px 12px rgba(0, 0, 0, 0.3);
|
||||
/* Ribbon forked end (snake tongue style) */
|
||||
clip-path: polygon(0 0, 100% 0, 100% 100%, 50% calc(100% - 12px), 0 100%);
|
||||
}
|
||||
|
||||
.room-code-banner::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.3) 0%, transparent 100%);
|
||||
}
|
||||
|
||||
.room-code-label {
|
||||
font-size: 0.65rem;
|
||||
font-weight: 600;
|
||||
font-size: 0.55rem;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
color: rgba(26, 71, 42, 0.8);
|
||||
letter-spacing: 0.25em;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
text-align: center;
|
||||
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.room-code-value {
|
||||
font-size: 1.5rem;
|
||||
font-size: 1.6rem;
|
||||
font-weight: 800;
|
||||
font-family: 'Courier New', monospace;
|
||||
letter-spacing: 0.2em;
|
||||
color: #1a472a;
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.3);
|
||||
color: #fff;
|
||||
text-shadow: 0 2px 2px rgba(0, 0, 0, 0.3);
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
.room-code-buttons {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.room-code-copy {
|
||||
background: rgba(26, 71, 42, 0.2);
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
padding: 6px 8px;
|
||||
border-radius: 4px;
|
||||
padding: 4px 8px;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
font-size: 0.9rem;
|
||||
transition: all 0.2s;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.room-code-copy:hover {
|
||||
background: rgba(26, 71, 42, 0.3);
|
||||
background: rgba(255, 255, 255, 0.35);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
@ -326,10 +348,6 @@ body {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.room-code-copy.copied {
|
||||
background: rgba(26, 71, 42, 0.4);
|
||||
}
|
||||
|
||||
|
||||
h1 {
|
||||
font-size: 3rem;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user