From c82418f8468f5a8210a183d86fda48781b2603e6 Mon Sep 17 00:00:00 2001
From: AskaEth
Date: Sun, 16 Aug 2026 20:00:26 +0800
Subject: [PATCH] feat: bundle demo webapp in apk
---
app/src/main/assets/webapps/demo/index.html | 58 +++++++++++++++++++
.../yeij/hearth/webapp/WebAppRepository.kt | 32 ++++++++--
2 files changed, 85 insertions(+), 5 deletions(-)
create mode 100644 app/src/main/assets/webapps/demo/index.html
diff --git a/app/src/main/assets/webapps/demo/index.html b/app/src/main/assets/webapps/demo/index.html
new file mode 100644
index 0000000..1d9acf5
--- /dev/null
+++ b/app/src/main/assets/webapps/demo/index.html
@@ -0,0 +1,58 @@
+
+
+
+
+
+示例应用
+
+
+
+
🎨
+ 示例应用
+
+
来源Hearth 内置
+
当前时间--:--:--
+
+ 这是打包在 Hearth APK 内的示例 webapp
用于演示 webAPP 打开 / 顶栏导航 / 多标签
+
+
+
diff --git a/app/src/main/java/top/yeij/hearth/webapp/WebAppRepository.kt b/app/src/main/java/top/yeij/hearth/webapp/WebAppRepository.kt
index 8cd8e6b..1ed37ff 100644
--- a/app/src/main/java/top/yeij/hearth/webapp/WebAppRepository.kt
+++ b/app/src/main/java/top/yeij/hearth/webapp/WebAppRepository.kt
@@ -44,15 +44,37 @@ class WebAppRepository(
// 先解析、成功才缓存,避免畸形 body 或空结果被永久缓存
// Parse first, cache only on success (never cache malformed/empty bodies)
val apps = parse(body)
- if (apps != null) {
+ if (apps != null && apps.isNotEmpty()) {
cache.save(KEY, body)
return apps
}
- Log.w(TAG, "fetchManifest: invalid body, not cached")
- return emptyList()
+ Log.w(TAG, "fetchManifest: invalid/empty body, not cached")
+ return builtinWebApps()
}
- val cached = cache.load(KEY) ?: return emptyList()
- return parse(cached) ?: emptyList()
+ val cached = cache.load(KEY)
+ if (cached != null) {
+ val apps = parse(cached)
+ if (apps != null && apps.isNotEmpty()) return apps
+ }
+ // 无远程清单:返回内置示例 webapp,保证列表不为空、可演示
+ // No remote manifest: return the builtin demo webapp so the list is non-empty
+ return builtinWebApps()
+ }
+
+ // 内置示例 webapp(打包在 assets 内,无需服务器)
+ // Builtin demo webapp (bundled in assets, no server required)
+ private fun builtinWebApps(): List {
+ return listOf(
+ WebApp(
+ id = "demo",
+ name = "示例应用",
+ icon = "data:image/svg+xml;utf8," +
+ "",
+ url = "file:///android_asset/webapps/demo/index.html",
+ )
+ )
}
// 解析清单 JSON;畸形 JSON 或缺少 apps 字段返回 null(调用方决定回退)