diff options
Diffstat (limited to 'android/app')
| -rw-r--r-- | android/app/src/main/AndroidManifest.xml | 6 | ||||
| -rw-r--r-- | android/app/src/main/java/org/terst/doot/widget/ui/DashboardActivity.kt | 76 |
2 files changed, 82 insertions, 0 deletions
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index ca96e71..c2200ba 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -33,6 +33,12 @@ android:exported="false" android:windowSoftInputMode="adjustResize" /> + <!-- Full dashboard, wrapped in a WebView (see DashboardActivity's doc comment) --> + <activity + android:name=".ui.DashboardActivity" + android:exported="false" + android:label="Doot" /> + <!-- Settings activity (also the widget config screen) --> <activity android:name=".ui.SettingsActivity" diff --git a/android/app/src/main/java/org/terst/doot/widget/ui/DashboardActivity.kt b/android/app/src/main/java/org/terst/doot/widget/ui/DashboardActivity.kt new file mode 100644 index 0000000..f5ae744 --- /dev/null +++ b/android/app/src/main/java/org/terst/doot/widget/ui/DashboardActivity.kt @@ -0,0 +1,76 @@ +package org.terst.doot.widget.ui + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.view.KeyEvent +import android.webkit.CookieManager +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.activity.ComponentActivity +import androidx.core.net.toUri +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch +import androidx.lifecycle.lifecycleScope +import org.terst.doot.widget.data.Keys +import org.terst.doot.widget.data.dataStore + +/** + * Wraps the existing web dashboard in a plain WebView -- the same session-cookie + * login flow a browser would use (see internal/auth/middleware.go's RequireAuth), + * no separate auth bridge needed since the widget's own bearer token is a + * completely different scheme. First cut per the 2026-08-06 feasibility check: + * one Activity, no deep-linking to specific tabs, no native-rendered chrome -- + * just prove the wrapped experience is worth building further before investing + * in anything past this. + */ +class DashboardActivity : ComponentActivity() { + + private lateinit var webView: WebView + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + webView = WebView(this).apply { + settings.javaScriptEnabled = true + settings.domStorageEnabled = true + settings.setSupportZoom(false) + webViewClient = object : WebViewClient() { + override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean { + val uri = url.toUri() + val sameHost = uri.host == null || uri.host == serverHost + if (sameHost) return false + // External links (e.g. a calendar event's source URL) open in the + // user's actual browser/app instead of getting stuck in this WebView. + startActivity(Intent(Intent.ACTION_VIEW, uri)) + return true + } + } + } + setContentView(webView) + + CookieManager.getInstance().setAcceptCookie(true) + CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true) + + lifecycleScope.launch { + val prefs = dataStore.data.first() + val url = prefs[Keys.SERVER_URL]?.trimEnd('/') + if (url.isNullOrBlank()) { + finish() + return@launch + } + serverHost = url.toUri().host + webView.loadUrl(url) + } + } + + private var serverHost: String? = null + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) { + webView.goBack() + return true + } + return super.onKeyDown(keyCode, event) + } +} |
