feat: offline package download/import, load progress, local-first open
This commit is contained in:
@@ -19,6 +19,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowInsets
|
||||
import android.view.WindowInsetsController
|
||||
import android.webkit.WebChromeClient
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import android.widget.FrameLayout
|
||||
@@ -36,6 +37,7 @@ import top.yeij.hearth.webapp.OkHttpHttpClient
|
||||
import top.yeij.hearth.webapp.Tab
|
||||
import top.yeij.hearth.webapp.WebAppContainer
|
||||
import top.yeij.hearth.webapp.WebAppRepository
|
||||
import top.yeij.hearth.webapp.WebAppStorage
|
||||
import top.yeij.hearth.webview.BrightnessProvider
|
||||
import top.yeij.hearth.webview.JsBridge
|
||||
import top.yeij.hearth.webview.NotificationAccessProvider
|
||||
@@ -67,9 +69,15 @@ class MainActivity : Activity() {
|
||||
// Global sidebar collapsed width (dp); content WebViews reserve it on the
|
||||
// left to avoid covering the sidebar
|
||||
private const val SIDEBAR_WIDTH_DP = 80
|
||||
// SAF 导入离线包的 requestCode
|
||||
private const val REQUEST_IMPORT_ZIP = 1001
|
||||
}
|
||||
|
||||
private val webAppContainer = WebAppContainer()
|
||||
private val webAppStorage = WebAppStorage(this)
|
||||
// 待导入离线包的 webapp id(SAF 回调用)
|
||||
// Pending webapp id for offline-package import (used in the SAF callback)
|
||||
private var pendingImportId: String? = null
|
||||
private val gson = Gson()
|
||||
private val webAppHost = WebAppHostImpl()
|
||||
|
||||
@@ -205,6 +213,8 @@ class MainActivity : Activity() {
|
||||
serverUrl = serverUrlProvider,
|
||||
wallpaper = wallpaperProvider,
|
||||
onShowTabPanel = { showNativeTabPanel() },
|
||||
storage = webAppStorage,
|
||||
onImportOfflinePackage = { id -> startImportOfflinePackage(id) },
|
||||
)
|
||||
root = FrameLayout(this)
|
||||
setContentView(root)
|
||||
@@ -273,6 +283,16 @@ class MainActivity : Activity() {
|
||||
view?.loadDataWithBaseURL(null, errorPage(description ?: "未知错误"), "text/html", "utf-8", null)
|
||||
}
|
||||
}
|
||||
webView.webChromeClient = object : WebChromeClient() {
|
||||
override fun onProgressChanged(view: WebView?, newProgress: Int) {
|
||||
// 推送 webapp 页面加载进度给 H5(0-100)
|
||||
// Push the webapp page load progress to H5 (0-100)
|
||||
desktopWebView.evaluateJavascript(
|
||||
"window.HearthEvents && window.HearthEvents.webappProgress('$id', $newProgress);",
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
val params = FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT
|
||||
@@ -416,6 +436,35 @@ class MainActivity : Activity() {
|
||||
// dp to px
|
||||
private fun dp(v: Int): Int = (v * resources.displayMetrics.density).toInt()
|
||||
|
||||
// 触发 SAF 选择 zip 导入离线包
|
||||
// Trigger SAF to pick a zip for offline-package import
|
||||
private fun startImportOfflinePackage(id: String) {
|
||||
pendingImportId = id
|
||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "application/zip"
|
||||
}
|
||||
startActivityForResult(intent, REQUEST_IMPORT_ZIP)
|
||||
}
|
||||
|
||||
// SAF 结果:导入离线包,成功后通知 H5(下次点开用本地)
|
||||
// SAF result: import the offline package, notify H5 on success (next open uses local)
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (requestCode == REQUEST_IMPORT_ZIP && resultCode == Activity.RESULT_OK) {
|
||||
val id = pendingImportId ?: return
|
||||
val uri = data?.data ?: return
|
||||
val ok = webAppStorage.importPackage(id, uri)
|
||||
Log.d(TAG, "importPackage: id=$id ok=$ok")
|
||||
desktopWebView.evaluateJavascript(
|
||||
"window.HearthEvents && window.HearthEvents.webappImported('$id', $ok);",
|
||||
null
|
||||
)
|
||||
}
|
||||
pendingImportId = null
|
||||
}
|
||||
|
||||
// 检测通知使用权是否已授予,未授予时打日志提示(UI 引导入口留后续)
|
||||
// Check whether notification access is granted; log a hint when not
|
||||
// (the settings UI entry is deferred to a later task)
|
||||
|
||||
Reference in New Issue
Block a user