fixed: force redirect open browser chrome / safari
All checks were successful
Build & Deploy on Dev / build (push) Successful in 2m9s
All checks were successful
Build & Deploy on Dev / build (push) Successful in 2m9s
This commit is contained in:
parent
5c05df26cf
commit
354f528651
3 changed files with 176 additions and 1 deletions
117
src/App.vue
117
src/App.vue
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
57
src/utils/forceExternalBrowser.ts
Normal file
57
src/utils/forceExternalBrowser.ts
Normal 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()
|
||||
Loading…
Add table
Add a link
Reference in a new issue