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
",
+ "D_SYNC_FOLDER_PATH": "同步文件在WebDAV服务器根目录下的相对存储路径(例如,'/super-productivity' 或 '/')。请注意,这不是您服务器内部的文件目录路径。",
"INFO": "WebDAV 实现差异很大。众所周知,Super Productivity 与 Nextcloud 配合良好,但它可能不适用于您的提供者。",
"L_BASE_URL": "基本 URL",
"L_PASSWORD": "密码",
"L_SYNC_FOLDER_PATH": "同步文件夹路径",
- "L_USER_NAME": "用户名"
+ "L_TEST_CONNECTION": "测试链接",
+ "L_USER_NAME": "用户名",
+ "S_TEST_FAIL": "连接测试失败:{{error}} - 目标URL:{{url}}",
+ "S_TEST_SUCCESS": "连接测试成功!目标URL:{{url}}"
}
},
"S": {
@@ -1150,6 +1159,9 @@
"BTN_FORCE_OVERWRITE": "强制覆盖",
"ERROR_CORS": "WebDAV 同步错误: 网络请求失败。\n\n这可能是一个跨域资源共享问题。请确保:\n• 您的 WebDAV 服务器允许跨源请求\n• 服务器 URL 正确且可访问\n• 您有有效的互联网连接",
"ERROR_DATA_IS_CURRENTLY_WRITTEN": "远程数据当前正在写入",
+ "ERROR_PERMISSION": "文件访问被拒绝。如果正在使用 Flatpak/Snap ,请通过 Flatseal 授予文件系统权限,或者使用 ~/.var/app/ 目录内的路径。",
+ "ERROR_PERMISSION_FLATPAK": "文件访问被拒绝。请通过Flatseal授予文件系统权限,或使用路径 ~/.var/app/ 内的目录。",
+ "ERROR_PERMISSION_SNAP": "文件访问被拒绝。请运行命令 'snap connect super-productivity:home',或使用路径 ~/snap/super-productivity/common/ 内的目录。",
"ERROR_FALLBACK_TO_BACKUP": "导入数据时出错。回退到本地备份。",
"ERROR_INVALID_DATA": "同步时出错。数据无效",
"ERROR_NO_REV": "远程文件没有有效的修订",
@@ -1751,6 +1763,10 @@
"HELP": "专注模式打开一个无干扰的屏幕,以帮助您专注于当前任务。",
"L_ALWAYS_OPEN_FOCUS_MODE": "始终在跟踪时打开专注模式",
"L_SKIP_PREPARATION_SCREEN": "跳过准备屏幕(拉伸等)",
+ "L_IS_PLAY_TICK": "专注时播放滴答声",
+ "L_PAUSE_TRACKING_DURING_BREAK": "休息期间暂停任务跟踪",
+ "L_SKIP_PREPARATION_SCREEN": "跳过准备界面(火箭动画)",
+ "L_START_IN_BACKGROUND": "仅以横幅开始专注时段(无覆盖层)",
"TITLE": "专注模式"
},
"IDLE": {
@@ -1887,8 +1903,8 @@
"IS_TRAY_SHOW_CURRENT_COUNTDOWN": "在托盘/状态菜单中显示当前倒计时(仅限桌面 Mac)",
"IS_TRAY_SHOW_CURRENT_TASK": "在托盘/状态菜单中显示当前任务(仅限桌面 Mac/Windows)",
"IS_TURN_OFF_MARKDOWN": "关闭任务描述的 Markdown 解析",
- "IS_USE_CUSTOM_WINDOW_TITLE_BAR": "Use custom title bar (Windows/Linux only)",
- "IS_USE_CUSTOM_WINDOW_TITLE_BAR_HINT": "Requires restart to take effect",
+ "IS_USE_CUSTOM_WINDOW_TITLE_BAR": "使用自定义标题栏(仅限Windows/Linux)",
+ "IS_USE_CUSTOM_WINDOW_TITLE_BAR_HINT": "需要重启方可生效",
"START_OF_NEXT_DAY": "下一天的开始时间",
"START_OF_NEXT_DAY_HINT": "从何时(小时)开始计算下一天已经开始。默认是午夜,即 0。",
"TASK_NOTES_TPL": "任务描述模板",