import { Capacitor, registerPlugin } from '@capacitor/core' // Define the plugin interface interface AppUpdatePlugin { getAppVersion(): Promise<{ versionName: string; versionCode: number }> downloadAndInstall(options: { url: string }): Promise<{ success: boolean }> } // Register the plugin const AppUpdate = registerPlugin('AppUpdate') // Update server configuration - use proxy to avoid CORS issues const UPDATE_CHECK_URL = 'https://app.logship.de/api/mobile/app-version' export const useAppUpdate = () => { const isNative = ref(false) const currentVersion = ref(null) const latestVersion = ref(null) const apkUrl = ref(null) const releaseNotes = ref(null) const updateAvailable = ref(false) const isChecking = ref(false) const isUpdating = ref(false) const error = ref(null) onMounted(async () => { isNative.value = Capacitor.isNativePlatform() if (isNative.value) { try { const info = await AppUpdate.getAppVersion() currentVersion.value = info.versionName console.log('[AppUpdate] Current version:', info.versionName, 'code:', info.versionCode) } catch (e) { console.error('[AppUpdate] Failed to get app version:', e) } } }) const checkForUpdate = async (): Promise => { console.log('[AppUpdate] checkForUpdate called, isNative:', isNative.value) // Allow checking even if not detected as native (for testing) isChecking.value = true error.value = null try { console.log('[AppUpdate] Fetching:', UPDATE_CHECK_URL) const response = await fetch(UPDATE_CHECK_URL, { method: 'GET', headers: { 'Accept': 'application/json', }, }) console.log('[AppUpdate] Response status:', response.status) if (!response.ok) { const text = await response.text() throw new Error(`HTTP ${response.status}: ${text.substring(0, 100)}`) } const data = await response.json() console.log('[AppUpdate] Response data:', data) latestVersion.value = data.versionName releaseNotes.value = data.releaseNotes || null // Build full APK URL from relative path if (data.apkUrl) { // Convert relative URL to absolute URL using the update server apkUrl.value = data.apkUrl.startsWith('http') ? data.apkUrl : `https://www.logyou.de/logship/${data.apkUrl}` } // Compare versions - if no current version, assume update available if (latestVersion.value) { if (currentVersion.value) { updateAvailable.value = compareVersions(latestVersion.value, currentVersion.value) > 0 } else { // Can't determine current version, show latest version info anyway updateAvailable.value = false } } console.log('[AppUpdate] Latest version:', latestVersion.value, 'Current:', currentVersion.value, 'Update available:', updateAvailable.value) return updateAvailable.value } catch (e: any) { const errorMsg = e.message || 'Unknown error' error.value = `Fehler: ${errorMsg}` console.error('[AppUpdate] Check failed:', e) return false } finally { isChecking.value = false } } const downloadAndInstall = async (): Promise => { if (!isNative.value || !updateAvailable.value || !apkUrl.value) return false isUpdating.value = true error.value = null try { const result = await AppUpdate.downloadAndInstall({ url: apkUrl.value }) console.log('[AppUpdate] Download and install result:', result) return result.success } catch (e: any) { error.value = e.message || 'Failed to download update' console.error('[AppUpdate] Update failed:', e) return false } finally { isUpdating.value = false } } // Compare semver versions: returns 1 if a > b, -1 if a < b, 0 if equal const compareVersions = (a: string, b: string): number => { const aParts = a.split('.').map(Number) const bParts = b.split('.').map(Number) const maxLen = Math.max(aParts.length, bParts.length) for (let i = 0; i < maxLen; i++) { const aVal = aParts[i] || 0 const bVal = bParts[i] || 0 if (aVal > bVal) return 1 if (aVal < bVal) return -1 } return 0 } return { isNative: readonly(isNative), currentVersion: readonly(currentVersion), latestVersion: readonly(latestVersion), releaseNotes: readonly(releaseNotes), updateAvailable: readonly(updateAvailable), isChecking: readonly(isChecking), isUpdating: readonly(isUpdating), error: readonly(error), checkForUpdate, downloadAndInstall } }