mejoras UX pwa
This commit is contained in:
@@ -1,10 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="lobby">
|
<div class="lobby">
|
||||||
<div class="lobby-container">
|
<div class="lobby-container">
|
||||||
<div class="lobby-header">
|
<div class="topbar">
|
||||||
<button @click="goToSelector" class="btn btn-back">
|
<div class="lobby-header">
|
||||||
← UUIDs
|
<button @click="goToSelector" class="btn btn-back">← UUIDs</button>
|
||||||
</button>
|
</div>
|
||||||
|
<!-- Install banner (sutil, inline con UUIDs) -->
|
||||||
|
<div
|
||||||
|
v-if="showInstallBanner"
|
||||||
|
class="install-banner"
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
>
|
||||||
|
<div class="install-banner-content">
|
||||||
|
<img class="install-icon" src="/pwa_icons/icon-72x72.png" alt="SnatchGame" />
|
||||||
|
<div class="install-text">
|
||||||
|
<strong>Instalá SnatchGame</strong>
|
||||||
|
<span v-if="canPromptInstall">Acceso rápido desde tu pantalla de inicio.</span>
|
||||||
|
<span v-else>iOS: Compartir → Añadir a pantalla de inicio.</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="install-actions">
|
||||||
|
<button v-if="canPromptInstall" class="btn btn-install" @click="triggerInstall">Instalar</button>
|
||||||
|
<button class="btn btn-dismiss" @click="dismissBanner" aria-label="Cerrar">✕</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h1 class="title">
|
<h1 class="title">
|
||||||
<GameLogo size="large" /> Snatch Game
|
<GameLogo size="large" /> Snatch Game
|
||||||
@@ -12,8 +32,9 @@
|
|||||||
<div class="subtitle">Arena de intercambio social</div>
|
<div class="subtitle">Arena de intercambio social</div>
|
||||||
|
|
||||||
<div class="player-section">
|
<div class="player-section">
|
||||||
<div class="name-input-group">
|
<div class="name-input-group" v-if="!nameConfirmed || editingName">
|
||||||
<input
|
<input
|
||||||
|
ref="nameInputRef"
|
||||||
v-model="inputName"
|
v-model="inputName"
|
||||||
@keyup.enter="updateName"
|
@keyup.enter="updateName"
|
||||||
type="text"
|
type="text"
|
||||||
@@ -23,8 +44,15 @@
|
|||||||
/>
|
/>
|
||||||
<button @click="updateName" class="btn btn-secondary">Confirmar Nombre</button>
|
<button @click="updateName" class="btn btn-secondary">Confirmar Nombre</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="current-name">
|
<div class="main-actions inline">
|
||||||
Jugando como: <span class="player-name">{{ playerName || 'invitado' }}</span>
|
<button @click="handleQuickPlay" class="btn btn-primary btn-large" :disabled="isJoining || !nameConfirmed">
|
||||||
|
<span v-if="!isJoining">Jugar</span>
|
||||||
|
<span v-else>Buscando partida...</span>
|
||||||
|
</button>
|
||||||
|
<div v-if="!nameConfirmed" class="hint">Antes de jugar, presiona "Confirmar Nombre" para confirmar tu nombre.</div>
|
||||||
|
</div>
|
||||||
|
<div class="current-name" :class="{ clickable: nameConfirmed }" @click="nameConfirmed ? startEditName() : null" :title="nameConfirmed ? 'Editar nombre' : ''">
|
||||||
|
Jugando como: <span class="player-name">{{ playerName || 'invitado' }}</span><span v-if="nameConfirmed" class="edit-hint"> (✏️)</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="color-picker">
|
<div class="color-picker">
|
||||||
<label class="color-label">Color:</label>
|
<label class="color-label">Color:</label>
|
||||||
@@ -35,30 +63,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="main-actions">
|
<div class="qr-section compact">
|
||||||
<button @click="handleQuickPlay" class="btn btn-primary btn-large" :disabled="isJoining || !nameConfirmed">
|
<div class="qr-container compact">
|
||||||
<span v-if="!isJoining">🧪 Jugar</span>
|
<div class="qr-inline">
|
||||||
<span v-else>Buscando partida...</span>
|
<canvas ref="qrCanvas" class="qr-canvas small"></canvas>
|
||||||
</button>
|
<div class="qr-side">
|
||||||
<div v-if="!nameConfirmed" class="hint">Antes de jugar, presiona "Confirmar Nombre" para confirmar tu nombre.</div>
|
<p class="url-display small" title="{{ gameUrl }}">{{ shortUrl }}</p>
|
||||||
<div v-else class="hint ok">Nombre confirmado ✔</div>
|
<div class="qr-actions tight">
|
||||||
</div>
|
<button @click="copyUrl" class="btn btn-copy tiny">Copiar</button>
|
||||||
|
<button @click="shareQR" class="btn btn-share tiny">Compartir</button>
|
||||||
<div class="qr-section">
|
</div>
|
||||||
<h2>🎯 Tu Acceso al Juego</h2>
|
<p class="uuid-display small">UUID: {{ routeUuid.substring(0, 8) }}...</p>
|
||||||
<div class="qr-container">
|
|
||||||
<div class="qr-header">
|
|
||||||
<h3>Enlace de Juego de {{ playerName || 'Invitado' }}</h3>
|
|
||||||
<p class="uuid-display">UUID: {{ routeUuid.substring(0, 8) }}...</p>
|
|
||||||
</div>
|
|
||||||
<div class="qr-code-wrapper">
|
|
||||||
<canvas ref="qrCanvas" class="qr-canvas"></canvas>
|
|
||||||
</div>
|
|
||||||
<div class="qr-footer">
|
|
||||||
<p class="url-display">{{ gameUrl }}</p>
|
|
||||||
<div class="qr-actions">
|
|
||||||
<button @click="copyUrl" class="btn btn-copy">📋 Copiar Enlace</button>
|
|
||||||
<button @click="shareQR" class="btn btn-share">📤 Compartir QR</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -83,6 +98,13 @@ const inputName = ref('');
|
|||||||
const isJoining = ref(false);
|
const isJoining = ref(false);
|
||||||
const colorInput = ref('#667eea');
|
const colorInput = ref('#667eea');
|
||||||
const qrCanvas = ref<HTMLCanvasElement>();
|
const qrCanvas = ref<HTMLCanvasElement>();
|
||||||
|
const showInstallBanner = ref(false);
|
||||||
|
const canPromptInstall = ref(false);
|
||||||
|
let deferredPrompt: any = null;
|
||||||
|
let onBipHandler: ((e: any) => void) | null = null;
|
||||||
|
let installTimer: any = null;
|
||||||
|
const editingName = ref(false);
|
||||||
|
const nameInputRef = ref<HTMLInputElement | null>(null);
|
||||||
|
|
||||||
// QR Code computed properties
|
// QR Code computed properties
|
||||||
const gameUrl = computed(() => {
|
const gameUrl = computed(() => {
|
||||||
@@ -90,6 +112,43 @@ const gameUrl = computed(() => {
|
|||||||
return `${baseUrl}/${routeUuid.value}`;
|
return `${baseUrl}/${routeUuid.value}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const shortUrl = computed(() => {
|
||||||
|
try {
|
||||||
|
const u = new URL(gameUrl.value);
|
||||||
|
// usar host corto + path uuid
|
||||||
|
return `${u.host}/${routeUuid.value}`;
|
||||||
|
} catch {
|
||||||
|
return gameUrl.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const isStandalone = () =>
|
||||||
|
(window.matchMedia && window.matchMedia('(display-mode: standalone)').matches) ||
|
||||||
|
// iOS
|
||||||
|
(window as any).navigator.standalone === true;
|
||||||
|
|
||||||
|
const isIOS = () => /iphone|ipad|ipod/i.test(navigator.userAgent);
|
||||||
|
|
||||||
|
function maybeShowInstallBanner() {
|
||||||
|
const dismissed = localStorage.getItem('sg_install_banner_dismissed') === '1';
|
||||||
|
if (dismissed || isStandalone()) return;
|
||||||
|
if (deferredPrompt) {
|
||||||
|
canPromptInstall.value = true;
|
||||||
|
showInstallBanner.value = true;
|
||||||
|
if (installTimer) clearTimeout(installTimer);
|
||||||
|
installTimer = setTimeout(() => {
|
||||||
|
showInstallBanner.value = false;
|
||||||
|
}, 10000);
|
||||||
|
} else if (isIOS()) {
|
||||||
|
canPromptInstall.value = false;
|
||||||
|
showInstallBanner.value = true;
|
||||||
|
if (installTimer) clearTimeout(installTimer);
|
||||||
|
installTimer = setTimeout(() => {
|
||||||
|
showInstallBanner.value = false;
|
||||||
|
}, 12000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const playerName = computed(() => colyseusService.playerName.value);
|
const playerName = computed(() => colyseusService.playerName.value);
|
||||||
const nameConfirmed = computed(() => colyseusService.nameConfirmed.value);
|
const nameConfirmed = computed(() => colyseusService.nameConfirmed.value);
|
||||||
const playerColor = computed(() => colyseusService.playerColor.value);
|
const playerColor = computed(() => colyseusService.playerColor.value);
|
||||||
@@ -110,8 +169,17 @@ const onlinePlayers = ref<any[]>([]);
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
|
// install prompt listener
|
||||||
|
onBipHandler = (e: any) => {
|
||||||
|
e.preventDefault();
|
||||||
|
deferredPrompt = e;
|
||||||
|
maybeShowInstallBanner();
|
||||||
|
};
|
||||||
|
window.addEventListener('beforeinstallprompt', onBipHandler);
|
||||||
|
|
||||||
const room = await colyseusService.joinLobby();
|
const room = await colyseusService.joinLobby();
|
||||||
colorInput.value = colyseusService.playerColor.value || '#667eea';
|
colorInput.value = colyseusService.playerColor.value || '#667eea';
|
||||||
|
inputName.value = colyseusService.playerName.value || '';
|
||||||
|
|
||||||
let resumed = false;
|
let resumed = false;
|
||||||
const guardResume = () => { if (resumed) return true; resumed = true; return false; };
|
const guardResume = () => { if (resumed) return true; resumed = true; return false; };
|
||||||
@@ -251,6 +319,9 @@ onMounted(async () => {
|
|||||||
|
|
||||||
// Generate QR code after lobby is set up
|
// Generate QR code after lobby is set up
|
||||||
await generateQRCode();
|
await generateQRCode();
|
||||||
|
|
||||||
|
// Show install banner if applicable (e.g., iOS or after BIP fired)
|
||||||
|
maybeShowInstallBanner();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to join lobby:', error);
|
console.error('Failed to join lobby:', error);
|
||||||
}
|
}
|
||||||
@@ -259,12 +330,15 @@ onMounted(async () => {
|
|||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
// Don't leave the current room - it might be a game room now
|
// Don't leave the current room - it might be a game room now
|
||||||
console.log('Lobby component unmounting...');
|
console.log('Lobby component unmounting...');
|
||||||
|
if (onBipHandler) window.removeEventListener('beforeinstallprompt', onBipHandler);
|
||||||
|
if (installTimer) clearTimeout(installTimer);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function updateName() {
|
async function updateName() {
|
||||||
// Send even if empty; server will assign a default unique name when empty
|
// Send even if empty; server will assign a default unique name when empty
|
||||||
const name = inputName.value.trim();
|
const name = inputName.value.trim();
|
||||||
await colyseusService.setPlayerName(name);
|
await colyseusService.setPlayerName(name);
|
||||||
|
editingName.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateColor() {
|
async function updateColor() {
|
||||||
@@ -321,11 +395,11 @@ async function generateQRCode() {
|
|||||||
try {
|
try {
|
||||||
// Responsive QR size based on screen width
|
// Responsive QR size based on screen width
|
||||||
const isMobile = window.innerWidth <= 767;
|
const isMobile = window.innerWidth <= 767;
|
||||||
const qrSize = isMobile ? 200 : 256;
|
const qrSize = isMobile ? 100 : 140; // aún más compacto
|
||||||
|
|
||||||
await QRCode.toCanvas(qrCanvas.value, gameUrl.value, {
|
await QRCode.toCanvas(qrCanvas.value, gameUrl.value, {
|
||||||
width: qrSize,
|
width: qrSize,
|
||||||
margin: 2,
|
margin: 0,
|
||||||
color: {
|
color: {
|
||||||
dark: '#000000',
|
dark: '#000000',
|
||||||
light: '#FFFFFF'
|
light: '#FFFFFF'
|
||||||
@@ -363,6 +437,32 @@ function shareQR() {
|
|||||||
function goToSelector() {
|
function goToSelector() {
|
||||||
router.push('/');
|
router.push('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function triggerInstall() {
|
||||||
|
try {
|
||||||
|
if (!deferredPrompt) return;
|
||||||
|
deferredPrompt.prompt();
|
||||||
|
const { outcome } = await deferredPrompt.userChoice;
|
||||||
|
if (outcome === 'accepted') {
|
||||||
|
dismissBanner();
|
||||||
|
}
|
||||||
|
deferredPrompt = null;
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
function dismissBanner() {
|
||||||
|
showInstallBanner.value = false;
|
||||||
|
localStorage.setItem('sg_install_banner_dismissed', '1');
|
||||||
|
if (installTimer) clearTimeout(installTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function startEditName() {
|
||||||
|
editingName.value = true;
|
||||||
|
inputName.value = colyseusService.playerName.value || '';
|
||||||
|
nextTick(() => {
|
||||||
|
nameInputRef.value?.focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -387,8 +487,30 @@ function goToSelector() {
|
|||||||
padding: 40px;
|
padding: 40px;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
.topbar { display:flex; align-items:center; gap: 8px; justify-content: space-between; margin-bottom: 10px; }
|
||||||
|
.topbar .install-banner { flex: 1; }
|
||||||
|
|
||||||
|
.install-banner {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
background: #f7f9ff;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.install-banner-content { display: flex; align-items: center; gap: 10px; }
|
||||||
|
.install-icon { width: 24px; height: 24px; border-radius: 6px; }
|
||||||
|
.install-text { display:flex; flex-direction: column; line-height: 1.1; }
|
||||||
|
.install-text strong { font-size: 14px; color: #334155; }
|
||||||
|
.install-text span { font-size: 12px; color: #64748b; }
|
||||||
|
.install-actions { display:flex; align-items:center; gap: 6px; }
|
||||||
|
.btn-install { background:#111; color:#fff; padding: 6px 10px; border-radius: 6px; font-size: 12px; }
|
||||||
|
.btn-dismiss { background: transparent; color:#64748b; padding: 4px 6px; font-size: 14px; }
|
||||||
|
|
||||||
.lobby-header {
|
.lobby-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -494,6 +616,10 @@ function goToSelector() {
|
|||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.current-name.clickable { cursor: pointer; }
|
||||||
|
.current-name.clickable:hover .player-name { text-decoration: underline; }
|
||||||
|
.edit-hint { color: #94a3b8; font-size: 0.9rem; }
|
||||||
|
|
||||||
.player-name {
|
.player-name {
|
||||||
color: #667eea;
|
color: #667eea;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@@ -541,6 +667,8 @@ function goToSelector() {
|
|||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn.tiny { padding: 6px 10px; font-size: 12px; }
|
||||||
|
|
||||||
.btn:disabled {
|
.btn:disabled {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
@@ -551,6 +679,8 @@ function goToSelector() {
|
|||||||
margin: 40px 0;
|
margin: 40px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.main-actions.inline { margin: 12px 0; }
|
||||||
|
|
||||||
.rooms-section {
|
.rooms-section {
|
||||||
margin: 40px 0;
|
margin: 40px 0;
|
||||||
}
|
}
|
||||||
@@ -682,6 +812,8 @@ function goToSelector() {
|
|||||||
margin: 40px 0;
|
margin: 40px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qr-section.compact { margin: 20px 0; }
|
||||||
|
|
||||||
.qr-section h2 {
|
.qr-section h2 {
|
||||||
color: #333;
|
color: #333;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
@@ -697,6 +829,8 @@ function goToSelector() {
|
|||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qr-container.compact { padding: 8px; }
|
||||||
|
|
||||||
.qr-container:hover {
|
.qr-container:hover {
|
||||||
border-color: #667eea;
|
border-color: #667eea;
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
@@ -713,8 +847,9 @@ function goToSelector() {
|
|||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
color: #666;
|
color: #666;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin: 0 0 20px 0;
|
margin: 0 0 20px 0;
|
||||||
}
|
}
|
||||||
|
.uuid-display.small { font-size: 11px; margin: 0; }
|
||||||
|
|
||||||
.qr-code-wrapper {
|
.qr-code-wrapper {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -729,6 +864,10 @@ function goToSelector() {
|
|||||||
display: block;
|
display: block;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
.qr-canvas.small { image-rendering: pixelated; }
|
||||||
|
|
||||||
|
.qr-inline { display:flex; align-items:center; gap: 8px; justify-content:center; }
|
||||||
|
.qr-side { display:flex; flex-direction: column; gap: 6px; align-items: flex-start; }
|
||||||
|
|
||||||
.qr-footer {
|
.qr-footer {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
@@ -744,6 +883,7 @@ function goToSelector() {
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid #e0e0e0;
|
border: 1px solid #e0e0e0;
|
||||||
}
|
}
|
||||||
|
.url-display.small { font-size: 11px; margin: 0; padding: 4px 6px; }
|
||||||
|
|
||||||
.qr-actions {
|
.qr-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -752,6 +892,8 @@ function goToSelector() {
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qr-actions.tight { gap: 6px; }
|
||||||
|
|
||||||
.btn-copy,
|
.btn-copy,
|
||||||
.btn-share {
|
.btn-share {
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
@@ -792,19 +934,9 @@ function goToSelector() {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.qr-container {
|
.qr-container { padding: 14px; }
|
||||||
padding: 20px;
|
.qr-code-wrapper { padding: 10px; margin: 10px 0; }
|
||||||
}
|
.qr-canvas.small { width: 100px !important; height: 100px !important; }
|
||||||
|
|
||||||
.qr-code-wrapper {
|
|
||||||
padding: 15px;
|
|
||||||
margin: 15px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.qr-canvas {
|
|
||||||
width: 200px !important;
|
|
||||||
height: 200px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.qr-actions {
|
.qr-actions {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -153,6 +153,15 @@ const qrMode = ref(false);
|
|||||||
const qrCanvas = ref<HTMLCanvasElement>();
|
const qrCanvas = ref<HTMLCanvasElement>();
|
||||||
const printContainer = ref<HTMLElement>();
|
const printContainer = ref<HTMLElement>();
|
||||||
|
|
||||||
|
// Detect PWA standalone mode
|
||||||
|
function isStandalone(): boolean {
|
||||||
|
return (
|
||||||
|
(window.matchMedia && window.matchMedia('(display-mode: standalone)').matches) ||
|
||||||
|
// iOS standalone
|
||||||
|
(window as any).navigator?.standalone === true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Context menu state
|
// Context menu state
|
||||||
const contextMenu = ref({
|
const contextMenu = ref({
|
||||||
visible: false,
|
visible: false,
|
||||||
@@ -231,9 +240,13 @@ function selectUuid(uuid: string) {
|
|||||||
printQR(uuidInfo);
|
printQR(uuidInfo);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Open in new tab instead of redirecting
|
if (isStandalone()) {
|
||||||
const url = `${window.location.origin}/${uuid}`;
|
// En PWA, navegar usando ruta nombrada para mayor robustez
|
||||||
window.open(url, '_blank');
|
router.push({ name: 'LobbyWithUuid', params: { uuid } });
|
||||||
|
} else {
|
||||||
|
const url = `${window.location.origin}/${uuid}`;
|
||||||
|
window.open(url, '_blank');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,9 +257,13 @@ function selectRandom() {
|
|||||||
// Show QR modal if in QR mode
|
// Show QR modal if in QR mode
|
||||||
printQR(randomUuidInfo);
|
printQR(randomUuidInfo);
|
||||||
} else {
|
} else {
|
||||||
// Open in new tab
|
const uuid = randomUuidInfo.uuid;
|
||||||
const url = `${window.location.origin}/${randomUuidInfo.uuid}`;
|
if (isStandalone()) {
|
||||||
window.open(url, '_blank');
|
router.push({ name: 'LobbyWithUuid', params: { uuid } });
|
||||||
|
} else {
|
||||||
|
const url = `${window.location.origin}/${uuid}`;
|
||||||
|
window.open(url, '_blank');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1316,7 +1333,6 @@ async function copyToClipboard() {
|
|||||||
.btn-leaderboard {
|
.btn-leaderboard {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.print-modal-content {
|
.print-modal-content {
|
||||||
width: 95%;
|
width: 95%;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
@@ -1326,4 +1342,4 @@ async function copyToClipboard() {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user