fix chnage mode web

This commit is contained in:
2026-03-06 00:29:16 +03:00
parent 4e171c3d35
commit 19b4efea6b
3 changed files with 24 additions and 12 deletions
+17 -8
View File
@@ -15,6 +15,14 @@ unit WebPageHtml;
- Opus: opQueue буферизует пакеты пока WASM не готов - Opus: opQueue буферизует пакеты пока WASM не готов
- Opus: AudioContext создаётся только по user gesture (оверлей) - Opus: AudioContext создаётся только по user gesture (оверлей)
- SPANS: только 48K..1536K - SPANS: только 48K..1536K
- (Mode fix) modTglBtn теперь отображает ТЕКУЩИЙ активный режим
(LSB/USB, CWL/CWU, AM/SAM, FM), а не следующий. При клике
переключает на парный режим внутри группы.
- (Mode fix) cwBtn удалён — его роль выполняет modTglBtn при CW группе.
- (Mode fix) syncModGrp + updModTglLabel корректно синхронизируют UI
из server state: выпадающий список и кнопка отражают десктоп.
- (Mode fix) modGrpSel.onchange при смене группы сразу отправляет
команду mode с дефолтным режимом группы (LSB, CWL, FM, AM).
} }
{$IFDEF FPC} {$IFDEF FPC}
@@ -140,7 +148,6 @@ begin
'<div id="vDispB" class="vfo-ro dim"></div>' + '<div id="vDispB" class="vfo-ro dim"></div>' +
'</div>' + '</div>' +
'<div class="right-g">' + '<div class="right-g">' +
'<button id="cwBtn">CW</button>' +
'<button id="modTglBtn">LSB</button>' + '<button id="modTglBtn">LSB</button>' +
'<select id="bandSel"></select>' + '<select id="bandSel"></select>' +
'<button id="fnpBtn">FNP</button>' + '<button id="fnpBtn">FNP</button>' +
@@ -181,13 +188,14 @@ begin
'const MODE_N=["LSB","USB","DSB","CWL","CWU","FM","AM","SAM"];' + 'const MODE_N=["LSB","USB","DSB","CWL","CWU","FM","AM","SAM"];' +
'const GRP_MAP={ssb:[0,1],cw:[3,4],fm:[5,5],am:[6,7]};' + 'const GRP_MAP={ssb:[0,1],cw:[3,4],fm:[5,5],am:[6,7]};' +
'const MODE_TO_GRP=["ssb","ssb","ssb","cw","cw","fm","am","am"];' +
'function modGrpFromMode(m){return MODE_TO_GRP[m]||"ssb";}' +
'function modGrp(){return q("modGrpSel").value||"ssb";}' + 'function modGrp(){return q("modGrpSel").value||"ssb";}' +
'function modTglTarget(){const grp=GRP_MAP[modGrp()];const cur_m=cur.mode||0;return(cur_m===grp[0])?grp[1]:grp[0];}' + 'function modTglTarget(){const grp=GRP_MAP[modGrp()];const m=cur.mode||0;return(m===grp[0])?grp[1]:grp[0];}' +
'function updModTglLabel(){const b=q("modTglBtn");if(!b)return;b.textContent=MODE_N[modTglTarget()];}' + 'function updModTglLabel(){const b=q("modTglBtn");if(!b)return;const grp=GRP_MAP[modGrp()];const m=cur.mode||0;const show=(m===grp[0]||m===grp[1])?m:grp[0];b.textContent=MODE_N[show];}' +
'function syncModGrp(m){const g=m<=1?"ssb":m<=4?"cw":m===5?"fm":"am";const s=q("modGrpSel");if(s&&s.value!==g)s.value=g;}' + 'function syncModGrp(m){const g=MODE_TO_GRP[m]||"ssb";const s=q("modGrpSel");if(s&&s.value!==g)s.value=g;updModTglLabel();}' +
'q("modGrpSel").onchange=function(){updModTglLabel();};' + 'q("modGrpSel").onchange=function(){const grp=GRP_MAP[modGrp()];const defaultMode=grp[0];cur.mode=defaultMode;updModTglLabel();pend("mode");ws2({cmd:"mode",mode:defaultMode});};' +
'q("modTglBtn").onclick=function(){audioKick();pend("mode");ws2({cmd:"mode",mode:modTglTarget()});};' + 'q("modTglBtn").onclick=function(){audioKick();const next=modTglTarget();cur.mode=next;updModTglLabel();pend("mode");ws2({cmd:"mode",mode:next});};' +
'q("cwBtn").onclick=function(){audioKick();pend("mode");ws2({cmd:"mode",mode:cur.mode===3?4:3});};' +
'q("agcSel").onchange=function(e){pend("agc");ws2({cmd:"agc",mode:+e.target.value});};' + 'q("agcSel").onchange=function(e){pend("agc");ws2({cmd:"agc",mode:+e.target.value});};' +
'q("volSl").oninput=function(e){ws2({cmd:"volume",v:+e.target.value});var v=q("volVal");if(v)v.textContent=e.target.value;};' + 'q("volSl").oninput=function(e){ws2({cmd:"volume",v:+e.target.value});var v=q("volVal");if(v)v.textContent=e.target.value;};' +
@@ -331,7 +339,8 @@ begin
'if(!isPending("nb"))sw("nbBtn",!!cur.nb);' + 'if(!isPending("nb"))sw("nbBtn",!!cur.nb);' +
'if(!isPending("anf"))sw("anfBtn",!!cur.anf);' + 'if(!isPending("anf"))sw("anfBtn",!!cur.anf);' +
'if(!isPending("run"))updRunBtn(!!cur.running);' + 'if(!isPending("run"))updRunBtn(!!cur.running);' +
'if(!isPending("mode")){syncModGrp(cur.mode||0);updModTglLabel();}' + // syncModGrp syncs dropdown AND calls updModTglLabel internally
'if(!isPending("mode")){syncModGrp(cur.mode||0);}' +
'updBand(cur.vfo_a_hz||0);updSpan(cur.span_hz||192000);' + 'updBand(cur.vfo_a_hz||0);updSpan(cur.span_hz||192000);' +
'paintSM(Number(cur.smeter_dbm||-130));' + 'paintSM(Number(cur.smeter_dbm||-130));' +
'const mn=cur.mode_name||(MODE_N[cur.mode||0]||"?");' + 'const mn=cur.mode_name||(MODE_N[cur.mode||0]||"?");' +
+5 -2
View File
@@ -269,11 +269,14 @@ var
K: string; K: string;
begin begin
Result := ''; Result := '';
K := '"' + Key + '"'; // Ищем "key": — с двоеточием, чтобы не совпасть с "key" внутри значения
// Например в {"cmd":"mode","mode":1} поиск "mode": не найдёт "mode" как значение cmd
K := '"' + Key + '":';
P := System.Pos(K, Json); P := System.Pos(K, Json);
if P = 0 then Exit; if P = 0 then Exit;
Inc(P, Length(K)); Inc(P, Length(K));
while (P <= Length(Json)) and (Json[P] in [' ', ':']) do Inc(P); // Пропускаем пробелы после двоеточия
while (P <= Length(Json)) and (Json[P] = ' ') do Inc(P);
if P > Length(Json) then Exit; if P > Length(Json) then Exit;
if Json[P] = '"' then if Json[P] = '"' then
begin begin
+2 -2
View File
@@ -285,7 +285,7 @@
"span_hz" : 1.9200000000000000E+005 "span_hz" : 1.9200000000000000E+005
}, },
"1" : { "1" : {
"vfo_a" : 3.6400000000000000E+006, "vfo_a" : 3.6210000000000000E+006,
"vfo_b" : 3.7500000000000000E+006, "vfo_b" : 3.7500000000000000E+006,
"mode" : 0, "mode" : 0,
"filter_idx" : 5, "filter_idx" : 5,
@@ -307,7 +307,7 @@
"span_hz" : 1.9200000000000000E+005 "span_hz" : 1.9200000000000000E+005
}, },
"3" : { "3" : {
"vfo_a" : 7.1470000000000000E+006, "vfo_a" : 7.1620000000000000E+006,
"vfo_b" : 7.1000000000000000E+006, "vfo_b" : 7.1000000000000000E+006,
"mode" : 0, "mode" : 0,
"filter_idx" : 5, "filter_idx" : 5,