The download section described a release as pending while the product was already installable, and its installer link pointed at a path the site build never ships, so a visitor would have reached a missing file. The section now states the released version and links the published update feed that the desktop client itself uses, with the release notes and hash metadata one click away. Repeated color literals behind the hero animation moved into named tokens.
110 lines
3.9 KiB
TypeScript
110 lines
3.9 KiB
TypeScript
import { useState, useEffect } from 'react'
|
|
import {
|
|
DESKTOP_VERSION,
|
|
DESKTOP_WINDOWS_INSTALLER_FILENAME,
|
|
DESKTOP_WINDOWS_INSTALLER_URL,
|
|
} from '../release'
|
|
|
|
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: '#download',
|
|
downloadFilename: '',
|
|
badgeText: 'ANDROID RELEASE PENDING',
|
|
buttonLabelKo: 'Android 공식 배포 준비 중',
|
|
buttonLabelEn: 'Android release unavailable',
|
|
subtextKo: '서명된 배포 증거가 확인될 때까지 다운로드를 제공하지 않습니다.',
|
|
subtextEn: 'Download stays unavailable until signed release evidence is verified.',
|
|
},
|
|
ios: {
|
|
os: 'ios',
|
|
osName: 'iOS',
|
|
isMobile: true,
|
|
downloadUrl: '#download',
|
|
downloadFilename: '',
|
|
badgeText: 'iOS DISTRIBUTION UNAVAILABLE',
|
|
buttonLabelKo: 'iOS 배포 미지원',
|
|
buttonLabelEn: 'iOS distribution unavailable',
|
|
subtextKo: '현재 검증된 App Store 또는 TestFlight 배포가 없습니다.',
|
|
subtextEn: 'No verified App Store or TestFlight distribution is available.',
|
|
},
|
|
windows: {
|
|
os: 'windows',
|
|
osName: 'Windows',
|
|
isMobile: false,
|
|
downloadUrl: DESKTOP_WINDOWS_INSTALLER_URL,
|
|
downloadFilename: DESKTOP_WINDOWS_INSTALLER_FILENAME,
|
|
badgeText: `DESKTOP ${DESKTOP_VERSION} OFFICIAL RELEASE`,
|
|
buttonLabelKo: `Windows용 다운로드 (x64) - v${DESKTOP_VERSION}`,
|
|
buttonLabelEn: `Download for Windows (x64) - v${DESKTOP_VERSION}`,
|
|
subtextKo: `서명된 공식 릴리스 v${DESKTOP_VERSION}이며, 설치 후 자동 업데이트 피드로 갱신됩니다.`,
|
|
subtextEn: `Signed official release v${DESKTOP_VERSION}, updated through the auto-update feed after install.`,
|
|
},
|
|
macos: {
|
|
os: 'macos',
|
|
osName: 'macOS',
|
|
isMobile: false,
|
|
downloadUrl: '#download',
|
|
downloadFilename: '',
|
|
badgeText: 'MACOS APPLE SILICON PREPARATION',
|
|
buttonLabelKo: 'macOS 릴리스 준비 중',
|
|
buttonLabelEn: 'macOS release in preparation',
|
|
subtextKo: 'Apple Silicon용 빌드는 서명과 설치 검증을 마친 뒤 제공합니다.',
|
|
subtextEn: 'The Apple Silicon build will be published after signing and installation verification.',
|
|
},
|
|
linux: {
|
|
os: 'linux',
|
|
osName: 'Linux',
|
|
isMobile: false,
|
|
downloadUrl: '#download',
|
|
downloadFilename: '',
|
|
badgeText: 'LINUX PACKAGE UNAVAILABLE',
|
|
buttonLabelKo: 'Linux 배포 미지원',
|
|
buttonLabelEn: 'Linux package unavailable',
|
|
subtextKo: '현재 검증된 AppImage 또는 DEB 패키지가 없습니다.',
|
|
subtextEn: 'No verified AppImage or DEB package is available.',
|
|
},
|
|
}
|
|
|
|
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
|
|
}
|