feat: settings interactions (theme/mask/brightness/server-url), svg icons, seconds display, page transition
This commit is contained in:
@@ -3,6 +3,7 @@ package top.yeij.hearth
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.text.TextUtils
|
||||
@@ -25,8 +26,10 @@ 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.webview.BrightnessProvider
|
||||
import top.yeij.hearth.webview.JsBridge
|
||||
import top.yeij.hearth.webview.NotificationAccessProvider
|
||||
import top.yeij.hearth.webview.ServerUrlProvider
|
||||
import top.yeij.hearth.webview.WebAppHost
|
||||
import top.yeij.hearth.webview.WebViewManager
|
||||
import java.io.File
|
||||
@@ -63,6 +66,47 @@ class MainActivity : Activity() {
|
||||
startActivity(Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS))
|
||||
}
|
||||
}
|
||||
|
||||
// 系统亮度访问实现:读/写 Settings.System.SCREEN_BRIGHTNESS,需 WRITE_SETTINGS 授权
|
||||
// System brightness implementation: read/write Settings.System.SCREEN_BRIGHTNESS,
|
||||
// requiring the WRITE_SETTINGS grant
|
||||
private val brightnessProvider = object : BrightnessProvider {
|
||||
override fun getSystemBrightness(): Int =
|
||||
Settings.System.getInt(contentResolver, Settings.System.SCREEN_BRIGHTNESS, 128)
|
||||
|
||||
override fun setSystemBrightness(value: Int) {
|
||||
Settings.System.putInt(
|
||||
contentResolver,
|
||||
Settings.System.SCREEN_BRIGHTNESS,
|
||||
value.coerceIn(0, 255)
|
||||
)
|
||||
}
|
||||
|
||||
override fun canWriteSettings(): Boolean = Settings.System.canWrite(this@MainActivity)
|
||||
|
||||
override fun requestWriteSettings() {
|
||||
startActivity(
|
||||
Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS, Uri.parse("package:$packageName"))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 服务器地址存储实现:SharedPreferences 持久化,设置时同步更新 WebAppRepository
|
||||
// Server URL storage implementation: persisted in SharedPreferences, syncing the
|
||||
// WebAppRepository manifest URL on change
|
||||
private val serverUrlProvider = object : ServerUrlProvider {
|
||||
private val prefs by lazy { getSharedPreferences("hearth", MODE_PRIVATE) }
|
||||
|
||||
override fun getServerUrl(): String =
|
||||
prefs.getString("server_url", MANIFEST_URL) ?: MANIFEST_URL
|
||||
|
||||
override fun setServerUrl(url: String) {
|
||||
prefs.edit().putString("server_url", url).apply()
|
||||
if (::webAppRepository.isInitialized) webAppRepository.setManifestUrl(url)
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var webAppRepository: WebAppRepository
|
||||
private lateinit var mediaSource: MediaSessionSource
|
||||
private lateinit var root: FrameLayout
|
||||
private lateinit var desktopWebView: WebView
|
||||
@@ -96,18 +140,21 @@ class MainActivity : Activity() {
|
||||
Configuration.UI_MODE_NIGHT_YES
|
||||
val cache = CacheManager(File(filesDir, "cache"))
|
||||
val http = OkHttpHttpClient()
|
||||
webAppRepository = WebAppRepository(http, cache, serverUrlProvider.getServerUrl())
|
||||
bridge = JsBridge(
|
||||
deviceWidthPx = dm.widthPixels,
|
||||
deviceHeightPx = dm.heightPixels,
|
||||
density = dm.density,
|
||||
darkMode = darkMode,
|
||||
appRepository = AppRepository(AndroidAppSource(this)),
|
||||
webAppRepository = WebAppRepository(http, cache, MANIFEST_URL),
|
||||
webAppRepository = webAppRepository,
|
||||
cardRepository = CardRepository(http, cache, CATALOG_URL),
|
||||
webAppContainer = webAppContainer,
|
||||
webAppHost = webAppHost,
|
||||
postToMainThread = { desktopWebView.post(it) },
|
||||
notificationAccess = notificationAccess,
|
||||
brightness = brightnessProvider,
|
||||
serverUrl = serverUrlProvider,
|
||||
)
|
||||
root = FrameLayout(this)
|
||||
setContentView(root)
|
||||
|
||||
@@ -27,10 +27,17 @@ interface HttpClient {
|
||||
class WebAppRepository(
|
||||
private val http: HttpClient,
|
||||
private val cache: CacheManager,
|
||||
private val manifestUrl: String,
|
||||
private var manifestUrl: String,
|
||||
) {
|
||||
private val gson = Gson()
|
||||
|
||||
// 更新清单地址(设置页修改服务器地址后调用)
|
||||
// Update the manifest URL (called after the settings page changes the server URL)
|
||||
fun setManifestUrl(url: String) {
|
||||
manifestUrl = url
|
||||
Log.d(TAG, "setManifestUrl: $url")
|
||||
}
|
||||
|
||||
fun fetchManifest(): List<WebApp> {
|
||||
val body = http.get(manifestUrl)
|
||||
if (body != null) {
|
||||
|
||||
@@ -19,6 +19,22 @@ interface NotificationAccessProvider {
|
||||
fun requestAccess()
|
||||
}
|
||||
|
||||
// 系统亮度访问接口:由 MainActivity 实现(Settings.System + WRITE_SETTINGS 授权)
|
||||
// System brightness provider implemented by MainActivity (Settings.System + WRITE_SETTINGS)
|
||||
interface BrightnessProvider {
|
||||
fun getSystemBrightness(): Int
|
||||
fun setSystemBrightness(value: Int)
|
||||
fun canWriteSettings(): Boolean
|
||||
fun requestWriteSettings()
|
||||
}
|
||||
|
||||
// 服务器地址存储接口:由 MainActivity 实现(SharedPreferences 持久化)
|
||||
// Server URL storage provider implemented by MainActivity (SharedPreferences)
|
||||
interface ServerUrlProvider {
|
||||
fun getServerUrl(): String
|
||||
fun setServerUrl(url: String)
|
||||
}
|
||||
|
||||
class JsBridge(
|
||||
private val deviceWidthPx: Int,
|
||||
private val deviceHeightPx: Int,
|
||||
@@ -35,6 +51,12 @@ class JsBridge(
|
||||
// 通知使用权访问接口(检查/申请授权),供设置页授权项使用
|
||||
// Notification-access provider (check/request) for the settings permission item
|
||||
private val notificationAccess: NotificationAccessProvider? = null,
|
||||
// 系统亮度接口(读取/设置 + WRITE_SETTINGS 授权)
|
||||
// System brightness provider (get/set + WRITE_SETTINGS grant)
|
||||
private val brightness: BrightnessProvider? = null,
|
||||
// 服务器地址存储接口
|
||||
// Server URL storage provider
|
||||
private val serverUrl: ServerUrlProvider? = null,
|
||||
) {
|
||||
private val gson = com.google.gson.Gson()
|
||||
|
||||
@@ -210,6 +232,55 @@ class JsBridge(
|
||||
notificationAccess?.requestAccess()
|
||||
}
|
||||
|
||||
// 返回系统亮度(0-255,未接入返回 -1)
|
||||
// Return system brightness (0-255, -1 when not wired)
|
||||
@android.webkit.JavascriptInterface
|
||||
fun getSystemBrightness(): Int = brightness?.getSystemBrightness() ?: -1
|
||||
|
||||
// 设置系统亮度(0-255)
|
||||
// Set system brightness (0-255)
|
||||
@android.webkit.JavascriptInterface
|
||||
fun setSystemBrightness(value: Int) {
|
||||
brightness?.setSystemBrightness(value)
|
||||
}
|
||||
|
||||
// 是否已授予「修改系统设置」权限(WRITE_SETTINGS)
|
||||
// Whether the WRITE_SETTINGS permission is granted
|
||||
@android.webkit.JavascriptInterface
|
||||
fun canWriteSettings(): Boolean = brightness?.canWriteSettings() ?: false
|
||||
|
||||
// 跳转系统「修改系统设置」授权页
|
||||
// Jump to the system WRITE_SETTINGS grant page
|
||||
@android.webkit.JavascriptInterface
|
||||
fun requestWriteSettings() {
|
||||
brightness?.requestWriteSettings()
|
||||
}
|
||||
|
||||
// 返回 webAPP 服务器地址(未接入返回空字符串)
|
||||
// Return the webAPP server URL (empty string when not wired)
|
||||
@android.webkit.JavascriptInterface
|
||||
fun getServerUrl(): String = serverUrl?.getServerUrl() ?: ""
|
||||
|
||||
// 设置 webAPP 服务器地址(持久化 + 后续拉取使用)
|
||||
// Set the webAPP server URL (persisted and used by subsequent fetches)
|
||||
@android.webkit.JavascriptInterface
|
||||
fun setServerUrl(url: String) {
|
||||
Log.d("HearthBridge", "setServerUrl: $url")
|
||||
serverUrl?.setServerUrl(url)
|
||||
}
|
||||
|
||||
// 重新拉取 webAPP 清单 + 卡片目录,返回 { count }
|
||||
// Re-fetch the webAPP manifest + card catalog, return { count }
|
||||
@android.webkit.JavascriptInterface
|
||||
fun refreshManifest(): String {
|
||||
manifestCache = null
|
||||
val apps = webAppRepository?.fetchManifest() ?: emptyList<WebApp>()
|
||||
if (apps.isNotEmpty()) manifestCache = apps
|
||||
val cards = cardRepository?.fetchCatalog() ?: emptyList<Card>()
|
||||
Log.d("HearthBridge", "refreshManifest: ${apps.size} apps, ${cards.size} cards")
|
||||
return gson.toJson(mapOf("count" to apps.size))
|
||||
}
|
||||
|
||||
// 注册媒体会话监听,回调推送给 H5(info 为 null 时推 "null")
|
||||
// Register media session listener; push callbacks to H5 (push "null" when info is null)
|
||||
fun setMediaListener(source: MediaSessionSource, webView: android.webkit.WebView) {
|
||||
|
||||
Reference in New Issue
Block a user