diff --git a/webui.go b/webui.go index a307943..a421198 100644 --- a/webui.go +++ b/webui.go @@ -746,8 +746,11 @@ async function refresh(){ }).join(""); var list = document.getElementById("st"); var sig = JSON.stringify(st.streamers); - // 数据没变化不重建;正在列表里操作时也跳过 - if(sig !== stSig && !list.contains(document.activeElement)){ + // 只有「正在列表里的文本框里打字」才跳过重建:下拉和勾选都是改完立即提交的, + // 一直卡着不重建会让「选了自定义该出现的码率框」「录播中的徽标」迟迟不刷新 + var ae = document.activeElement; + var typing = !!(ae && list.contains(ae) && ae.tagName === "INPUT" && ae.type !== "checkbox"); + if(sig !== stSig && !typing){ stSig = sig; // 重建前记下用户改过、还没提交的自定义码率,建完抄回去(填错的不用留) var keepNum = {}; @@ -1289,6 +1292,36 @@ async function delUid(uid){ if(!confirm("确定删除 uid " + uid + " 并停止其录制?")) return; post("/api/streamer/remove", {uid: uid}); } +// 选到「自定义」时当场把码率框建出来:列表在「正在文本框里打字」时不会重建, +// 光等服务端回来是看不到输入框的,用户会以为没地方填。顺带把焦点放进去,直接就能敲数字 +function showBrNum(row, sel, focus){ + var el = row.querySelector("input.brnum"); + if(el){ + if(focus){ el.focus(); el.select(); } + return el; + } + var uid = parseInt(sel.dataset.uid, 10); + var cur = (lastSt && lastSt.streamers ? lastSt.streamers : []).filter(function(s){ return s.uid === uid; })[0]; + el = document.createElement("input"); + el.type = "text"; + el.className = "brnum"; + el.dataset.uid = String(uid); + el.inputMode = "numeric"; + el.placeholder = "Kbps"; + el.title = "自定义:取不超过这个码率的最高档"; + // 初始值:填过自定义就用上次那个数(切走再切回来不该被改掉),没填过就用现在实际在用的那一档, + // 免得切过去的一瞬间变成最低档 + var v = cur ? (cur.bitrate || 0) : 0; + if(!(v > 0) && cur) v = cur.qualityBitrate || 0; + el.value = v; + sel.parentNode.insertBefore(el, sel.nextSibling); + if(focus){ el.focus(); el.select(); } + return el; +} +function hideBrNum(row){ + var el = row.querySelector("input.brnum"); + if(el && el.parentNode) el.parentNode.removeChild(el); +} // 读一行里选的档位:pref 是下拉的值;自定义时把输入框里的码率一起带上, // 输入框不在(刚切到自定义、或不是自定义)就不带 bitrate,服务端会保留原来填的值 function rowQuality(row){ @@ -1302,11 +1335,11 @@ function rowQuality(row){ v = parseInt(num.value.trim(), 10); if(isNaN(v) || v < 0) return null; }else{ - // 刚切到自定义、输入框还没建出来:用「现在实际用到的档位码率」当起点, - // 免得切过去的一瞬间掉到最低档(uid 可能还没设过自定义值) - var uid = parseInt(sel.dataset.uid, 10); - var cur = (lastSt && lastSt.streamers ? lastSt.streamers : []).filter(function(s){ return s.uid === uid; })[0]; - v = cur ? (cur.qualityBitrate || cur.bitrate || 0) : 0; + // 兜底:填过自定义就用上次那个数,没填过就用现在实际在用的那一档 + var uid0 = parseInt(sel.dataset.uid, 10); + var cur0 = (lastSt && lastSt.streamers ? lastSt.streamers : []).filter(function(s){ return s.uid === uid0; })[0]; + v = cur0 ? (cur0.bitrate || 0) : 0; + if(!(v > 0) && cur0) v = cur0.qualityBitrate || 0; } out.bitrate = v; } @@ -1328,6 +1361,9 @@ document.addEventListener("change", async function(e){ // 档位下拉是选完立即生效的(正在录制时会自动换档重录) var uid3 = parseInt(t.dataset.uid, 10); var row3 = t.closest(".row"); + // 选到「自定义」当场把码率框建出来并聚焦,切走就收掉(不依赖列表重建,见 showBrNum) + if(t.value === "custom") showBrNum(row3, t, true); + else hideBrNum(row3); var q3 = rowQuality(row3); if(!q3){ showMsg(false, "自定义档位的码率必须是大于等于 0 的数字"); return; } q3.uid = uid3;