Improve share button: mobile-friendly Web Share API, icon button, fallback clipboard
This commit is contained in:
@@ -28,7 +28,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
|
|||||||
const { gameState, statistics, addGuess } = useGameState(genre, maxAttempts);
|
const { gameState, statistics, addGuess } = useGameState(genre, maxAttempts);
|
||||||
const [hasWon, setHasWon] = useState(false);
|
const [hasWon, setHasWon] = useState(false);
|
||||||
const [hasLost, setHasLost] = useState(false);
|
const [hasLost, setHasLost] = useState(false);
|
||||||
const [shareText, setShareText] = useState('Share Result');
|
const [shareText, setShareText] = useState('🔗 Share');
|
||||||
const [lastAction, setLastAction] = useState<'GUESS' | 'SKIP' | null>(null);
|
const [lastAction, setLastAction] = useState<'GUESS' | 'SKIP' | null>(null);
|
||||||
const [isProcessingGuess, setIsProcessingGuess] = useState(false);
|
const [isProcessingGuess, setIsProcessingGuess] = useState(false);
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
|
|||||||
|
|
||||||
const unlockedSeconds = unlockSteps[Math.min(gameState.guesses.length, unlockSteps.length - 1)];
|
const unlockedSeconds = unlockSteps[Math.min(gameState.guesses.length, unlockSteps.length - 1)];
|
||||||
|
|
||||||
const handleShare = () => {
|
const handleShare = async () => {
|
||||||
let emojiGrid = '';
|
let emojiGrid = '';
|
||||||
const totalGuesses = maxAttempts;
|
const totalGuesses = maxAttempts;
|
||||||
|
|
||||||
@@ -124,24 +124,33 @@ export default function Game({ dailyPuzzle, genre = null, isSpecial = false, max
|
|||||||
|
|
||||||
const text = `Hördle #${dailyPuzzle.id}\n${genreText}\n${speaker}${emojiGrid}\n\n#Hördle #Music\n\n${shareUrl}`;
|
const text = `Hördle #${dailyPuzzle.id}\n${genreText}\n${speaker}${emojiGrid}\n\n#Hördle #Music\n\n${shareUrl}`;
|
||||||
|
|
||||||
// Fallback method for copying to clipboard
|
// Try native Web Share API first (mobile-friendly)
|
||||||
const textarea = document.createElement('textarea');
|
if (navigator.share) {
|
||||||
textarea.value = text;
|
|
||||||
textarea.style.position = 'fixed';
|
|
||||||
textarea.style.opacity = '0';
|
|
||||||
document.body.appendChild(textarea);
|
|
||||||
textarea.select();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
document.execCommand('copy');
|
await navigator.share({
|
||||||
setShareText('Copied!');
|
title: `Hördle #${dailyPuzzle.id}`,
|
||||||
setTimeout(() => setShareText('Share Result'), 2000);
|
text: text,
|
||||||
|
});
|
||||||
|
setShareText('✓ Shared!');
|
||||||
|
setTimeout(() => setShareText('🔗 Share'), 2000);
|
||||||
|
return;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to copy:', err);
|
// User cancelled or error - fall through to clipboard
|
||||||
setShareText('Copy failed');
|
if ((err as Error).name !== 'AbortError') {
|
||||||
setTimeout(() => setShareText('Share Result'), 2000);
|
console.error('Share failed:', err);
|
||||||
} finally {
|
}
|
||||||
document.body.removeChild(textarea);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: Copy to clipboard
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(text);
|
||||||
|
setShareText('✓ Copied!');
|
||||||
|
setTimeout(() => setShareText('🔗 Share'), 2000);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Clipboard failed:', err);
|
||||||
|
setShareText('✗ Failed');
|
||||||
|
setTimeout(() => setShareText('🔗 Share'), 2000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user