fixed: force redirect open browser chrome / safari
All checks were successful
Build & Deploy on Dev / build (push) Successful in 2m9s

This commit is contained in:
Warunee Tamkoo 2026-06-05 16:45:35 +07:00
parent 5c05df26cf
commit 354f528651
3 changed files with 176 additions and 1 deletions

View file

@ -1,6 +1,29 @@
<script setup lang="ts">
import { onMounted } from 'vue'
import { computed, onMounted, ref } from 'vue'
import { useSocketStore } from '@/stores/socket'
import {
getExternalBrowserUrl,
shouldShowIOSLineFallback,
} from '@/utils/forceExternalBrowser'
const showExternalBrowserFallback = computed(() => shouldShowIOSLineFallback())
const fallbackUrl = computed(() => getExternalBrowserUrl())
const copied = ref(false)
const tryOpenAgain = () => {
window.location.href = fallbackUrl.value
}
const copyLink = async () => {
copied.value = false
if (!navigator.clipboard?.writeText) {
return
}
await navigator.clipboard.writeText(fallbackUrl.value)
copied.value = true
}
onMounted(() => {
useSocketStore()
@ -9,6 +32,33 @@ onMounted(() => {
<template>
<router-view />
<div v-if="showExternalBrowserFallback" class="external-browser-overlay">
<div class="external-browser-card">
<h2>แนะนำใหเปดดวย Safari</h2>
<p>
LINE Browser อาจทำใหกลองหรอตำแหนงทำงานไมครบ กรณาเปดหนานใน
Safari เพอใชงานระบบลงเวลาไดเสถยรกวาเด
</p>
<ol>
<li>แตะป เมน ใน LINE Browser</li>
<li>เลอก เปดใน Safari</li>
</ol>
<div class="external-browser-actions">
<button type="button" class="primary" @click="tryOpenAgain">
ลองเปดอกคร
</button>
<button type="button" class="secondary" @click="copyLink">
ดลอกลงก
</button>
</div>
<p v-if="copied" class="copy-success">
ดลอกลงกแล สามารถวางใน Safari ไดนท
</p>
</div>
</div>
</template>
<style>
@ -32,4 +82,69 @@ nav a {
nav a.router-link-exact-active {
color: #42b983;
}
.external-browser-overlay {
position: fixed;
inset: 0;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
background: rgba(0, 0, 0, 0.45);
}
.external-browser-card {
width: min(520px, 100%);
border-radius: 16px;
padding: 20px;
background: #ffffff;
text-align: left;
box-shadow: 0 10px 32px rgba(0, 0, 0, 0.18);
}
.external-browser-card h2 {
margin: 0 0 10px;
font-size: 24px;
color: #0d3b66;
}
.external-browser-card p {
margin: 0 0 12px;
line-height: 1.5;
}
.external-browser-card ol {
margin: 0 0 16px;
padding-left: 20px;
}
.external-browser-actions {
display: flex;
gap: 10px;
}
.external-browser-actions button {
border: 0;
border-radius: 10px;
padding: 10px 14px;
font-size: 16px;
cursor: pointer;
}
.external-browser-actions .primary {
background: #1976d2;
color: #ffffff;
}
.external-browser-actions .secondary {
background: #edf2f7;
color: #1f2937;
}
.copy-success {
margin-top: 12px;
color: #0b7a3f;
font-weight: 600;
}
</style>

View file

@ -12,6 +12,9 @@ import 'quasar/src/css/index.sass'
import th from 'quasar/lang/th'
import http from '@/plugins/http'
import { forceOpenInExternalBrowser } from '@/utils/forceExternalBrowser'
forceOpenInExternalBrowser()
const app = createApp(App)
const pinia = createPinia()

View file

@ -0,0 +1,57 @@
const EXTERNAL_BROWSER_QUERY_KEY = 'openExternalBrowser'
const isLineBrowser = (userAgent: string) => /Line/i.test(userAgent)
const isAndroid = (userAgent: string) => /Android/i.test(userAgent)
const isIOS = (userAgent: string) => /iPhone|iPad|iPod/i.test(userAgent)
const hasExternalRedirectFlag = () => {
const params = new URLSearchParams(window.location.search)
return params.get(EXTERNAL_BROWSER_QUERY_KEY) === '1'
}
const buildIOSUrlWithFlag = () => {
const url = new URL(window.location.href)
url.searchParams.set(EXTERNAL_BROWSER_QUERY_KEY, '1')
return url.toString()
}
const buildUrlWithoutFlag = () => {
const url = new URL(window.location.href)
url.searchParams.delete(EXTERNAL_BROWSER_QUERY_KEY)
return url.toString()
}
const buildAndroidIntentUrl = () => {
const currentUrl = window.location.href
const strippedUrl = currentUrl.replace(/^https?:\/\//i, '')
return `intent://${strippedUrl}#Intent;scheme=https;package=com.android.chrome;end`
}
export const forceOpenInExternalBrowser = () => {
const userAgent = navigator.userAgent || ''
// Prevent redirect loops and only run in LINE browser.
if (!isLineBrowser(userAgent) || hasExternalRedirectFlag()) {
return
}
if (isAndroid(userAgent)) {
window.location.replace(buildAndroidIntentUrl())
return
}
if (isIOS(userAgent)) {
window.location.replace(buildIOSUrlWithFlag())
}
}
export const shouldShowIOSLineFallback = () => {
const userAgent = navigator.userAgent || ''
return (
isLineBrowser(userAgent) && isIOS(userAgent) && hasExternalRedirectFlag()
)
}
export const getExternalBrowserUrl = () => buildUrlWithoutFlag()