diff --git a/.ottotime b/.ottotime index 0ffd5ae..0b2dcb5 100644 --- a/.ottotime +++ b/.ottotime @@ -39,4 +39,9 @@ 1766434090- 25:55 1766435988- 26:44 1766438813- 3:31 -1766505127-178:25 +1766505127-209:24 +1766523797-241:53 +1766567819-999:59 +1766627818- 5:26 +1766745865- 1:03 +1766745972- 0:00 diff --git a/app.vue b/app.vue index 8e43a30..56cb578 100644 --- a/app.vue +++ b/app.vue @@ -14,13 +14,17 @@ const categoriesStore = useCategoriesStore() const placeStore = useMyPlacesStore() const authStore = useAuthStore() const configStore = useMyConfigStore() -const token = useCookie('_auth') +const { loadToken, getToken } = useAuthToken() async function loadData() { + // Először betöltjük a tokent (natív appnál Preferences-ből) + await loadToken() + const token = getToken() + const { data } = await useFetch('https://olcsoberauto.hu/rest/init', { headers: { - 'auth-key': token.value + 'auth-key': token || '' } } ) diff --git a/capacitor.config.ts b/capacitor.config.ts index 7b271a6..b435987 100644 --- a/capacitor.config.ts +++ b/capacitor.config.ts @@ -7,16 +7,13 @@ const config: CapacitorConfig = { plugins: { SplashScreen: { launchShowDuration: 2000, - launchAutoHide: false, + launchAutoHide: true, backgroundColor: '#262626', androidScaleType: 'CENTER_CROP', - showSpinner: false, - splashFullScreen: true, - splashImmersive: true + showSpinner: false }, StatusBar: { - style: 'DARK', - backgroundColor: '#262626' + overlaysWebView: false } }, android: { diff --git a/composables/useAuthToken.ts b/composables/useAuthToken.ts new file mode 100644 index 0000000..8c5211f --- /dev/null +++ b/composables/useAuthToken.ts @@ -0,0 +1,80 @@ +const AUTH_KEY = '_auth' + +// Platform ellenőrzés - csak kliens oldalon +const isNative = (): boolean => { + if (typeof window === 'undefined') return false + try { + const { Capacitor } = require('@capacitor/core') + return Capacitor.isNativePlatform() + } catch { + return false + } +} + +export const useAuthToken = () => { + const token = ref(null) + const isLoaded = ref(false) + + // Token betöltése + const loadToken = async (): Promise => { + // SSR esetén ne csináljunk semmit + if (typeof window === 'undefined') { + return null + } + + if (isNative()) { + // Natív app: Preferences használata + const { Preferences } = await import('@capacitor/preferences') + const { value } = await Preferences.get({ key: AUTH_KEY }) + token.value = value + } else { + // Web: Cookie használata + const cookie = useCookie(AUTH_KEY) + token.value = cookie.value || null + } + isLoaded.value = true + return token.value + } + + // Token mentése + const setToken = async (newToken: string): Promise => { + if (typeof window === 'undefined') return + + token.value = newToken + if (isNative()) { + const { Preferences } = await import('@capacitor/preferences') + await Preferences.set({ key: AUTH_KEY, value: newToken }) + } else { + const cookie = useCookie(AUTH_KEY, { maxAge: 60 * 60 * 24 * 365 }) // 1 év + cookie.value = newToken + } + } + + // Token törlése (kijelentkezés) + const clearToken = async (): Promise => { + if (typeof window === 'undefined') return + + token.value = null + if (isNative()) { + const { Preferences } = await import('@capacitor/preferences') + await Preferences.remove({ key: AUTH_KEY }) + } else { + const cookie = useCookie(AUTH_KEY) + cookie.value = null + } + } + + // Getter a token értékhez + const getToken = (): string | null => { + return token.value + } + + return { + token: readonly(token), + isLoaded: readonly(isLoaded), + loadToken, + setToken, + clearToken, + getToken + } +} diff --git a/package.json b/package.json index 27e5613..a35ca86 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "nuxt-app", "type": "module", - "version": "1.0.1", - "versionCode": 2, + "version": "1.0.2", + "versionCode": 3, "scripts": { "build": "nuxt build", "dev": "nuxt dev", @@ -35,6 +35,7 @@ "@capacitor/core": "^8.0.0", "@capacitor/haptics": "^8.0.0", "@capacitor/ios": "^8.0.0", + "@capacitor/preferences": "^8.0.0", "@capacitor/splash-screen": "^8.0.0", "@capacitor/status-bar": "^8.0.0", "primeicons": "^7.0.0", diff --git a/pages/login/code.vue b/pages/login/code.vue index a70b4c7..22aa27d 100644 --- a/pages/login/code.vue +++ b/pages/login/code.vue @@ -1,6 +1,7 @@ \ No newline at end of file diff --git a/plugins/capacitor.client.ts b/plugins/capacitor.client.ts index 0aba47b..fa250d8 100644 --- a/plugins/capacitor.client.ts +++ b/plugins/capacitor.client.ts @@ -18,21 +18,24 @@ export default defineNuxtPlugin((nuxtApp) => { if (router.currentRoute.value.path !== '/' && window.history.length > 1) { router.back() } else { - // Ha a főoldalon vagyunk, kérdezzük meg hogy ki akar-e lépni - // vagy minimalizáljuk az appot + // Ha a főoldalon vagyunk, minimalizáljuk az appot App.minimizeApp() } }) - // Status bar beállítása - const setupStatusBar = async () => { + // Status bar beállítása dark/light mode alapján + const setupStatusBar = async (isDark: boolean) => { try { - // Sötét ikonok világos háttérrel (vagy fordítva dark mode-ban) - await StatusBar.setStyle({ style: Style.Dark }) - - // Android-on beállíthatjuk a háttérszínt if (Capacitor.getPlatform() === 'android') { - await StatusBar.setBackgroundColor({ color: '#262626' }) // neutral-800 + if (isDark) { + // Dark mode: sötét háttér, világos ikonok + await StatusBar.setBackgroundColor({ color: '#0a0a0a' }) // surface-950 + await StatusBar.setStyle({ style: Style.Dark }) // világos ikonok + } else { + // Light mode: világos háttér, sötét ikonok + await StatusBar.setBackgroundColor({ color: '#fafafa' }) // surface-50 + await StatusBar.setStyle({ style: Style.Light }) // sötét ikonok + } } } catch (e) { console.warn('StatusBar setup error:', e) @@ -50,9 +53,18 @@ export default defineNuxtPlugin((nuxtApp) => { } } + // Dark mode figyelése + const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)') + + // Dark mode változás figyelése + darkModeQuery.addEventListener('change', (e) => { + setupStatusBar(e.matches) + }) + // App mounted hook nuxtApp.hooks.hook('app:mounted', async () => { - await setupStatusBar() + // Kezdeti beállítás a jelenlegi dark mode állapot alapján + await setupStatusBar(darkModeQuery.matches) // Kis késleltetés hogy a UI renderelődjön setTimeout(() => { hideSplash() diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f922c4b..9cd6e7c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: '@capacitor/ios': specifier: ^8.0.0 version: 8.0.0(@capacitor/core@8.0.0) + '@capacitor/preferences': + specifier: ^8.0.0 + version: 8.0.0(@capacitor/core@8.0.0) '@capacitor/splash-screen': specifier: ^8.0.0 version: 8.0.0(@capacitor/core@8.0.0) @@ -74,7 +77,7 @@ importers: version: 10.4.23(postcss@8.5.6) nuxt: specifier: 3.15.0 - version: 3.15.0(@parcel/watcher@2.5.1)(@types/node@25.0.3)(db0@0.3.4)(ioredis@5.8.2)(magicast@0.5.1)(rollup@4.54.0)(terser@5.44.1)(typescript@5.9.3)(vite@6.4.1(@types/node@25.0.3)(jiti@2.6.1)(terser@5.44.1)(yaml@2.8.2))(xml2js@0.6.2)(yaml@2.8.2) + version: 3.15.0(@capacitor/preferences@8.0.0(@capacitor/core@8.0.0))(@parcel/watcher@2.5.1)(@types/node@25.0.3)(db0@0.3.4)(ioredis@5.8.2)(magicast@0.5.1)(rollup@4.54.0)(terser@5.44.1)(typescript@5.9.3)(vite@6.4.1(@types/node@25.0.3)(jiti@2.6.1)(terser@5.44.1)(yaml@2.8.2))(xml2js@0.6.2)(yaml@2.8.2) pinia: specifier: ^2.3.1 version: 2.3.1(typescript@5.9.3)(vue@3.5.26(typescript@5.9.3)) @@ -681,6 +684,11 @@ packages: peerDependencies: '@capacitor/core': ^8.0.0 + '@capacitor/preferences@8.0.0': + resolution: {integrity: sha512-NsE7Srk9Zr0SxiVelHGiAJR7M238eyCD6dI/sDhu3ckKwFrXn8/GRyGr+SZcnGLlQKy948li8Pfcfr0dqxNf1g==} + peerDependencies: + '@capacitor/core': '>=8.0.0' + '@capacitor/splash-screen@8.0.0': resolution: {integrity: sha512-zkFdUSd6C6gd3s3bIEgtO3DVjfwpaX5mmWU9er8xYTg47zr2toEkGtfyE6CPhhErG09fl4rCqrK5DfnGrXLh9w==} peerDependencies: @@ -6640,6 +6648,10 @@ snapshots: dependencies: '@capacitor/core': 8.0.0 + '@capacitor/preferences@8.0.0(@capacitor/core@8.0.0)': + dependencies: + '@capacitor/core': 8.0.0 + '@capacitor/splash-screen@8.0.0(@capacitor/core@8.0.0)': dependencies: '@capacitor/core': 8.0.0 @@ -10242,7 +10254,7 @@ snapshots: neo-async@2.6.2: {} - nitropack@2.12.9(xml2js@0.6.2): + nitropack@2.12.9(@capacitor/preferences@8.0.0(@capacitor/core@8.0.0))(xml2js@0.6.2): dependencies: '@cloudflare/kv-asset-handler': 0.4.1 '@rollup/plugin-alias': 5.1.1(rollup@4.54.0) @@ -10309,7 +10321,7 @@ snapshots: unenv: 2.0.0-rc.24 unimport: 5.6.0 unplugin-utils: 0.3.1 - unstorage: 1.17.3(db0@0.3.4)(ioredis@5.8.2) + unstorage: 1.17.3(@capacitor/preferences@8.0.0(@capacitor/core@8.0.0))(db0@0.3.4)(ioredis@5.8.2) untyped: 2.0.0 unwasm: 0.3.11 youch: 4.1.0-beta.13 @@ -10407,7 +10419,7 @@ snapshots: nuxi@3.31.3: {} - nuxt@3.15.0(@parcel/watcher@2.5.1)(@types/node@25.0.3)(db0@0.3.4)(ioredis@5.8.2)(magicast@0.5.1)(rollup@4.54.0)(terser@5.44.1)(typescript@5.9.3)(vite@6.4.1(@types/node@25.0.3)(jiti@2.6.1)(terser@5.44.1)(yaml@2.8.2))(xml2js@0.6.2)(yaml@2.8.2): + nuxt@3.15.0(@capacitor/preferences@8.0.0(@capacitor/core@8.0.0))(@parcel/watcher@2.5.1)(@types/node@25.0.3)(db0@0.3.4)(ioredis@5.8.2)(magicast@0.5.1)(rollup@4.54.0)(terser@5.44.1)(typescript@5.9.3)(vite@6.4.1(@types/node@25.0.3)(jiti@2.6.1)(terser@5.44.1)(yaml@2.8.2))(xml2js@0.6.2)(yaml@2.8.2): dependencies: '@nuxt/devalue': 2.0.2 '@nuxt/devtools': 1.7.0(rollup@4.54.0)(vite@6.4.1(@types/node@25.0.3)(jiti@2.6.1)(terser@5.44.1)(yaml@2.8.2))(vue@3.5.26(typescript@5.9.3)) @@ -10444,7 +10456,7 @@ snapshots: magic-string: 0.30.21 mlly: 1.8.0 nanotar: 0.1.1 - nitropack: 2.12.9(xml2js@0.6.2) + nitropack: 2.12.9(@capacitor/preferences@8.0.0(@capacitor/core@8.0.0))(xml2js@0.6.2) nuxi: 3.31.3 nypm: 0.4.1 ofetch: 1.5.1 @@ -10467,7 +10479,7 @@ snapshots: unimport: 3.14.6(rollup@4.54.0) unplugin: 2.3.11 unplugin-vue-router: 0.10.9(rollup@4.54.0)(vue-router@4.6.4(vue@3.5.26(typescript@5.9.3)))(vue@3.5.26(typescript@5.9.3)) - unstorage: 1.17.3(db0@0.3.4)(ioredis@5.8.2) + unstorage: 1.17.3(@capacitor/preferences@8.0.0(@capacitor/core@8.0.0))(db0@0.3.4)(ioredis@5.8.2) untyped: 1.5.2 vue: 3.5.26(typescript@5.9.3) vue-bundle-renderer: 2.2.0 @@ -12057,7 +12069,7 @@ snapshots: picomatch: 4.0.3 webpack-virtual-modules: 0.6.2 - unstorage@1.17.3(db0@0.3.4)(ioredis@5.8.2): + unstorage@1.17.3(@capacitor/preferences@8.0.0(@capacitor/core@8.0.0))(db0@0.3.4)(ioredis@5.8.2): dependencies: anymatch: 3.1.3 chokidar: 4.0.3 @@ -12068,6 +12080,7 @@ snapshots: ofetch: 1.5.1 ufo: 1.6.1 optionalDependencies: + '@capacitor/preferences': 8.0.0(@capacitor/core@8.0.0) db0: 0.3.4 ioredis: 5.8.2 diff --git a/stores/auth.ts b/stores/auth.ts index ed9fb67..91d3067 100644 --- a/stores/auth.ts +++ b/stores/auth.ts @@ -5,12 +5,13 @@ export const useAuthStore = defineStore({ state: () => ({ user: null, rentals: null, rent: {} }), actions: { async getData() { - const token = useCookie('_auth') - if (token.value) { + const { getToken } = useAuthToken() + const token = getToken() + if (token) { const { data } = await useFetch('https://olcsoberauto.hu/rest/me', { headers: { - 'auth-key': token.value + 'auth-key': token } } ) @@ -20,6 +21,14 @@ export const useAuthStore = defineStore({ this.rentals = data.value.rentals } } + }, + async logout() { + const { clearToken } = useAuthToken() + await clearToken() + this.user = null + this.rentals = null + this.rent = {} + navigateTo('/login') } } })