feat: card repository and home three-column layout
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
package top.yeij.hearth.card
|
||||
|
||||
import android.util.Log
|
||||
import com.google.gson.Gson
|
||||
import top.yeij.hearth.cache.CacheManager
|
||||
import top.yeij.hearth.webapp.HttpClient
|
||||
|
||||
// 首页卡片条目:id 唯一标识,priority 数字小者排前,entry 为卡片渲染入口
|
||||
// Home card entry: id is the unique key, smaller priority comes first, entry is the render entry point
|
||||
data class Card(val id: String, val name: String, val priority: Int, val entry: String)
|
||||
|
||||
// 卡片目录仓库:拉取成功缓存并解析,失败回退缓存,无目录/无缓存返回内置 time 卡
|
||||
// Card catalog repository: cache+parse on success, fall back to cache on failure,
|
||||
// return builtin time card when there is no catalog or no cache
|
||||
class CardRepository(
|
||||
private val http: HttpClient,
|
||||
private val cache: CacheManager,
|
||||
private val catalogUrl: String,
|
||||
) {
|
||||
private val gson = Gson()
|
||||
|
||||
fun fetchCatalog(): List<Card> {
|
||||
val body = http.get(catalogUrl)
|
||||
if (body != null) {
|
||||
cache.save(KEY, body)
|
||||
Log.d(TAG, "fetchCatalog: fetched ${body.length} bytes from network")
|
||||
return parse(body)
|
||||
}
|
||||
val cached = cache.load(KEY)
|
||||
if (cached != null) {
|
||||
Log.d(TAG, "fetchCatalog: network failed, using cache")
|
||||
return parse(cached)
|
||||
}
|
||||
Log.d(TAG, "fetchCatalog: no network and no cache, return builtin time card")
|
||||
return builtin()
|
||||
}
|
||||
|
||||
// 解析目录 JSON:{ "cards": [ {id,name,priority,entry} ] },字段缺失/非法时跳过该项
|
||||
// Parse catalog JSON; skip malformed or missing-field entries
|
||||
private fun parse(body: String): List<Card> {
|
||||
val root = gson.fromJson(body, Map::class.java)
|
||||
val list = root["cards"] as? List<*> ?: return builtin()
|
||||
val parsed = list.mapNotNull { m ->
|
||||
val map = m as? Map<*, *> ?: return@mapNotNull null
|
||||
val id = map["id"] as? String ?: return@mapNotNull null
|
||||
val name = map["name"] as? String ?: return@mapNotNull null
|
||||
val priority = (map["priority"] as? Number)?.toInt() ?: return@mapNotNull null
|
||||
val entry = map["entry"] as? String ?: return@mapNotNull null
|
||||
Card(id, name, priority, entry)
|
||||
}
|
||||
// 内置 time 卡始终保留(追加在目录卡之后)
|
||||
// builtin time card is always kept (appended after catalog cards)
|
||||
return parsed + builtin()
|
||||
}
|
||||
|
||||
// 内置卡:大字时间卡 priority 0,无目录时兜底
|
||||
// Builtin card: big time card at priority 0, fallback when no catalog
|
||||
private fun builtin(): List<Card> = listOf(Card("time", "大字时间", 0, "cards/time-card.html"))
|
||||
|
||||
companion object {
|
||||
private const val TAG = "HearthCard"
|
||||
private const val KEY = "card-catalog"
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package top.yeij.hearth.webview
|
||||
|
||||
import android.util.Log
|
||||
import top.yeij.hearth.app.AppRepository
|
||||
import top.yeij.hearth.card.Card
|
||||
import top.yeij.hearth.card.CardRepository
|
||||
import top.yeij.hearth.webapp.WebApp
|
||||
import top.yeij.hearth.webapp.WebAppRepository
|
||||
|
||||
@@ -12,6 +14,7 @@ class JsBridge(
|
||||
private val darkMode: Boolean,
|
||||
private val appRepository: AppRepository? = null,
|
||||
private val webAppRepository: WebAppRepository? = null,
|
||||
private val cardRepository: CardRepository? = null,
|
||||
) {
|
||||
private val gson = com.google.gson.Gson()
|
||||
|
||||
@@ -42,4 +45,14 @@ class JsBridge(
|
||||
// Return the H5 web app manifest JSON (empty array when no repository wired)
|
||||
@android.webkit.JavascriptInterface
|
||||
fun fetchWebApps(): String = gson.toJson(webAppRepository?.fetchManifest() ?: emptyList<WebApp>())
|
||||
|
||||
// 返回首页卡片目录 JSON(无仓库时返回空数组;有仓库时由 fetchCatalog 保证内置 time 卡)
|
||||
// Return the home card catalog JSON (empty array when no repository wired;
|
||||
// fetchCatalog guarantees the builtin time card when wired)
|
||||
@android.webkit.JavascriptInterface
|
||||
fun fetchCards(): String {
|
||||
val cards = cardRepository?.fetchCatalog() ?: emptyList<Card>()
|
||||
Log.d("HearthBridge", "fetchCards: ${cards.size} cards")
|
||||
return gson.toJson(cards)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user