- M7 launcher 重写 5 期(虚拟化宫格/meow_theme 单一权威/横幅动画/自定义 PIN 键盘) - OOM 通用化(cachegov 上收 SDK)、自动切歌根治、meowpanel jv_free 泄漏修复、Hello 滚动卡顿修复 - ncm 歌词 UI / 媒体通知封面 / 封面分辨率 640 - 5 bug 修复:ncm 后台化 UI 叠层+点击穿透、再进 ncm 桌面叠层、播放页新旧 UI 叠层抢刷脏区(meow_ui_gfx 恢复边沿整帧重画)、PIN 亮屏亮度跳(keys.c meow_panel_on 按 settings_brightness_clamped 恢复)、通知中心封面显歌单封面(cover.c save_cover_raw 加 is_song + 命中块守卫) - 四 App 统一重链新 meow_ui.a 51caee4a;M6.19=0.8.19 固件 2d2331f2 推卡自刷验收全绿
434 lines
18 KiB
C
434 lines
18 KiB
C
/* ui/home.c — 我的音乐页(ACT_HOME,根页,已登录)。
|
||
*
|
||
* 网易云风格(NCM_UI_DESIGN §4.2):红系 topbar(标题「我的音乐」+搜索/刷新/设置动作)+
|
||
* 个人区卡片(头像/昵称/ID)+ 双页签「我创建的/我收藏的」(meow_tabbar + 各自 meow_listview)+
|
||
* 组头红条 + 歌单行(rounded card + 红 mini-vinyl 缩略 + 红色按压竖条)。
|
||
*
|
||
* 品牌红走 ncm_palette(g_dark)(App 无权改 SDK MD3 蓝 primary),代码零硬编码散落:
|
||
* 中性色读 meow_theme_get(),红读 ncm_palette()。SDK listview 的 MD3 蓝选中不可改,
|
||
* 故用 MEOW_LIST_SEL_NONE + 自定义红态叠层(§4.2 叠加红条)。
|
||
*
|
||
* 左缘返回 = 退出 App(app.c)。歌单加载后台 worker(home_worker,保留 REPORT §10.11
|
||
* 的异步结构,不回退成同步——P1 启动卡顿已修,勿回退)。
|
||
*/
|
||
#include "../ncm_app_internal.h"
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
#include <pthread.h>
|
||
|
||
typedef struct { meow_view *view; int active; } home_ctrl;
|
||
static home_ctrl g_hc;
|
||
|
||
static meow_widget *g_tb, *g_list, *g_tabs;
|
||
static ncm_rect_t r_cont, r_list, r_tabs, r_group;
|
||
static int g_bg_id, g_draw_id, g_empty_id, g_footer_id;
|
||
static volatile int g_load_err;
|
||
static int g_tab; /* 0=我创建的 1=我收藏的 */
|
||
static int g_press_row, g_press_delta, g_dragging, g_drag_last_y;
|
||
|
||
/* 歌单加载后台 worker(P1:从 UI 线程挪出,gen 代数做完成信号)。 */
|
||
static pthread_mutex_t g_home_mu = PTHREAD_MUTEX_INITIALIZER;
|
||
static pthread_t g_home_thr;
|
||
static int g_home_thr_on;
|
||
static volatile int g_home_gen;
|
||
static int g_home_acked;
|
||
static volatile int g_home_loading;
|
||
|
||
static const char *tab_label(int tab) { return tab ? "我收藏的" : "我创建的"; }
|
||
|
||
/* ---- tab 数据子集(is_collected 过滤)---- */
|
||
static int tab_count(int tab)
|
||
{
|
||
int c = 0;
|
||
for (int i = 0; i < g_st.playlist_count; i++)
|
||
if ((g_st.playlists[i].is_collected != 0) == (tab == 1)) c++;
|
||
return c;
|
||
}
|
||
static int tab_global_idx(int tab, int k)
|
||
{
|
||
int c = 0;
|
||
for (int i = 0; i < g_st.playlist_count; i++)
|
||
if ((g_st.playlists[i].is_collected != 0) == (tab == 1)) {
|
||
if (c == k) return i;
|
||
c++;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
static void home_drag_reset(void)
|
||
{
|
||
g_press_row = -1; g_press_delta = 0; g_dragging = 0; g_drag_last_y = 0;
|
||
}
|
||
|
||
static int home_src2(int idx, meow_list_item *out, void *ctx)
|
||
{
|
||
(void)ctx;
|
||
int gi = tab_global_idx(g_tab, idx);
|
||
if (gi < 0) return 0;
|
||
ncm_playlist_t *pl = &g_st.playlists[gi];
|
||
static char title[128], sub[64];
|
||
snprintf(title, sizeof title, "%s", pl->name);
|
||
snprintf(sub, sizeof sub, "%d 首", pl->track_count);
|
||
out->icon_kind = MEOW_LIST_ICON_NONE; /* 图标槽由红 overlays 画迷你黑胶 */
|
||
out->title = title;
|
||
out->subtitle = sub;
|
||
out->right = MEOW_LIST_RIGHT_ARROW;
|
||
out->on = 0; out->enabled = 1;
|
||
return 1;
|
||
}
|
||
|
||
/* ---- 歌单行 rounded card 背景(z=5,画在 listview 文本之下)---- */
|
||
static void home_row_bg(void *ctx)
|
||
{
|
||
(void)ctx;
|
||
if (meow_ui_activity_active() != ACT_HOME) return;
|
||
if (g_load_err != 0 || g_st.playlist_count == 0) return;
|
||
const meow_theme *th = meow_theme_get();
|
||
int item = APP_ROW_H;
|
||
int off = meow_listview_scroll(g_list);
|
||
int first = off / item, last = (off + r_list.h) / item + 1;
|
||
int n = tab_count(g_tab);
|
||
if (last > n) last = n;
|
||
for (int i = first; i < last; i++) {
|
||
int ry = r_list.y + (i * item - off) + 1, th2 = item - 2;
|
||
if (ry < r_list.y || ry + th2 > r_list.y + r_list.h) continue; /* 只画完整落在视口内的行 */
|
||
ncm_fill_round(r_list.x, ry, r_list.w, th2, 12, th->surfaceContainer);
|
||
}
|
||
}
|
||
|
||
/* ---- 主绘制(z=60):个人卡/组头红条/tab 红态/行缩略与按压红条,>listview 红态叠层 ---- */
|
||
static void home_draw(void *ctx)
|
||
{
|
||
(void)ctx;
|
||
if (meow_ui_activity_active() != ACT_HOME) return;
|
||
const meow_theme *th = meow_theme_get();
|
||
const ncm_pal_t *pa = ncm_palette(g_dark);
|
||
int w = r_cont.w;
|
||
|
||
/* 个人区·卡片(16, y0, w-32, 72):圆角 16 surfaceContainer。 */
|
||
ncm_rect_t pc = NR(16, r_cont.y + 8, w - 32, 72);
|
||
ncm_fill_round(pc.x, pc.y, pc.w, pc.h, 16, th->surfaceContainer);
|
||
int asz = 40, ax = pc.x + 16, acy = pc.y + (pc.h - asz) / 2;
|
||
ncm_fill_round(ax, acy, asz, asz, asz / 2, pa->red_ctr); /* 圆形头像底 */
|
||
char glyph[8];
|
||
int gn = first_glyph(g_st.nickname, glyph, sizeof glyph);
|
||
if (!gn) snprintf(glyph, sizeof glyph, "\u266a"); /* ♪ 无昵称占位 */
|
||
meow_ui_text_center(ax + asz / 2, acy + (asz - th->font_body) / 2, glyph, th->font_body, pa->red);
|
||
char idtxt[64];
|
||
snprintf(idtxt, sizeof idtxt, "ID: %s", g_st.uid[0] ? g_st.uid : "-");
|
||
meow_ui_text(pc.x + asz + 28, pc.y + 6, g_st.nickname[0] ? g_st.nickname : "我的歌单",
|
||
th->font_body, th->onSurface);
|
||
meow_ui_text(pc.x + asz + 28, pc.y + 6 + th->font_body + 4, idtxt, th->font_body, th->onSurfaceVariant);
|
||
/* §22 会员等级小字:account_vip() 枚举(用户语义 0=无 / 1=畅听会员 / 2=黑胶 VIP /
|
||
* 3=超级会员);昵称右侧画小红徽章(red_ctr 底 + 红字),无会员则不画。 */
|
||
{
|
||
int vip = account_vip();
|
||
if (vip != NCM_VIP_NONE) {
|
||
const char *vip_lab = (vip == NCM_VIP_CVIP) ? "畅听会员"
|
||
: (vip == NCM_VIP_SVIP) ? "黑胶 VIP"
|
||
: (vip == NCM_VIP_SUPER) ? "超级会员" : "";
|
||
const char *nm = g_st.nickname[0] ? g_st.nickname : "我的歌单";
|
||
int nmw = meow_ui_text_width(nm, th->font_body);
|
||
int bs = th->font_body - 2; /* 徽章字号略小 */
|
||
if (bs < 16) bs = 16;
|
||
int bw = meow_ui_text_width(vip_lab, bs) + 12;
|
||
int bx = pc.x + asz + 28 + nmw + 8;
|
||
int by = pc.y + 6 + (th->font_body - (bs + 4)) / 2;
|
||
if (bx + bw <= pc.x + pc.w - 24) { /* 不越卡片右缘(避开“>”) */
|
||
ncm_fill_round(bx, by, bw, bs + 4, 6, pa->red_ctr);
|
||
meow_ui_text_center(bx + bw / 2, by + 2, vip_lab, bs, pa->red);
|
||
}
|
||
}
|
||
}
|
||
meow_ui_text_right(pc.x + pc.w - 16, pc.y + (pc.h - 28) / 2, ">", 28, th->onSurfaceVariant);
|
||
|
||
/* 双页签(g_tabs=meow_tabbar widget 建)——红下划线/红选中字叠层。 */
|
||
if (g_tabs) {
|
||
int iw = r_tabs.w / 2;
|
||
int ay = r_tabs.y + (r_tabs.h - meow_ui_text_height(th->font_body)) / 2;
|
||
meow_ui_fill_rect(r_tabs.x + g_tab * iw, r_tabs.y + r_tabs.h - 2, iw, 2, pa->red);
|
||
meow_ui_text_center(r_tabs.x + g_tab * iw + iw / 2, ay, tab_label(g_tab), th->font_body, pa->red);
|
||
}
|
||
|
||
/* 组头红条(red_ctr 底 + 红字 + 红侧条)。 */
|
||
ncm_fill_round(r_group.x, r_group.y, r_group.w, r_group.h, 8, pa->red_ctr);
|
||
meow_ui_fill_rect(r_group.x, r_group.y + 4, 4, r_group.h - 8, pa->red);
|
||
char ght[64];
|
||
snprintf(ght, sizeof ght, "%s / %d 个", tab_label(g_tab), tab_count(g_tab));
|
||
meow_ui_text(r_group.x + 16, r_group.y + (r_group.h - th->font_body) / 2,
|
||
ght, th->font_body, pa->red);
|
||
meow_ui_text_right(r_group.x + r_group.w - 16, r_group.y + (r_group.h - th->font_body) / 2,
|
||
"+ 新建", th->font_body, pa->red);
|
||
|
||
/* 歌单行:红 mini-vinyl 缩略 + 按压红条(文本由 listview 画在 z=10)。 */
|
||
if (g_load_err == 0 && g_st.playlist_count > 0) {
|
||
int item = APP_ROW_H;
|
||
int off = meow_listview_scroll(g_list);
|
||
int isz = 24;
|
||
int first = off / item, last = (off + r_list.h) / item + 1;
|
||
int n = tab_count(g_tab);
|
||
if (last > n) last = n;
|
||
for (int i = first; i < last; i++) {
|
||
int ry = r_list.y + (i * item - off) + 1, th2 = item - 2;
|
||
if (ry < r_list.y || ry + th2 > r_list.y + r_list.h) continue;
|
||
int icy = ry + (item - isz) / 2;
|
||
int bx = r_list.x + 16;
|
||
ncm_fill_round(bx, icy, isz, isz, 6, pa->red);
|
||
meow_ui_fill_rect(bx + isz / 2 - 2, icy + isz / 2 - 2, 4, 4, pa->on_red); /* 盘芯 */
|
||
if (g_press_row == i) {
|
||
meow_ui_fill_rect(r_list.x, ry, 4, item - 2, pa->red);
|
||
meow_ui_fill_rect_alpha(r_list.x, ry, r_list.w, item - 2, pa->red, 26);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 空态 / 错误 / LOADING。 */
|
||
static void home_draw_empty(void *ctx)
|
||
{
|
||
(void)ctx;
|
||
if (meow_ui_activity_active() != ACT_HOME) return;
|
||
if (g_st.playlist_count != 0) return; /* 有数据(缓存/已载)即显示列表,后台刷新失败不置空 */
|
||
if (g_home_loading) { ncm_draw_empty(r_list, "LOADING", "正在加载歌单..."); return; }
|
||
if (g_st.logged_in == 0) ncm_draw_empty(r_list, "NOT SIGNED IN", "请先登录");
|
||
else if (g_load_err == NCM_ERR_AUTH) ncm_draw_empty(r_list, "SESSION EXPIRED", "请重新登录");
|
||
else if (g_load_err) ncm_draw_empty(r_list, "NETWORK ERROR", "上滑重试");
|
||
else ncm_draw_empty(r_list, "NO PLAYLISTS", "还没有歌单");
|
||
}
|
||
|
||
static void home_draw_footer(void *ctx)
|
||
{
|
||
(void)ctx;
|
||
if (meow_ui_activity_active() != ACT_HOME) return;
|
||
if (g_load_err != 0) return;
|
||
char foot[192];
|
||
snprintf(foot, sizeof foot, "共 %d 个歌单 %s", g_st.playlist_count,
|
||
g_st.nickname[0] ? g_st.nickname : "");
|
||
ncm_draw_footer(r_cont, foot);
|
||
}
|
||
|
||
/* 把当前 tab 子集刷进列表 + 重绘(UI 线程)。 */
|
||
static void home_apply(void)
|
||
{
|
||
if (g_list) {
|
||
meow_listview_set_count(g_list, tab_count(g_tab));
|
||
meow_listview_set_scroll(g_list, 0);
|
||
meow_listview_set_sel(g_list, -1);
|
||
}
|
||
if (g_tabs) meow_tabbar_set_selected(g_tabs, g_tab);
|
||
const meow_theme *th = meow_theme_get();
|
||
meow_ui_set_page_bg(th->bg);
|
||
meow_ui_paint_full();
|
||
}
|
||
|
||
/* 后台 worker:唯一走网络的地方(ensure_uid + user_playlist)。
|
||
* §26 stale-while-revalidate:网络成功 → appstate_load_playlists 覆写盘缓存 + 更新内存;
|
||
* 失败但有缓存在展示 → 保持缓存列表(g_load_err=0),后台静默不打断(断网可离线浏览)。 */
|
||
static void *home_worker(void *arg)
|
||
{
|
||
(void)arg;
|
||
int rc;
|
||
if (!g_st.logged_in) rc = NCM_ERR_AUTH;
|
||
else {
|
||
/* §NEW MUSIC_U 临期续期:先于歌单网络请求(后续 eapi/weapi 用新 cookie)。
|
||
* AUTH=会话确失效(置回登录页标志,UI 线程消费);瞬断=保持旧 cookie 走缓存/旧会话。 */
|
||
int crc = account_cookie_maybe_refresh();
|
||
if (crc == NCM_ERR_AUTH) rc = NCM_ERR_AUTH;
|
||
else rc = appstate_load_playlists();
|
||
}
|
||
if (rc == NCM_OK)
|
||
account_vip_maybe_refresh(0); /* §20:超 1 天/到期后各补查一次(worker 线程,不卡 UI) */
|
||
pthread_mutex_lock(&g_home_mu);
|
||
g_load_err = (g_st.playlist_count > 0) ? 0 : rc; /* 有数据(缓存/已载)即不置错误态 */
|
||
g_home_loading = 0;
|
||
g_home_gen++;
|
||
pthread_mutex_unlock(&g_home_mu);
|
||
return NULL;
|
||
}
|
||
|
||
void home_reload(void)
|
||
{
|
||
if (g_host_mock) { g_load_err = 0; home_apply(); return; }
|
||
if (g_home_thr_on) return;
|
||
/* §26:进首页先用磁盘缓存秒渲染(若有),后台 worker 静默刷新;无缓存才显示 LOADING。 */
|
||
int64_t ts = 0;
|
||
int had_cache = (appstate_playlists_cache_load(&ts) == NCM_OK && g_st.playlist_count > 0);
|
||
g_load_err = 0;
|
||
if (!had_cache) {
|
||
g_st.playlist_count = 0; /* 无缓存 → LOADING 空态 */
|
||
g_home_loading = 1;
|
||
}
|
||
g_home_thr_on = 1;
|
||
if (ncm_thread_create(&g_home_thr, home_worker, NULL) != 0) {
|
||
g_home_thr_on = 0; g_home_loading = 0; g_load_err = NCM_ERR_IO;
|
||
}
|
||
home_apply();
|
||
}
|
||
|
||
void home_tick(uint64_t now)
|
||
{
|
||
(void)now;
|
||
if (!g_home_thr_on) return;
|
||
if (g_home_gen == g_home_acked) return;
|
||
g_home_acked = g_home_gen;
|
||
g_home_thr_on = 0;
|
||
g_home_loading = 0;
|
||
home_apply();
|
||
}
|
||
|
||
int home_is_active(void) { return g_hc.active; }
|
||
|
||
int home_on_tap(int x, int y)
|
||
{
|
||
if (g_tb) {
|
||
int ah = meow_topappbar_hit(g_tb, x, y);
|
||
if (ah == MEOW_TOPBAR_BACK) { home_drag_reset(); return 1; }
|
||
if (ah == 0) { /* 刷新 */
|
||
home_drag_reset();
|
||
ncm_api_cache_refresh_path("/api/user/playlist"); /* 手动刷新绕过接口缓存 */
|
||
home_reload();
|
||
return 1;
|
||
}
|
||
if (ah == 1) { home_drag_reset(); settings_open(); return 1; } /* 设置 */
|
||
if (ah >= 2) { home_drag_reset(); search_open(); return 1; } /* 搜索(最右) */
|
||
}
|
||
if (g_tabs && meow_widget_hit(g_tabs, x, y)) {
|
||
int t = meow_tabbar_hit(g_tabs, x, y);
|
||
if (t >= 0 && t != g_tab) { g_tab = t; home_drag_reset(); home_apply(); }
|
||
return 1;
|
||
}
|
||
if (g_load_err != 0 || g_st.playlist_count == 0) return 0;
|
||
if (meow_widget_hit(g_list, x, y)) {
|
||
/* 误触修复(同 playlist.c):小拖动滚动列表后 release 被 SDK 判成 TAP,旧命中用“释放点 +
|
||
* 新 scroll”,打到非按下行;改用按下行 g_press_row,移动超阈值(>10)视为滚动不触发。 */
|
||
int was_drag = (g_press_delta > 10);
|
||
int row = (g_press_row >= 0) ? g_press_row : meow_listview_hit(g_list, x, y);
|
||
home_drag_reset();
|
||
if (row < 0 || was_drag) return 1;
|
||
playlist_open(tab_global_idx(g_tab, row));
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
void home_touch_down(int x, int y)
|
||
{
|
||
home_drag_reset();
|
||
if (g_load_err != 0 || g_st.playlist_count == 0) return;
|
||
if (meow_widget_hit(g_list, x, y)) {
|
||
int row = meow_listview_hit(g_list, x, y);
|
||
if (row >= 0) g_press_row = row;
|
||
g_dragging = 1; g_drag_last_y = y;
|
||
meow_ui_invalidate(r_list.x, r_list.y, r_list.w, r_list.h);
|
||
}
|
||
}
|
||
|
||
void home_touch_move(int x, int y)
|
||
{
|
||
(void)x;
|
||
if (!g_dragging) return;
|
||
if (g_press_row >= 0) {
|
||
int d = y - g_drag_last_y; if (d < 0) d = -d;
|
||
g_press_delta += d;
|
||
if (g_press_delta > 10) g_press_row = -1;
|
||
}
|
||
int dy = y - g_drag_last_y; g_drag_last_y = y;
|
||
if (dy == 0) return;
|
||
int before = meow_listview_scroll(g_list);
|
||
meow_listview_scroll_by(g_list, -dy);
|
||
if (meow_listview_scroll(g_list) != before)
|
||
meow_ui_invalidate(r_list.x, r_list.y, r_list.w, r_list.h);
|
||
}
|
||
|
||
void home_swipe(int dir, int dist)
|
||
{
|
||
if (dir != MEOW_SWIPE_UP && dir != MEOW_SWIPE_DOWN) return;
|
||
if (g_load_err != 0 || g_st.playlist_count == 0) return;
|
||
int del = (dir == MEOW_SWIPE_UP) ? dist : -dist;
|
||
int before = meow_listview_scroll(g_list);
|
||
meow_listview_scroll_by(g_list, del);
|
||
if (meow_listview_scroll(g_list) != before)
|
||
meow_ui_invalidate(r_list.x, r_list.y, r_list.w, r_list.h);
|
||
}
|
||
|
||
/* 生命周期 */
|
||
static void home_page_create(meow_view *v, void *ctx)
|
||
{
|
||
(void)v;
|
||
((home_ctrl *)ctx)->view = v;
|
||
r_cont = ncm_content_rect();
|
||
ncm_rect_t pc = NR(16, r_cont.y + 8, r_cont.w - 32, 72);
|
||
r_tabs = NR(16, pc.y + pc.h + 8, r_cont.w - 32, 48);
|
||
r_group = NR(16, r_tabs.y + r_tabs.h + 4, r_cont.w - 32, 36);
|
||
r_list = NR(16, r_group.y + r_group.h + 8, r_cont.w - 32,
|
||
r_cont.y + r_cont.h - APP_FOOTER_H - (r_group.y + r_group.h + 8));
|
||
if (r_list.h < 0) r_list.h = 0;
|
||
meow_ui_activity_push(ACT_HOME); /* owner=ACT_HOME */
|
||
g_tb = ncm_topbar_create("我的音乐", 0, "\xe2\x86\xbb"); /* 刷新(动作0) */
|
||
meow_topappbar_add_action(g_tb, "\xe2\x9a\x99"); /* 设置(动作1) */
|
||
meow_topappbar_add_action(g_tb, "\xe2\x8c\x95"); /* 搜索(动作2, 最右) */
|
||
/* §307 topbar 图标迁移:三位码点(↻ ⚙ ⌕)在 4k 字库缺字形渲染成豆腐(WORK_STATE 310 前置
|
||
* 症状①),改为 sb_icons 位图(Material Symbols Rounded,字符标签仅作占位,绘制走位图)。 */
|
||
meow_topappbar_set_item_icon(g_tb, 0, MEOW_ICON_REFRESH);
|
||
meow_topappbar_set_item_icon(g_tb, 1, MEOW_ICON_SETTINGS);
|
||
meow_topappbar_set_item_icon(g_tb, 2, MEOW_ICON_SEARCH);
|
||
g_tabs = meow_tabbar_create(r_tabs.x, r_tabs.y, r_tabs.w, r_tabs.h);
|
||
meow_tabbar_add_tab(g_tabs, tab_label(0));
|
||
meow_tabbar_add_tab(g_tabs, tab_label(1));
|
||
meow_tabbar_set_selected(g_tabs, 0);
|
||
g_list = meow_listview_create(r_list.x, r_list.y, r_list.w, r_list.h, 0,
|
||
home_src2, NULL, MEOW_LIST_SEL_NONE);
|
||
meow_listview_set_item_h(g_list, APP_ROW_H);
|
||
meow_ui_activity_pop();
|
||
/* 显式 z:行卡片(5) < listview(10) < tabbar(20) < 红态叠层(60) < topbar(999) */
|
||
meow_widget_set_z(g_list, 10);
|
||
meow_widget_set_z(g_tabs, 20);
|
||
g_bg_id = meow_draw_custom_register(5, r_list.x, r_list.y, r_list.w, r_list.h, home_row_bg, NULL);
|
||
g_draw_id = meow_draw_custom_register(60, r_cont.x, r_cont.y, r_cont.w, r_cont.h,
|
||
home_draw, NULL);
|
||
g_empty_id = meow_draw_custom_register(1, r_list.x, r_list.y, r_list.w, r_list.h,
|
||
home_draw_empty, NULL);
|
||
g_footer_id = meow_draw_custom_register(1, r_cont.x, r_cont.y + r_cont.h - APP_FOOTER_H,
|
||
r_cont.w, APP_FOOTER_H, home_draw_footer, NULL);
|
||
home_drag_reset();
|
||
}
|
||
|
||
static void home_page_enter(meow_view *v, void *ctx)
|
||
{
|
||
(void)v;
|
||
((home_ctrl *)ctx)->active = 1;
|
||
const meow_theme *th = meow_theme_get();
|
||
meow_ui_set_page_bg(th->bg);
|
||
home_reload();
|
||
}
|
||
|
||
static void home_page_leave(meow_view *v, void *ctx)
|
||
{
|
||
(void)v;
|
||
((home_ctrl *)ctx)->active = 0;
|
||
}
|
||
|
||
static void home_page_destroy(meow_view *v, void *ctx)
|
||
{
|
||
(void)v; (void)ctx;
|
||
if (g_bg_id) { meow_draw_unregister(g_bg_id); g_bg_id = 0; }
|
||
if (g_draw_id) { meow_draw_unregister(g_draw_id); g_draw_id = 0; }
|
||
if (g_empty_id) { meow_draw_unregister(g_empty_id); g_empty_id = 0; }
|
||
if (g_footer_id){ meow_draw_unregister(g_footer_id);g_footer_id = 0; }
|
||
if (g_list) { meow_widget_free(g_list); g_list = NULL; }
|
||
if (g_tabs) { meow_widget_free(g_tabs); g_tabs = NULL; }
|
||
if (g_tb) { meow_widget_free(g_tb); g_tb = NULL; }
|
||
}
|
||
|
||
meow_view *home_view_create(void)
|
||
{
|
||
static const meow_view_hooks h = {
|
||
.on_create = home_page_create,
|
||
.on_enter = home_page_enter,
|
||
.on_leave = home_page_leave,
|
||
.on_destroy = home_page_destroy,
|
||
};
|
||
return meow_view_create(ACT_HOME, MEOW_VIEW_ACTIVITY, &h, &g_hc);
|
||
}
|