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
@@ -98,6 +98,7 @@ int appstate_init(void)
|
||||
|
||||
appstate_load_settings();
|
||||
g_st.logged_in = (g_st.ctx.cookie[0] != 0);
|
||||
g_st.offline = 0; /* M9:启动先按在线渲染;首个网络动作失败再进离线(本地会话不被否决) */
|
||||
g_st.active_playlist = -1;
|
||||
g_st.playing_song = -1;
|
||||
g_st.qr_size = 0;
|
||||
@@ -169,6 +170,33 @@ void appstate_set_logged_in(const char *uid, const char *nickname)
|
||||
g_st.logged_in = 1;
|
||||
}
|
||||
|
||||
/* ---- 会话保持 / 离线模式(M9)----
|
||||
* 判定本身在 core(ncm_gate_decide,宿主可单测);这里只把结果落到 App 状态并打日志。
|
||||
* 关键不变量:**只有 NCM_ERR_AUTH 会走退出登录**;传输层/服务端暂不可用只切离线,
|
||||
* 绝不清 cookie(清 cookie 才是「退到扫码登录」的实质)。 */
|
||||
void appstate_offline_set(int on)
|
||||
{
|
||||
int v = on ? 1 : 0;
|
||||
if (g_st.offline == v) return;
|
||||
g_st.offline = v;
|
||||
meow_log(v ? MEOW_LOG_WARN : MEOW_LOG_INFO, "session: %s", v ? "offline" : "online");
|
||||
}
|
||||
|
||||
int appstate_is_offline(void) { return g_st.offline; }
|
||||
|
||||
int appstate_session_gate(int rc)
|
||||
{
|
||||
ncm_gate_t g = ncm_gate_decide(g_st.logged_in, rc);
|
||||
switch (g) {
|
||||
case NCM_GATE_ONLINE: appstate_offline_set(0); break;
|
||||
case NCM_GATE_OFFLINE: appstate_offline_set(1); break;
|
||||
/* RELOGIN:登录态处置由调用方(app.c tick / settings 登出)执行;
|
||||
* HOLD:解析/参数类错误,保持现状。 */
|
||||
default: break;
|
||||
}
|
||||
return (int)g;
|
||||
}
|
||||
|
||||
void appstate_logout(void)
|
||||
{
|
||||
ncm_ctx_clear_cookie(&g_st.ctx);
|
||||
@@ -176,6 +204,7 @@ void appstate_logout(void)
|
||||
* 被下一账号复用;盘缓存目录一并清)。 */
|
||||
ncm_apicache_clear();
|
||||
g_st.logged_in = 0;
|
||||
g_st.offline = 0;
|
||||
g_st.uid[0] = 0;
|
||||
g_st.nickname[0] = 0;
|
||||
g_st.vip = NCM_VIP_NONE; /* §20:登出清会员态(下一账号不继承) */
|
||||
@@ -199,7 +228,9 @@ void appstate_logout(void)
|
||||
cover_cache_reset();
|
||||
}
|
||||
|
||||
/* 若 uid 缺失(cookie 在但没存 uid),用 login_status_check 校验并取回。返回 0=成功。 */
|
||||
/* 若 uid 缺失(cookie 在但没存 uid),用 login_status_check 校验并取回。返回 0=成功。
|
||||
* M9:只有服务端**明确**否定会话(NCM_ERR_AUTH:HTTP 401/403、业务码 301/302)才清 cookie;
|
||||
* 网络不可达/超时/服务端 5xx 一律保留 cookie 与登录态,只切离线模式。 */
|
||||
int appstate_ensure_uid(void)
|
||||
{
|
||||
if (!g_st.logged_in || !g_st.ctx.cookie[0]) return NCM_ERR_AUTH;
|
||||
@@ -209,12 +240,16 @@ int appstate_ensure_uid(void)
|
||||
nick, sizeof nick);
|
||||
if (rc == NCM_OK) {
|
||||
appstate_set_logged_in(uid, nick);
|
||||
appstate_offline_set(0);
|
||||
return NCM_OK;
|
||||
}
|
||||
/* 会话失效:清 cookie → 未登录 */
|
||||
if (rc == NCM_ERR_AUTH) {
|
||||
/* 会话确失效:清 cookie → 未登录(原逻辑) */
|
||||
ncm_ctx_clear_cookie(&g_st.ctx);
|
||||
g_st.logged_in = 0;
|
||||
g_st.offline = 0;
|
||||
} else if (ncm_err_is_network(rc)) {
|
||||
appstate_offline_set(1); /* 只是连不上:保留账号态,离线可看缓存 */
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user