feat(site): implement dynamic client OS negotiation for Hero and CTA download buttons
This commit is contained in:
parent
4865387d7f
commit
55d03baf6b
5 changed files with 280 additions and 16 deletions
105
site/src/hooks/useClientOS.ts
Normal file
105
site/src/hooks/useClientOS.ts
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import { useState, useEffect } from 'react'
|
||||
|
||||
export type ClientOSType = 'android' | 'ios' | 'windows' | 'macos' | 'linux'
|
||||
|
||||
export interface ClientOSInfo {
|
||||
os: ClientOSType
|
||||
osName: string
|
||||
isMobile: boolean
|
||||
downloadUrl: string
|
||||
downloadFilename: string
|
||||
badgeText: string
|
||||
buttonLabelKo: string
|
||||
buttonLabelEn: string
|
||||
subtextKo: string
|
||||
subtextEn: string
|
||||
}
|
||||
|
||||
export const OS_CONFIGS: Record<ClientOSType, ClientOSInfo> = {
|
||||
android: {
|
||||
os: 'android',
|
||||
osName: 'Android',
|
||||
isMobile: true,
|
||||
downloadUrl: 'https://d3ro.chanpaca.net/releases/1.0.0/d3ro-voice-v1.0.0-signed.apk',
|
||||
downloadFilename: 'd3ro-voice-v1.0.0-signed.apk',
|
||||
badgeText: 'ANDROID APK v1.0.0',
|
||||
buttonLabelKo: 'Android용 무료 다운로드 (APK)',
|
||||
buttonLabelEn: 'Download for Android (APK)',
|
||||
subtextKo: 'v1.0.0 · 공식 서명 APK (47.5MB) · Google Play 호환',
|
||||
subtextEn: 'v1.0.0 · Official Signed APK (47.5MB) · Play Protected',
|
||||
},
|
||||
ios: {
|
||||
os: 'ios',
|
||||
osName: 'iOS',
|
||||
isMobile: true,
|
||||
downloadUrl: '#download',
|
||||
downloadFilename: '',
|
||||
badgeText: 'iOS TESTFLIGHT / PWA',
|
||||
buttonLabelKo: 'iOS 앱 / TestFlight 시작',
|
||||
buttonLabelEn: 'Download for iOS (TestFlight)',
|
||||
subtextKo: 'v1.0.0 · iPhone & iPad 지원 · PWA 즉시 실행',
|
||||
subtextEn: 'v1.0.0 · iPhone & iPad Supported · Instant PWA',
|
||||
},
|
||||
windows: {
|
||||
os: 'windows',
|
||||
osName: 'Windows',
|
||||
isMobile: false,
|
||||
downloadUrl: 'https://d3ro.chanpaca.net/releases/1.0.0/D3RO-Voice-Setup-1.0.0-x64.exe',
|
||||
downloadFilename: 'D3RO-Voice-Setup-1.0.0-x64.exe',
|
||||
badgeText: 'WINDOWS x64 v1.0.0',
|
||||
buttonLabelKo: 'Windows용 무료 다운로드',
|
||||
buttonLabelEn: 'Download for Windows (x64)',
|
||||
subtextKo: 'v1.0.0 · x64 공식 인스톨러 (102MB) · 온디바이스',
|
||||
subtextEn: 'v1.0.0 · x64 Official Setup (102MB) · On-Device',
|
||||
},
|
||||
macos: {
|
||||
os: 'macos',
|
||||
osName: 'macOS',
|
||||
isMobile: false,
|
||||
downloadUrl: '#download',
|
||||
downloadFilename: '',
|
||||
badgeText: 'MACOS UNIVERSAL',
|
||||
buttonLabelKo: 'macOS용 무료 다운로드',
|
||||
buttonLabelEn: 'Download for macOS (Universal)',
|
||||
subtextKo: 'v1.0.0 · Apple Silicon (M1/M2/M3/M4) & Intel 지원',
|
||||
subtextEn: 'v1.0.0 · Apple Silicon & Intel Universal',
|
||||
},
|
||||
linux: {
|
||||
os: 'linux',
|
||||
osName: 'Linux',
|
||||
isMobile: false,
|
||||
downloadUrl: '#download',
|
||||
downloadFilename: '',
|
||||
badgeText: 'LINUX APPIMAGE / DEB',
|
||||
buttonLabelKo: 'Linux용 무료 다운로드',
|
||||
buttonLabelEn: 'Download for Linux (AppImage)',
|
||||
subtextKo: 'v1.0.0 · Ubuntu / Debian / Arch 지원',
|
||||
subtextEn: 'v1.0.0 · Ubuntu / Debian / Arch Supported',
|
||||
},
|
||||
}
|
||||
|
||||
export function useClientOS(): ClientOSInfo {
|
||||
const [osInfo, setOsInfo] = useState<ClientOSInfo>(OS_CONFIGS.windows)
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window === 'undefined' || !navigator) return
|
||||
const ua = navigator.userAgent || ''
|
||||
const platform = (navigator as any).userAgentData?.platform || navigator.platform || ''
|
||||
|
||||
if (/android/i.test(ua)) {
|
||||
setOsInfo(OS_CONFIGS.android)
|
||||
} else if (/iphone|ipad|ipod/i.test(ua) || (platform === 'MacIntel' && navigator.maxTouchPoints > 1)) {
|
||||
setOsInfo(OS_CONFIGS.ios)
|
||||
} else if (/macintosh|mac os x/i.test(ua) || /mac/i.test(platform)) {
|
||||
setOsInfo(OS_CONFIGS.macos)
|
||||
} else if (/linux/i.test(ua) || /linux/i.test(platform)) {
|
||||
setOsInfo(OS_CONFIGS.linux)
|
||||
} else if (/windows|win32|win64/i.test(ua) || /win/i.test(platform)) {
|
||||
setOsInfo(OS_CONFIGS.windows)
|
||||
} else {
|
||||
setOsInfo(OS_CONFIGS.windows)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return osInfo
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue