feat(ncm): 断网保持登录态 + 离线模式(可见提示/缓存可播/联网自动回在线)(M9)
用户报告:「一断网就退出到扫码登录界面,不会保持账号态切离线,缓存列表形同虚设」。 上一条已把失败分成 NETWORK/AUTH;本条把结论落到 App 状态与 UI。 - 会话状态机(appstate.c):只有 NCM_ERR_AUTH(401/403/301/302)清 cookie;网络类失败 (不可达/超时/TLS/5xx/-460)只置 g_st.offline,账号态与 session.enc 一律保留; appstate_ensure_uid 同语义(原先任何 AUTH 都清 cookie,网络故障不得进入该分支)。 - 启动(app.c):根页改由 ncm_session_boot_decide 决定——有本地会话就进 home(无网也是), 只有无本地会话才进扫码;打印 boot 决策日志。 - 离线 UX:首页个人卡「离线模式」红标 + 页脚提示 + 空态「离线模式/可播放已缓存」; 歌单页/搜索页/播放页/缓存页分别给出离线文案(缓存页点播照旧走 NCM_QUEUE_CACHE,本地可播)。 - 恢复:home 可见时每 30s 静默重试一次(强制绕过接口缓存,成功即回在线并重绘); 任何真实网络成功(home/playlist worker)也会清离线态。 - 防误判:接口缓存命中(120s 旧响应)不算「回在线」——home_worker 用 ncm_apicache_hits() 差分识别,避免离线提示被缓存命中闪掉。
This commit is contained in:
1 parent
8557da6fca
commit
707bbd8a02
8 files changed
+111
-10
No files matched your search
@@ -146,6 +146,21 @@ static void home_draw(void *ctx)
|
||||
}
|
||||
meow_ui_text_right(pc.x + pc.w - 16, pc.y + (pc.h - 28) / 2, ">", 28, th->onSurfaceVariant);
|
||||
|
||||
/* M9 离线模式:个人卡右侧可见提示(红点 + 红字,避开「>」)。断网不再退扫码,
|
||||
* 用户能从这一处看出「当前是离线,缓存照常可播」。 */
|
||||
if (appstate_is_offline()) {
|
||||
const char *ol = "离线模式";
|
||||
int osz = th->font_body - 2;
|
||||
if (osz < 16) osz = 16;
|
||||
int ow = meow_ui_text_width(ol, osz);
|
||||
int ox = pc.x + pc.w - 28 - ow;
|
||||
int oy = pc.y + (pc.h - osz) / 2;
|
||||
if (ox > pc.x + asz + 28) {
|
||||
meow_ui_fill_rect(ox - 14, oy + osz / 2 - 3, 6, 6, pa->red);
|
||||
meow_ui_text(ox, oy, ol, osz, pa->red);
|
||||
}
|
||||
}
|
||||
|
||||
/* 双页签(g_tabs=meow_tabbar widget 建)——红下划线/红选中字叠层。 */
|
||||
if (g_tabs) {
|
||||
int iw = r_tabs.w / 2;
|
||||
@@ -201,6 +216,8 @@ static void home_draw_empty(void *ctx)
|
||||
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", "请重新登录");
|
||||
/* M9 离线模式:网络类失败不再是「登录过期」,提示可离线听已缓存。 */
|
||||
else if (appstate_is_offline()) ncm_draw_empty(r_list, "离线模式", "网络不可用 · 可播放已缓存(顶栏「已缓存」)");
|
||||
else if (g_load_err) ncm_draw_empty(r_list, "NETWORK ERROR", "上滑重试");
|
||||
else ncm_draw_empty(r_list, "NO PLAYLISTS", "还没有歌单");
|
||||
}
|
||||
@@ -211,8 +228,9 @@ static void home_draw_footer(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 : "");
|
||||
snprintf(foot, sizeof foot, "共 %d 个歌单 %s%s", g_st.playlist_count,
|
||||
g_st.nickname[0] ? g_st.nickname : "",
|
||||
appstate_is_offline() ? " · 离线模式" : "");
|
||||
ncm_draw_footer(r_cont, foot);
|
||||
}
|
||||
|
||||
@@ -237,6 +255,7 @@ static void *home_worker(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int rc;
|
||||
uint64_t hits0 = ncm_apicache_hits();
|
||||
if (!g_st.logged_in) rc = NCM_ERR_AUTH;
|
||||
else {
|
||||
/* §NEW MUSIC_U 临期续期:先于歌单网络请求(后续 eapi/weapi 用新 cookie)。
|
||||
@@ -247,6 +266,10 @@ static void *home_worker(void *arg)
|
||||
}
|
||||
if (rc == NCM_OK)
|
||||
account_vip_maybe_refresh(0); /* §20:超 1 天/到期后各补查一次(worker 线程,不卡 UI) */
|
||||
/* M9:网络类失败→离线(保留登录态);成功→回在线。但「接口缓存命中」不算回在线——
|
||||
* 离线时读到 120s 内的旧缓存同样返回 NCM_OK,不能据此清掉离线提示/重试节奏。 */
|
||||
int from_cache = (rc == NCM_OK) && (ncm_apicache_hits() != hits0);
|
||||
if (!from_cache) appstate_session_gate(rc);
|
||||
pthread_mutex_lock(&g_home_mu);
|
||||
g_load_err = (g_st.playlist_count > 0) ? 0 : rc; /* 有数据(缓存/已载)即不置错误态 */
|
||||
g_home_loading = 0;
|
||||
@@ -276,7 +299,20 @@ void home_reload(void)
|
||||
|
||||
void home_tick(uint64_t now)
|
||||
{
|
||||
(void)now;
|
||||
/* M9 离线恢复:离线时每 30s 静默重试一次(home worker 单飞;成功后 appstate_session_gate
|
||||
* 自动回在线并重绘)。仅在 home 可见时轮询,不轰炸服务端(风控纪律)。 */
|
||||
static uint64_t g_offline_retry_ms;
|
||||
if (appstate_is_offline() && !g_host_mock) {
|
||||
if (!g_home_thr_on && (!g_offline_retry_ms || now - g_offline_retry_ms >= 30000)) {
|
||||
g_offline_retry_ms = now;
|
||||
meow_log(MEOW_LOG_INFO, "home: offline retry");
|
||||
ncm_api_cache_refresh_path("/api/user/playlist"); /* 离线恢复探测必须真打网络 */
|
||||
home_reload();
|
||||
}
|
||||
} else {
|
||||
g_offline_retry_ms = 0;
|
||||
}
|
||||
|
||||
if (!g_home_thr_on) return;
|
||||
if (g_home_gen == g_home_acked) return;
|
||||
g_home_acked = g_home_gen;
|
||||
|
||||
Reference in new issue
Block a user