feat: M6.40批 — 阅读器UI改版(书架list·grid+空态骨架+界面设置+App设置页+header·footer+背景黑默认) + 系统级音量翻页映射 + P1 MD3(select面板28/对话框按钮胶囊) + MeowPanel写端点护栏 + SDK公开仓·文档同步

- reader: app.c/shelf.c/reader.c 全套UI; 新增 reader_conf(reader.conf)/settings(App设置页)/reader_ipc(音量翻页IPC响应); app.json加volume_page
- launcher: keys.c meow_volpage_*门 + util.c app_id→fd映射(HELLO记fd/断开清) + app_launcher.c 前台三处接线(进入sink/按键路径volpage_key/离开clear) → 前台声明volume_page的App音量键→MSG_KEY_PAGEUP/PAGEDOWN翻页(非阅读器前台音量照旧)
- sdk: meow_select.c 底部面板28 + meow_ui_dialog.c 对话框按钮胶囊(h/2) + test_meow_ui_select.c修采样
- meowpanel: /api/net/policy·/api/power/policy 加防自锁+policy默认关两条护栏(panel.policy_enabled默认0)
- 文档: MEOW_APP_SDK.md §12.6 + meowpanel README端点表

0warning;宿主测试全过;二进制留批量批次未入库
This commit is contained in:
AskaEth committed 2026-09-04 18:13:18 +08:00
1 parent b364b6371a
commit 2826c1e905
27 files changed
+1704 -129

No files matched your search

+49
View File
@@ -907,6 +907,52 @@ int meow_ipc_conn_alive(int fd)
return 0;
}
/* ---- E:系统级音量翻页——app_id→持久 IPC fd 最近活跃映射(util.c 单写者 = ipc_dispatch)----
* App 的「持久连接」(如 reader_app/app/reader_ipc.c 后台线程)连上后发 MSG_HELLO,本映射在该
* HELLO 被 ipc_dispatch 处理时记录 app_id→m->fd;连接关闭(meow_ipc_process 剔除)时清对应项。
* 只记录「declares volume_page」的 App(meow_volpage_app_allows),保持映射极小且无歧义。
* meow_ipc_app_fd() 供 app_launcher.c 前台会话取持久 fd 武装翻页 sink。 */
#define VOLPAGE_FD_MAX 8
static struct { char app_id[MEOW_APP_ID_MAX]; int fd; } g_volpage_fd[VOLPAGE_FD_MAX];
static int g_volpage_fd_n;
static void volpage_fd_set(const char *app_id, int fd)
{
if (!app_id || !app_id[0] || fd < 0) return;
for (int i = 0; i < g_volpage_fd_n; i++) {
if (!strcmp(g_volpage_fd[i].app_id, app_id)) { g_volpage_fd[i].fd = fd; return; }
}
if (g_volpage_fd_n < VOLPAGE_FD_MAX) {
snprintf(g_volpage_fd[g_volpage_fd_n].app_id, sizeof g_volpage_fd[0].app_id, "%s", app_id);
g_volpage_fd[g_volpage_fd_n].fd = fd;
g_volpage_fd_n++;
}
}
static void volpage_fd_clear_fd(int fd)
{
for (int i = 0; i < g_volpage_fd_n; i++) {
if (g_volpage_fd[i].fd == fd) {
for (int j = i; j < g_volpage_fd_n - 1; j++) g_volpage_fd[j] = g_volpage_fd[j + 1];
g_volpage_fd_n--;
return;
}
}
}
int meow_ipc_app_fd(const char *app_id)
{
if (!app_id) return -1;
for (int i = 0; i < g_volpage_fd_n; i++) {
if (!strcmp(g_volpage_fd[i].app_id, app_id)) {
if (meow_ipc_conn_alive(g_volpage_fd[i].fd)) return g_volpage_fd[i].fd;
volpage_fd_clear_fd(g_volpage_fd[i].fd); /* fd 已死:清残留 */
return -1;
}
}
return -1;
}
/* §10.5:待处理的 App 前台「展开通知中心」请求(ipc_dispatch 单写者置位;launch_app waitpid
* 循环 meow_notif_open_take 读取并清除)。仅当 g_app_session_active(App 前台会话)期间才置位,
* 否则回 ERR(无 App 前台,不展开)。 */
@@ -1099,6 +1145,7 @@ static void *ipc_thread(void *arg)
if (ipc_conn_read(cc) < 0) {
logmsg("ipc: conn %d closed", cc->fd);
close(cc->fd);
volpage_fd_clear_fd(cc->fd); /* E:清已断连接的翻页 fd 映射 */
for (int j = i; j < nfds - 1; j++) {
fds[j] = fds[j + 1];
ipc_conns[j - 1] = ipc_conns[j];
@@ -1209,6 +1256,8 @@ static void ipc_dispatch(struct meow_ipc_msg *m)
memcpy(&h, m->payload, m->plen < (uint16_t)sizeof h ? m->plen : (uint16_t)sizeof h);
h.app_id[MEOW_APP_ID_MAX - 1] = 0;
meow_acct_hello(h.app_id, h.version, h.flags);
/* E:记录声明 volume_page 的 App 的持久连接 fd(HELLO=App 侧持久 IPC 连接;仅读卡 app.json 一次)。 */
if (meow_volpage_app_allows(h.app_id)) volpage_fd_set(h.app_id, m->fd);
m_ack_t a;
a.code = MEOW_OK;
a.status = (uint32_t)g_naccts;