diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 9f13a99d7..1289bdf16 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -107,5 +107,25 @@ android:name=".receiver.ReminderActionReceiver" android:enabled="true" android:exported="false" /> + + + + + + + + + + + diff --git a/android/app/src/main/java/com/superproductivity/superproductivity/App.kt b/android/app/src/main/java/com/superproductivity/superproductivity/App.kt index bb9d9443a..540af3e9f 100644 --- a/android/app/src/main/java/com/superproductivity/superproductivity/App.kt +++ b/android/app/src/main/java/com/superproductivity/superproductivity/App.kt @@ -1,16 +1,15 @@ package com.superproductivity.superproductivity import android.app.Application +import android.os.Looper +import android.os.MessageQueue +import android.util.Log +import android.webkit.WebSettings import com.superproductivity.superproductivity.app.AppLifecycleObserver import com.superproductivity.superproductivity.app.KeyValStore class App : Application() { - // NOTE using the web view like this causes all html5 inputs not to work -// val wv: WebView by lazy { -// WebHelper().instanceView(this) -// } - val keyValStore: KeyValStore by lazy { KeyValStore(this) } @@ -20,5 +19,36 @@ class App : Application() { // Initialize AppLifecycleObserver at app startup AppLifecycleObserver.getInstance() + + // Prewarm WebView by loading native libraries during idle time + prewarmWebView() + } + + /** + * Prewarms the WebView's Chromium engine by triggering native library loading + * during main thread idle time. This reduces the 200-300ms freeze that occurs + * on first WebView creation. + * + * Uses WebSettings.getDefaultUserAgent() as recommended by the Chromium team - + * it loads WebView libraries without side effects. + */ + private fun prewarmWebView() { + try { + Looper.getMainLooper().queue.addIdleHandler(object : MessageQueue.IdleHandler { + override fun queueIdle(): Boolean { + try { + val startTime = System.currentTimeMillis() + WebSettings.getDefaultUserAgent(this@App) + val duration = System.currentTimeMillis() - startTime + Log.d("SP-WebView", "WebView prewarmed in ${duration}ms") + } catch (e: Exception) { + Log.w("SP-WebView", "WebView prewarm failed: ${e.message}") + } + return false // Remove handler after execution + } + }) + } catch (e: Exception) { + Log.w("SP-WebView", "Failed to schedule WebView prewarm: ${e.message}") + } } } diff --git a/android/app/src/main/java/com/superproductivity/superproductivity/webview/JavaScriptInterface.kt b/android/app/src/main/java/com/superproductivity/superproductivity/webview/JavaScriptInterface.kt index c8b1e4800..4f0ef9235 100644 --- a/android/app/src/main/java/com/superproductivity/superproductivity/webview/JavaScriptInterface.kt +++ b/android/app/src/main/java/com/superproductivity/superproductivity/webview/JavaScriptInterface.kt @@ -13,6 +13,7 @@ import com.superproductivity.superproductivity.app.LaunchDecider import com.superproductivity.superproductivity.service.FocusModeForegroundService import com.superproductivity.superproductivity.service.ReminderNotificationHelper import com.superproductivity.superproductivity.service.TrackingForegroundService +import com.superproductivity.superproductivity.widget.WidgetTaskQueue class JavaScriptInterface( @@ -192,6 +193,16 @@ class JavaScriptInterface( ReminderNotificationHelper.cancelReminder(activity, notificationId) } + /** + * Get queued tasks from the widget and clear the queue. + * Returns JSON string of tasks or null if empty. + */ + @Suppress("unused") + @JavascriptInterface + fun getWidgetTaskQueue(): String? { + return WidgetTaskQueue.getAndClearQueue(activity) + } + fun callJavaScriptFunction(script: String) { webView.post { webView.evaluateJavascript(script) { } } } diff --git a/android/app/src/main/java/com/superproductivity/superproductivity/widget/QuickAddActivity.kt b/android/app/src/main/java/com/superproductivity/superproductivity/widget/QuickAddActivity.kt new file mode 100644 index 000000000..07215a347 --- /dev/null +++ b/android/app/src/main/java/com/superproductivity/superproductivity/widget/QuickAddActivity.kt @@ -0,0 +1,64 @@ +package com.superproductivity.superproductivity.widget + +import android.app.Activity +import android.os.Bundle +import android.view.KeyEvent +import android.view.WindowManager +import android.view.inputmethod.EditorInfo +import android.widget.Button +import android.widget.EditText +import android.widget.Toast +import com.superproductivity.superproductivity.R + +/** + * A minimal floating dialog activity for quick task entry from the widget. + * Uses a dialog theme to appear as a floating window. + */ +class QuickAddActivity : Activity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_quick_add) + + // Make it dialog-like with proper sizing + window.setLayout( + WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.WRAP_CONTENT + ) + setFinishOnTouchOutside(true) + + val editText = findViewById(R.id.quick_add_input) + val addButton = findViewById