From 6c9df2365972a3cf42dcfbac3e27a3b894211b28 Mon Sep 17 00:00:00 2001 From: arnef Date: Wed, 12 Aug 2026 11:46:56 +0200 Subject: [PATCH] Add dev live-reload tooling DevPlugin (native + TS) lets the running app switch its webview to a Vite dev server via DEV_URL, toggled from a hidden DevMenu (5 taps on the app title). --- .../java/com/tiptoisync/app/MainActivity.kt | 16 ++++ client/src/components/DevMenu.tsx | 81 +++++++++++++++++++ client/src/native/DevPlugin.ts | 8 ++ 3 files changed, 105 insertions(+) create mode 100644 client/src/components/DevMenu.tsx create mode 100644 client/src/native/DevPlugin.ts diff --git a/client/android/app/src/main/java/com/tiptoisync/app/MainActivity.kt b/client/android/app/src/main/java/com/tiptoisync/app/MainActivity.kt index e70090a..45592e3 100644 --- a/client/android/app/src/main/java/com/tiptoisync/app/MainActivity.kt +++ b/client/android/app/src/main/java/com/tiptoisync/app/MainActivity.kt @@ -3,10 +3,26 @@ package com.tiptoisync.app import android.os.Bundle import androidx.core.view.WindowCompat import com.getcapacitor.BridgeActivity +import com.getcapacitor.CapConfig class MainActivity : BridgeActivity() { override fun onCreate(savedInstanceState: Bundle?) { + // Dev-URL aus SharedPreferences lesen, bevor die Bridge initialisiert wird. + // "CapacitorStorage" ist der von @capacitor/preferences genutzte SharedPreferences-Name. + val devUrl = getSharedPreferences("CapacitorStorage", MODE_PRIVATE) + .getString("devServerUrl", null) + + if (devUrl != null) { + // CapConfig mit der Dev-Server-URL überschreiben – die Bridge lädt dann + // direkt vom Vite Dev-Server und injiziert die Bridge trotzdem korrekt. + config = CapConfig.Builder(this) + .setServerUrl(devUrl) + .setAllowMixedContent(true) + .create() + } + registerPlugin(TiptoiPlugin::class.java) + registerPlugin(DevPlugin::class.java) super.onCreate(savedInstanceState) WindowCompat.setDecorFitsSystemWindows(window, false) } diff --git a/client/src/components/DevMenu.tsx b/client/src/components/DevMenu.tsx new file mode 100644 index 0000000..f6af998 --- /dev/null +++ b/client/src/components/DevMenu.tsx @@ -0,0 +1,81 @@ +import { createSignal, onMount, Show } from 'solid-js' +import { Preferences } from '@capacitor/preferences' +import { Dev } from '../native/DevPlugin' + +const DEV_URL_KEY = 'devServerUrl' + +interface Props { + onClose: () => void +} + +export default function DevMenu(props: Props) { + const [url, setUrl] = createSignal('') + const [saved, setSaved] = createSignal(null) + + onMount(async () => { + const { value } = await Preferences.get({ key: DEV_URL_KEY }) + setSaved(value) + setUrl(value ?? '') + }) + + const handleSave = async () => { + const trimmed = url().trim() + if (!trimmed) return + // Speichern + Activity-Neustart → Bridge initialisiert sich mit Dev-URL + await Dev.activate({ url: trimmed }) + } + + const handleClear = async () => { + // Entfernen + Activity-Neustart → Bridge initialisiert sich mit gebundelter App + await Dev.deactivate() + } + + return ( +
+
e.stopPropagation()}> +
+ ⚙️ Dev-Modus + +
+ +

+ Vite Dev-Server URL eintragen. Die App lädt dann JavaScript direkt + vom Dev-Server – inkl. Hot Reload. Native Plugins bleiben aktiv. +

+ + +
+ + Aktiv: {saved()} +
+
+ +
+ setUrl(e.currentTarget.value)} + onKeyDown={e => e.key === 'Enter' && handleSave()} + /> +
+ +
+ + + + +
+
+
+ ) +} diff --git a/client/src/native/DevPlugin.ts b/client/src/native/DevPlugin.ts new file mode 100644 index 0000000..b43a08f --- /dev/null +++ b/client/src/native/DevPlugin.ts @@ -0,0 +1,8 @@ +import { registerPlugin } from '@capacitor/core' + +export interface DevPlugin { + activate(options: { url: string }): Promise + deactivate(): Promise +} + +export const Dev = registerPlugin('Dev')