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:
1 parent
b364b6371a
commit
2826c1e905
27 files changed
+1704
-129
No files matched your search
@@ -0,0 +1,117 @@
|
||||
/* app/reader_conf.c — 阅读器 App 私有配置实现(见 app/reader_conf.h)。 */
|
||||
#include "reader_conf.h"
|
||||
#include "meow_ui.h" /* meow_config_dir() */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* 从 MEOW_DATA_DIR(<TF>/MeowData/<pkg>/data)剥掉尾 "/data",得到 <TF>/MeowData/<pkg>。 */
|
||||
static void strip_data_suffix(const char *d, char *out, int outsz)
|
||||
{
|
||||
if (!d || !d[0]) { strncpy(out, "/tmp", (size_t)outsz - 1); out[outsz - 1] = 0; return; }
|
||||
size_t n = strlen(d);
|
||||
const char *suffix = "/data";
|
||||
size_t sl = strlen(suffix);
|
||||
size_t keep;
|
||||
if (n >= sl && strcmp(d + n - sl, suffix) == 0) keep = n - sl;
|
||||
else keep = n;
|
||||
if (keep >= (size_t)outsz) keep = (size_t)outsz - 1;
|
||||
memcpy(out, d, keep);
|
||||
out[keep] = 0;
|
||||
}
|
||||
|
||||
static void conf_path(char *out, int outsz)
|
||||
{
|
||||
const char *data = meow_config_dir();
|
||||
char base[360];
|
||||
strip_data_suffix(data ? data : "", base, sizeof base);
|
||||
if (snprintf(out, (size_t)outsz, "%s/reader.conf", base) >= outsz) out[0] = 0;
|
||||
/* mkdir -p base */
|
||||
char tmp[400];
|
||||
strncpy(tmp, base, sizeof tmp - 1); tmp[sizeof tmp - 1] = 0;
|
||||
for (char *p = tmp + 1; *p; p++) {
|
||||
if (*p == '/') { *p = 0; mkdir(tmp, 0755); *p = '/'; }
|
||||
}
|
||||
mkdir(tmp, 0755);
|
||||
}
|
||||
|
||||
static void conf_defaults(rdconf *c)
|
||||
{
|
||||
c->fs = 20;
|
||||
c->ls = 130;
|
||||
strcpy(c->bg, "black"); /* B 定案:默认纯黑 */
|
||||
strcpy(c->theme, "auto");
|
||||
strcpy(c->shelf, "list"); /* A 定案:默认 list */
|
||||
c->header = 1;
|
||||
c->footer = 1;
|
||||
c->font[0] = 0;
|
||||
}
|
||||
|
||||
static void clamp_str(char *v, size_t sz)
|
||||
{
|
||||
v[sz - 1] = 0;
|
||||
}
|
||||
|
||||
rdconf *rdconf_get(void)
|
||||
{
|
||||
static rdconf g;
|
||||
static int loaded = 0;
|
||||
if (loaded) return &g;
|
||||
conf_defaults(&g);
|
||||
char path[440];
|
||||
conf_path(path, sizeof path);
|
||||
FILE *f = path[0] ? fopen(path, "r") : NULL;
|
||||
if (f) {
|
||||
char line[512];
|
||||
while (fgets(line, sizeof line, f)) {
|
||||
line[strcspn(line, "\r\n")] = 0;
|
||||
char *eq = strchr(line, '=');
|
||||
if (!eq) continue;
|
||||
*eq = 0;
|
||||
const char *k = line, *v = eq + 1;
|
||||
if (!strcmp(k, "ui.shelf_layout")) { strncpy(g.shelf, v, sizeof g.shelf - 1); g.shelf[sizeof g.shelf - 1] = 0; }
|
||||
else if (!strcmp(k, "rd.fs")) { int t = atoi(v); if (t >= 14 && t <= 40) g.fs = t; }
|
||||
else if (!strcmp(k, "rd.ls")) { int t = atoi(v); if (t >= 100 && t <= 200) g.ls = t; }
|
||||
else if (!strcmp(k, "rd.bg")) { strncpy(g.bg, v, sizeof g.bg - 1); g.bg[sizeof g.bg - 1] = 0; }
|
||||
else if (!strcmp(k, "rd.theme")) { strncpy(g.theme, v, sizeof g.theme - 1); g.theme[sizeof g.theme - 1] = 0; }
|
||||
else if (!strcmp(k, "rd.header")) { g.header = atoi(v) ? 1 : 0; }
|
||||
else if (!strcmp(k, "rd.footer")) { g.footer = atoi(v) ? 1 : 0; }
|
||||
else if (!strcmp(k, "rd.font")) { strncpy(g.font, v, sizeof g.font - 1); g.font[sizeof g.font - 1] = 0; }
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
/* 校验合法取值(越界回默认/回退),避免脏档破坏 UI */
|
||||
if (strcmp(g.shelf, "grid") && strcmp(g.shelf, "list")) strcpy(g.shelf, "list");
|
||||
if (strcmp(g.bg, "black") && strcmp(g.bg, "white") &&
|
||||
strcmp(g.bg, "sepia") && strcmp(g.bg, "auto")) strcpy(g.bg, "black");
|
||||
if (strcmp(g.theme, "light") && strcmp(g.theme, "dark") &&
|
||||
strcmp(g.theme, "auto")) strcpy(g.theme, "auto");
|
||||
clamp_str(g.shelf, sizeof g.shelf);
|
||||
clamp_str(g.bg, sizeof g.bg);
|
||||
clamp_str(g.theme, sizeof g.theme);
|
||||
clamp_str(g.font, sizeof g.font);
|
||||
loaded = 1;
|
||||
return &g;
|
||||
}
|
||||
|
||||
int rdconf_persist(void)
|
||||
{
|
||||
rdconf *c = rdconf_get();
|
||||
char path[440];
|
||||
conf_path(path, sizeof path);
|
||||
if (!path[0]) return -1;
|
||||
FILE *f = fopen(path, "wb");
|
||||
if (!f) return -5;
|
||||
fprintf(f, "ui.shelf_layout=%s\n", c->shelf);
|
||||
fprintf(f, "rd.fs=%d\n", c->fs);
|
||||
fprintf(f, "rd.ls=%d\n", c->ls);
|
||||
fprintf(f, "rd.bg=%s\n", c->bg);
|
||||
fprintf(f, "rd.theme=%s\n", c->theme);
|
||||
fprintf(f, "rd.header=%d\n", c->header);
|
||||
fprintf(f, "rd.footer=%d\n", c->footer);
|
||||
fprintf(f, "rd.font=%s\n", c->font);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user