luci-app-usteer: per-SSID settings tabs and known-station tracking - #8869
luci-app-usteer: per-SSID settings tabs and known-station tracking#8869grzegorz914 wants to merge 2 commits into
Conversation
279269a to
ff4374e
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the two new commits (per-SSID settings UI + translation refresh). The backend dependency (openwrt/usteer#22) is disclosed in the PR body, so the new UCI options / delete_known ubus call are not flagged as frontend-only. Both commit messages match their diffs. Two inline questions about the per-SSID section handling below.
Generated by Claude Code
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the two new commits since ff4374e (aab5f29 lazy per-SSID section creation + collision-free ids, 18f43f1 re-nest SSID tabs after every render). Both previous inline findings are addressed. The lazy-write approach checks out against form.js/uci.js: uci.set() is indeed a no-op on a section that doesn't exist yet, so creating the section inside the write() wrapper rather than at render time is the right hook, and AbstractValue.write() honours ucisection, so the wrapper lands in the correct section.
One follow-on issue with the collision fix and two nits inline.
Commit checks
- 18f43f1 "luci-app-usteer: re-nest SSID tabs after every render, not just the first" — the body's claim "Pre-existing bug, not introduced by the per-SSID tabs commit itself (reproduced on an older build too)" doesn't hold against this tree:
master(96a255d) has no tab-relocation code inusteer.jsat all — nodata-tabDOM manipulation, noknowndevicestab, norelocateSsidTabsequivalent. All of it is added by cd58ab1 in this same PR, so this is fixing a bug introduced two commits earlier in the series, not a pre-existing one. Worth rewording (or dropping the sentence) so the history doesn't mislead someone bisecting later.
Generated by Claude Code
18f43f1 to
cae4bcd
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the new work since 18f43f1. The branch was force-pushed: e1488b2 squashes the previously reviewed cd58ab1 + aab5f29 + 18f43f1 together with this round's ssidSectionId() fixes, cae4bcd carries the i18n, and 2a5c682 + 1443c8e are genuinely new. All four commit messages match their diffs, so no Commit checks section.
The ssidSectionId() rework addresses the previous round's findings correctly — ids are now resolved from each existing usteer_ssid section's own ssid option before any allocation, usedSsidSectionIds is seeded from the existing section names, and both maps are Object.create(null). uci.load('usteer') is part of load(), so uci.sections() has real data by the time render() calls ssidSectionId(). The known_stations_timeout o.default = '0' removal is right: renderWidget() seeds the input with this.default when cfgvalue is null, which is what was pre-filling a literal 0 over the placeholder.
The band steering toggle itself behaves as the commit message describes — with default = '1' and optional, Flag.parse() removes the option when checked and writes '0' when unchecked, so the daemon's implicit on-by-default is preserved and no section is created just by leaving the box ticked. One issue with how the four dependent fields are wired to it, plus one series nit, inline.
Generated by Claude Code
1443c8e to
3d84344
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now b3f29ea + 3d84344, replacing e1488b2/cae4bcd/2a5c682/1443c8e). The i18n squash asked for last round is done: the only non-reference change in the po files since 1443c8e is one re-wrapped Polish line in po/pl, and the .pot references line up with the final usteer.js (e.g. Band steering → usteer.js:667). Both commit messages match their diffs — b3f29ea touches only usteer.js, 3d84344 only the po files — so no Commit checks section.
The hasBandSteeringToggle hoist resolves the previous round's finding correctly: all four depends(sid + '_band_steering_enabled', '1') sites are now behind the same Initscript.includes() check that guards the toggle itself, so on a usteer build without band_steering_enabled the four parameter fields stay visible and parse() no longer strips their stored values.
New this round: the delete_known plumbing added by b3f29ea looks like it cannot work as shipped — the method is missing from the app's rpcd ACL, and the RPC declaration lacks reject: true, which turns any failure into a silent fake success. Details plus one question about remote nodes inline.
Generated by Claude Code
3d84344 to
17fead0
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now 2516ae3 + 17fead0, replacing b3f29ea/3d84344). The delta since 3d84344 is small: reject: true on the delete_known declaration, the catch() now surfacing err.message via ui.addNotification(), the isLocal flag on collectKnownStaEntries(), and the ACL grant. Both commit messages match their diffs — 2516ae3 touches only usteer.js and acl.d/luci-app-usteer.json, 17fead0 only the po files — so no Commit checks section.
All three findings from the previous round are resolved correctly:
reject: trueis set, sohandleCallReply()now raises on a non-zero ubus status instead of resolving with the status code, and thecatch()branch is reachable.L.raise('RPCError', …)produces a realError, soerr.messageis populated."usteer": [ "delete_known" ]landed underwrite.ubus, which is the right block for a state-mutating call.- The remote-node question is answered by dropping the button on
Remoteinforows rather than shipping one that silently undoes itself on the nextremote_update_interval; both call sites (lines 200-201 and 802-803) pass the flag consistently.
The i18n commit is now purely reference-line churn relative to 3d84344 — no msgid or msgstr changed — and the regenerated references match the final file (e.g. Delete → usteer.js:171). FormalityCheck is green on 17fead0.
One nit inline.
Generated by Claude Code
17fead0 to
ced26b7
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now 9a7e04e + ced26b7, replacing 2516ae3/17fead0). The delta since 17fead0 is one line of usteer.js plus the i18n propagation of that single msgid. Both commit messages match their diffs — 9a7e04e touches only usteer.js and acl.d/luci-app-usteer.json, ced26b7 only the po files — so no Commit checks section.
The previous round's nit is addressed: the Known-stations help text now explains why remote rows carry no Delete button, and it gained the trailing period the two preceding sentences already had. The .pot reference still resolves to the right place (usteer.js:184), the new msgid is propagated to all 31 language files plus the template, and the Polish msgstr is a complete translation of the new wording. All three FormalityCheck runs are green on ced26b7.
Two i18n nits inline, both confined to po/pl/usteer.po; nothing blocking.
Generated by Claude Code
ced26b7 to
c763e7d
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now 8ae5020 + c763e7d, replacing 9a7e04e/ced26b7). 8ae5020 is byte-identical to the previously reviewed 9a7e04e — same tree, same message — so the entire delta is the po/pl/usteer.po rebuild plus the paragraph documenting it in c763e7d.
Both nits from the previous round are resolved, and the rebuild's claims check out against the tree:
- Obsolete entries in
po/pl/usteer.podrop from 52 to 31, and the resulting set is exactly the setpo/de/usteer.po(and the other translated languages) gains from this PR — I compared the two files entry by entry, the msgid sets match with nothing extra on either side. The 21 PR-internal leftovers are gone. - All 165 live entries are still present, none went empty or fuzzy, and the
#:reference lines and msgid ordering are identical topo/de/usteer.po, i.e. the file really was merged against this PR's final.pot(166 entries incl. header, matchingpo/templates/usteer.pot). - The Weblate header block (
Project-Id-Version,PO-Revision-Date: 2026-03-29,Last-Translator,Plural-Forms,X-Generator) is preserved from master's copy rather than replaced by the template's, so the rebuild won't look like a translator change to Weblate. - The
Dostępne→Wypełnianerevert landed and the Polish sentence now tracks the EnglishOnly populated while …again.
All three FormalityCheck runs are green on c763e7d. One wording issue on the new commit message below; nothing blocking.
Commit checks
- c763e7d "luci-app-usteer: update translation template and Polish translation" — the new paragraph ends with "was diffed msgid-by-msgid against the carried-forward copy to confirm all 165 live translations are unchanged", but the commit does change one live translation:
po/pl/usteer.po:587-590restoresDostępne tylko gdy→Wypełniane tylko gdyin the usteer.js:184 description. That revert is correct and was the point of the previous round's second nit — but it is the only substantive msgstr change in the whole commit, and the message currently asserts the opposite. Everything else really is obsolete-entry churn, so a reader trusting the message would skip the one hunk that isn't. Suggest amending the last sentence to something like "…to confirm all 165 live translations are unchanged apart from theOnly populated while …description, whose opening verb is restored to Wypełniane."
Generated by Claude Code
c763e7d to
51a1bf4
Compare
|
Fixed in 51a1bf4 (amend, no file changes): reworded the commit message's last sentence to call out the Dostępne→Wypełniane revert as the one substantive msgstr change, instead of implying nothing changed. |
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed 1 new commit; no new issues found.
51a1bf4 replaces c763e7d as the i18n commit and 8ae5020 is carried over unchanged. git diff c763e7d..51a1bf4 is empty — the trees are byte-identical, so the entire delta is the commit-message amend the author described, exactly as stated in the PR comment.
The previous round's Commit checks finding is resolved: the last sentence of the rebuild paragraph now reads "…are unchanged apart from the "Only populated while ..." description, whose opening verb is restored to "Wypełniane"", and a new paragraph explains the choice. That matches the tree — po/pl/usteer.po:584-588 is the one live msgstr the rebuild changed relative to the carried-forward copy, and the message no longer asserts the opposite.
All three FormalityCheck runs are green on 51a1bf4.
Generated by Claude Code
51a1bf4 to
1b0a234
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now 3a4cee1 + 1b0a234, replacing 8ae5020/51a1bf4). This round is substantially bigger than the last few: 3a4cee1 moves thirteen options (sta_block_timeout, local_sta_timeout, max_retry_band, seen_policy_timeout, assoc_steering, probe_steering, max_neighbor_reports, load_balancing_threshold, steer_reject_timeout, roam_process_timeout, roam_kick_delay, initial_connect_delay, node_up_script) out of the global Settings tab into addSsidTab() and reorders the per-SSID field list, and 1b0a234 regenerates the whole i18n set for it.
What checks out:
- The
.potreally was regenerated against the finalusteer.js— spot-checked references resolve (Sta block timeout→ usteer.js:576,Band steering threshold→ usteer.js:602,Node up script→ usteer.js:786), and the msgids dropped by this round's rewording (default false,empty means all,Default: 3) are gone from the template whileDefault:survives because usteer.js:780`` still uses it. - The obsolete-entry claim holds:
po/pl,po/de,po/csandpo/ruall carry exactly 47#~ msgidentries and 162 live ones, matching the 162-entry template, so the pl file is in line with the rest as the commit message says. No fuzzy and no empty msgstr inpo/pl. - All three FormalityCheck runs are green on
1b0a234.
Two problems introduced by this round, plus one question and one nit, inline. The i18n one is the bigger of the two — the rebuild carried in 19 changed Polish translations of msgids this PR doesn't touch on the English side.
Commit checks
- 3a4cee1 "luci-app-usteer: add per-SSID settings tabs and known-station tracking UI" — the message says "The four band-steering parameter fields depend on it and hide when disabled", but after this revision's reorder only three do:
band_steering_thresholdwas moved up into the station-policy cluster at usteer.js:602-604`` and lost itsif (hasBandSteeringToggle) o.depends(…)in the process. Either restore the dependency (see inline) or drop the "four" from the message. - 1b0a234 "luci-app-usteer: update translation template and Polish translation" — the message says the rebuilt
po/pl/usteer.powas "verified msgid-by-msgid against the working copy first to confirm no live translation regressed", but 19 live msgstr differ from the previously reviewed 51a1bf4 copy, and 13 of those had matchedmasterexactly (Event log types,Interval (ms) between sending state updates to other APs,Local sta timeout,Local sta update,Max neighbor reports,Measurement report timeout,Message types to include in log.,Node up script,Remote node timeout,Remote update interval,Seen policy timeout,Setting the interval to 0 disables link-measurements.,Sta block timeout). None of those msgids changed in English in this PR, so the merge should have left them alone. Details inline onpo/pl/usteer.po:288.
Generated by Claude Code
1b0a234 to
bf996b4
Compare
daf4473 to
c5b1468
Compare
643bd11 to
9f1345e
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now 46a98d9 + 9f1345e, replacing 3a4cee1/1b0a234). The code delta since 1b0a234 is 56 lines of usteer.js: hasBandSteeringToggle hoisted to the top of addSsidTab(), the band_steering_threshold dependency restored, local_sta_update moved out of the global Settings tab into the per-SSID tab, and assoc_steering/probe_steering converted from form.Flag to a three-way form.ListValue.
Both fixes from the previous round check out:
band_steering_thresholdis guarded again (usteer.js:633-634), and hoisting theconstabove the field cluster removes the temporal-dead-zone problem; the toggle is still declared later in the same section, which is fine sincedepends()resolves by name atcheckDepends()time.- The tri-state does what the new comment claims. With
o.default = ''andoptional,parse()removes the option when the blank choice is picked — so nousteer_ssidsection is forced into existence — while'0'is a real write that can override a globally-enabled setting, which the old Flag could not express. And because the choice list contains'',ui.Selectreuses that choice's own label instead of prepending a second-- Please choose --entry, so the dropdown has exactly three items.
i18n: the template really was regenerated against the final file — the three new msgids resolve to usteer.js:615-617/621-623 and the reworded local_sta_update description to usteer.js:594. po/de, po/cs and po/ru are clean mechanical merges (exactly the four msgid additions and one removal, no msgstr touched). po/pl has the same msgid set as the template, 0 fuzzy and 0 untranslated, but also rewrites 10 live translations of msgids this PR leaves alone — inline.
All three FormalityCheck runs are green on 9f1345e.
Commit checks
- 9f1345e "luci-app-usteer: update translation template and Polish translation" — the message scopes the regeneration to "the string changed by moving local_sta_update to the per-SSID tab", but this is the PR's only i18n commit: the template it produces adds 61 and drops 48 msgids relative to master, and this revision alone contributes three more (
On,Off,Use global setting) beyond thelocal_sta_updaterewording. The message also says it "translates the new/reworded Polish strings", while the commit additionally rewrites 10 livepo/plmsgstr whose English text this PR does not change (details inline onpo/pl/usteer.po:372). - 46a98d9 "luci-app-usteer: add per-SSID settings tabs and known-station tracking UI" — the content matches the diff, but the body is written as a changelog against states that will never exist in master: "plus fixes from review: reject:true and ACL grant for delete_known, Delete button hidden for remote-owned entries, band_steering_enabled dependencies guarded against builds lacking the toggle…". This is the commit that introduces
delete_known, its ACL entry and those dependencies in the first place, so ingit logthe sentence reads as if an earlier commit had shipped them broken. Dropping "plus fixes from review:" and stating the behaviour directly keeps the same information without the phantom history.
Generated by Claude Code
9f1345e to
aec0084
Compare
a14333d to
de6a51b
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now 0307d7a + de6a51b, replacing 5fa58dc/eafda37f/70deda34). Both findings from the last round are fixed, and the rest of the delta is a rebase onto current master (19365a7):
- The empty
70deda34"retrigger CI checks" commit is gone — the branch is back to two commits. po/sv/usteer.pois merged against this PR's template now. It carries the template's 162 live msgids exactly (0 missing, 0 extra), the same 48 obsolete entries aspo/de/po/cs/po/ru(identical msgid set), and 59 untranslated — the same count as every other fully-merged language — with not a single Swedish msgstr differing from master's copy. The Weblate header block is preserved (PO-Revision-Date: 2026-08-13,Last-Translator,X-Generator), so it won't read as a translator change. All 31 languages now land on 162/162 againstpo/templates/usteer.pot, in identical msgid order.usteer.jsandacl.d/luci-app-usteer.jsonare byte-identical to the previously reviewed5fa58dc3, and both commit messages are unchanged, so there is no code delta this round. The.potstill matches the file it was generated from — all 194usteer.js:NNNreferences resolve to a line whose_()call carries that msgid — andpo/plis unchanged since eafda37 (no msgstr diff, 0 fuzzy, 0 untranslated).- The rebase is clean: master's only change to this app in the window is a three-line Weblate update to
po/lt/usteer.po, and head'spo/ltcarries master's current msgstr verbatim, with only#:reference lines differing. - All three FormalityCheck runs are green on
de6a51b.
One cosmetic difference worth naming so it isn't mistaken for a missed merge: sv's #~ tail is ordered alphabetically while the other 30 languages keep msgmerge's default order. Same 48 entries either way, and dead text regardless.
The two inline threads from the last round are still open — the Band-steering threshold / Band steering threshold label collision, and the migration question about the options that no longer appear on the global Settings tab — not repeated here.
Commit checks
- de6a51b "luci-app-usteer: update translation template and Polish translation" — the message is unchanged from eafda37, so both wording problems raised on it stand. It enumerates the regeneration as dropping the band-steering toggle's strings and picking up the restored "A value of 0 disables band-steering." sentence, but never mentions the
On/Off→Enable/Disablerelabel, which is the other half of what the template picks up: it dropsOnandOffand gainsEnableandDisable, and those two are the only strings besides the reworded interval description thatpo/plneeded new translations for. And "Dropped the resulting pl-only obsolete entries … matching every other language" still describes no hunk in this commit: relative to master,po/pl/usteer.pogains 48 obsolete entries (173#~lines) and removes none — that cleanup happened in the since-squashed2f59d60. The end state the sentence claims is true (pl's obsolete set is now identical to de/cs/ru's), but as written it points at a removal the diff doesn't contain. "merges into every language's po file" is accurate now that sv is included.
Generated by Claude Code
de6a51b to
cac79e7
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now 3057a13 + cac79e7, replacing 46a98d9/9f1345e; the branch was also rebased onto current master). The usteer.js delta since 9f1345e is ~140 lines: the band_steering_enabled toggle and its four depends() sites reverted, On/Off relabelled to Enable/Disable, band_steering_min_snr restored to master's label, and every per-SSID o.placeholder = … replaced by the new setPlaceholder() helper.
What checks out:
setPlaceholder()'s lookup works as intended:uci.resolveSID()does expand the@type[idx]form beforeget()reads it, souci.get('usteer', '@usteer[0]', field)resolves to the anonymous shared section.uci.load('usteer')runs inload(), andaddSsidTab()is called fromrender()(line 931), so the values are there. Evaluating the placeholder once at render is fine here precisely because these options are no longer editable on the page.- The band-steering revert is complete and self-consistent — no
depends()left pointing at the removedband_steering_enabled, and the interval field regained master's "A value of 0 disables band-steering." sentence. - i18n: this round does not repeat the recurring problem. Diffing
po/pl/usteer.poentry by entry against 9f1345e, zero live msgstr changed; the only delta is 4 msgids added (Enable,Disable,Band steering min SNR, the reworded interval description) and 6 removed.po/plhas 0 fuzzy and 0 untranslated, and all 31 languages plus the template carry the same 163 live msgids. - All three FormalityCheck runs are green on
cac79e7.
Three things introduced or missed by this round are inline: a hard-coded band-steering-interval fallback that drops master's init-script-conditional default, the 35 options this revision removes from the global Settings tab with no feature guard, and a .pot whose references are two lines stale. Plus one nit.
Commit checks
-
3057a13"luci-app-usteer: add per-SSID settings tabs and known-station tracking UI" — the message is a botched squash:Signed-off-by: Grzegorz Kaczor <…>appears at line 24, in the middle of the body, followed by two more prose paragraphs and a second, duplicateSigned-off-byat line 42. A trailer block has to be the last thing in the message; as it standsgit interpret-trailersand anything else parsing the footer sees a body paragraph after the sign-off. Fold the two trailing paragraphs into the body above and keep a single sign-off at the end.The same two paragraphs also bring back the phantom-history framing you removed in 3e2f5d7: "Previously the placeholder always showed the compiled-in default…" and "band_steering_min_snr keeps its master label … instead of 'Band-steering threshold'" describe intermediate states of this PR that will never exist in master. This commit is the one that introduces
setPlaceholder()and theband_steering_min_snrfield in the merged history, so there is no earlier state for it to be correcting. Stating the behaviour directly keeps the rationale without the review-round narration. -
cac79e7"luci-app-usteer: update translation template and Polish translation" — three claims don't match the tree:- "Regenerates usteer.pot against the final usteer.js" — it doesn't; 132 of the template's references are two lines stale (details inline on
po/templates/usteer.pot:678). - "all 31 languages now carry the template's 162 live msgids and the same 47 obsolete entries" — the live count is 163, not 162, and the obsolete count is nowhere near uniform: 47 in cs, de, es, ga, ko, lo, lt, pl, ru, sv, uk, zh_Hans; 42 in ta and tr; 10 in it; 9 in zh_Hant; 4 in pt and ro; 2 in fr and pt_BR; and 0 in az, be, bn_BD, da, fi, hu, ja, nb_NO, nl, sk, vi. That is the expected outcome (msgmerge only preserves obsolete entries that had a translation), so the fix is to the sentence, not the files.
- "Polish needs no new translation work this round" — the commit adds two brand-new Polish translations,
Enable→ "Włącz" (po/pl/usteer.po:203-204) andDisable→ "Wyłącz" (po/pl/usteer.po:194-195). Neither msgid existed in 9f1345e'spo/pl, as a live entry or an obsolete one, so they are not reused wording. TheBand steering min SNRreuse the message describes is real (#~ msgidat 9f1345e'spo/pl/usteer.po:913); theEnable/Disablepair is not.
- "Regenerates usteer.pot against the final usteer.js" — it doesn't; 132 of the template's references are two lines stale (details inline on
Generated by Claude Code
cac79e7 to
d0e31d9
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now 112078a + d0e31d9, replacing 3057a13/cac79e7). Two things this round: usteer.js gains 228 lines — setPlaceholder() learns to carry the fallback's unit onto the global value (plus the snrDbm sign-based variant), and a !Initscript.includes('usteer_ssid') block restores the 35 removed options to the global Settings tab — and the whole i18n set is regenerated for it.
What checks out:
- The previous round's
band_steering_intervalfinding is fixed: line 761 now usesInitscript.includes('aggressiveness') ? '30000 (ms)' : '120000 (ms)', matching master's conditional at usteer.js:679.`` - The unit-annotation regex is safe against the fallbacks actually passed.
/^-?[0-9]+ (\(.+\))$/would greedily swallow0 (SNR) or -95 (dBm)whole, but all five dual-convention fields (min_snr,min_connect_snr,roam_scan_snr,roam_trigger_snr,band_steering_min_snr) passsnrDbm = trueand return before reaching it; every other fallback is either a bare number or a singleN (unit)string. - The restored block is a faithful copy of master's, not a re-invention: diffing it line-by-line against
19365a7'ss.taboption('settings', …)run, the labels, descriptions, placeholders, datatypes and theaggressiveness/aggressiveness_mac_list/band_steering_signal_thresholdsub-guards are identical, and the field count really is 35. It also quietly fixes master's'band_steering_signal_threshold 'option name, which carried a trailing space. - No option-name collision between the two paths:
opt()prefixes every per-SSID key with the section id, somin_snrandssid_foo_min_snrcoexist in the same CBI section. - The last commit's
Signed-off-byplacement is fixed — one trailer, at the end. - i18n is mechanically clean. All 276
usteer.js:NNNreferences in the regenerated.potresolve to a line whose_()call carries that msgid, all 31 languages plus the template land on the same 206 live msgids in the same order, and — notably — this round does not repeat the recurring problem: diffingpo/plandpo/deentry by entry againstcac79e7, zero surviving msgstr changed; the delta is 43 msgid additions (the restored global-tab strings) and nothing removed.po/plis 0 fuzzy / 0 untranslated. The obsolete-count claim holds exactly: 15 languages on 0 (the listed set), 14 on 4, plusiton 1 andzh_Hanton 2. - All three FormalityCheck runs are green on
d0e31d9.
One issue with how the new guard interacts with addSsidTab(), plus a nit, inline. The still-open thread about the shared usteer values being read-only placeholders on a new daemon (and a device with no configured SSID having no editable copy at all) isn't repeated here.
Commit checks
-
112078a"luci-app-usteer: add per-SSID settings tabs and known-station tracking UI" — the message says these fields are removed from the global tab "unless the running usteer build's init script has nousteer_ssidsupport … on such a build the tab falls back to registering them there instead". The diff doesn't implement the "instead": the guard covers only the global block, whileaddSsidTab()is called unconditionally, so an old daemon gets both sets of widgets, one of which silently does nothing. Details inline on usteer.js:1084 — either guard theallSsidNames.forEach(...)too, or drop "instead" from the message. -
d0e31d9"luci-app-usteer: update translation template and Polish translation" — two counts don't match the tree:- "Regenerates usteer.pot from the final usteer.js (207 live msgids)" — the template has 207
msgidentries, but one of them is the PO header (msgid ""), so the live count is 206.po/pl's "all 207 live msgids" in the last paragraph is the same off-by-one. - "Relative to master, the template drops the band-steering toggle's four strings" — the four msgids actually dropped relative to
19365a7areList of SSIDs to enable steering on,Refresh page to get new mac addresses to show up,default trueandempty means all. Theband_steering_enabledtoggle's strings were never in master's template; they were added and reverted inside this PR, so they can't be part of a delta against master. The same sentence then says the template gainsEnable/Disable"replacingOn/Off" andBand steering min SNR"back under its master label" — butOn/Offwere also never in master, andBand steering min SNRis present in master's template and this one alike, so it isn't gained either. The sentence is describing the delta against the previous revision of this PR while claiming to describe the delta against master; the obsolete-count paragraph that follows then attributes the per-language 0/4 split to "this round's four-string removal", which is the correct count attached to the wrong four strings.
- "Regenerates usteer.pot from the final usteer.js (207 live msgids)" — the template has 207
Generated by Claude Code
d0e31d9 to
68e6a6f
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now d1b9b95 + 68e6a6f, replacing 112078a/d0e31d9). The delta since d0e31d9 is 21 lines of usteer.js plus pure #: reference churn in the po files.
Both findings from the previous round are fixed:
hasSsidConfigis hoisted to line 945 and now guards theallSsidNames.forEach(addSsidTab)call as well as the restored global block, so the two paths really are mutually exclusive and an old daemon no longer gets both sets of widgets. One leftover at the third site, inline.load_kick_reason_code's description lost master's unbalanced trailing)and wrapsDefault:in_(), matching how the per-SSID copy at usteer.js:806`` already spells it. No new msgid, sinceDefault:was already in the template.
The i18n commit is clean this round and its counts all check out against the tree:
- The delta since d0e31d9 is only reference lines — across all 31 languages plus the template, zero msgids added or removed, zero msgstr changed, zero obsolete entries changed.
- The template really was regenerated from the final
usteer.js: all 277usteer.js:NNNreferences resolve to a line whose_()call carries that msgid. - "206 live msgids" is right (207
msgidentries minus the PO header; the twoSignalentries aremsgctxt-distinguished, not a duplicate). Relative to master the template drops exactly the four named strings and gains exactly 59. - The per-language obsolete split matches the message exactly:
az be bn_BD da fi fr hu ja nb_NO nl pt pt_BR ro sk vion 0, fourteen on 4,iton 1,zh_Hanton 2.po/plis 0 fuzzy / 0 untranslated across all 206.
All three FormalityCheck runs are green on 68e6a6f.
One bug introduced by an earlier round that is still live, plus the leftover guard, inline. The still-open threads about the shared usteer values being read-only placeholders on a new daemon, and the Polish msgstr that diverge from master, aren't repeated here.
Commit checks
- d1b9b95 "luci-app-usteer: add per-SSID settings tabs and known-station tracking UI" — the third paragraph says the restored global fields keep "the same labels, descriptions and defaults master's copy of this file used", but one description deliberately doesn't:
load_kick_reason_codeat usteer.js:1231-1232`` drops master's stray)and makes `Default:` translatable. It's the right change and it's the only one, so it's cheap to name it ("…the same labels, descriptions and defaults master used, apart from `load_kick_reason_code`'s description, whose unbalanced trailing paren is dropped and whose `Default:` is made translatable") rather than have a reader diff the block to find the one intentional deviation.
Generated by Claude Code
68e6a6f to
e9579a7
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now d1b9b95 + 23870d4 + e9579a7, replacing 46a98d9/9f1345e). Big round: setPlaceholder() sources every per-SSID Value placeholder from the shared usteer section, the band_steering_enabled toggle and its four depends() sites are reverted, On/Off become Enable/Disable, band_steering_min_snr gets master's label back, and 35 global fields are restored to the Settings tab behind !hasSsidConfig.
Every finding from the previous round is resolved, and I re-verified each against the tree:
- The 35 deleted global options are back. Diffing the restored
if (!hasSsidConfig)block against master's copy line by line, the labels, descriptions, placeholders and datatypes are identical, andaddSsidTab()is now gated on the same flag, so the two paths really are mutually exclusive. Two silent improvements ride along: master's option name'band_steering_signal_threshold '(trailing space, so it wrote a UCI key nobody reads) loses the space, andload_kick_reason_code's unbalanced trailing paren is fixed. band_steering_interval's fallback now followsInitscript.includes('aggressiveness')instead of a hard-coded 30000..potreferences. I resolved all 277usteer.js:NNNreferences in the regenerated template against the head file: 277 correct, 0 off. The previous round's uniform +2 shift is gone.po/svis merged again — it lands on the same 205 live / 4 obsolete shape as de/cs/ru/uk/zh_Hans, and is no longer byte-identical to master.== nulland thehasSsidConfig &&relocation guard landed in23870d4, so a stock config no longer rendersundefined (ms)and a pre-usteer_ssiddaemon no longer gets an empty bordered box above Save/Reset.
e9579a7's i18n bookkeeping claims all hold: the template is 206 live msgids, drops exactly the four named strings (List of SSIDs to enable steering on, empty means all, Refresh page to get new mac addresses to show up, default true) and gains 59, and the per-language obsolete counts are exactly as listed — 15 languages at 0 (az, be, bn_BD, da, fi, fr, hu, ja, nb_NO, nl, pt, pt_BR, ro, sk, vi), 14 at 4, it at 1, zh_Hant at 2. po/pl has 0 fuzzy and 0 untranslated. All three FormalityCheck runs are green on e9579a7.
One issue in addSsidTab(), one in the Polish merge, and one nit inline.
Commit checks
- d1b9b95 + 23870d4 "luci-app-usteer: add per-SSID settings tabs and known-station tracking UI" — two commits with the same subject and near-identical full-feature bodies, where
23870d4is a two-line fixup ofd1b9b95(=== null→== nullinsetPlaceholder(), andhasSsidConfig &&added to the tab-relocation guard). Its message describes the whole feature rather than its own change, sogit logshows the feature twice and the delta nowhere. It also leavesd1b9b95's message wrong aboutd1b9b95's own code: that message promises the placeholder falls back to "that fallback itself once the global option is unset too", but with=== nullan unset-but-present option takes theundefinedbranch and the field rendersundefined (ms)/undefined (SNR)on a stock config — so a bisect landing ond1b9b95gets a commit whose message contradicts its behaviour. Squashing23870d4intod1b9b95and keeping23870d4's (already updated) message fixes both, and is the same squash this series did ate1488b2andb3f29ea. - e9579a7 "luci-app-usteer: update translation template and Polish translation" — the message presents the
po/plchange as a plain merge ("every string this revision touches … already had a Polish translation to merge against"), but the commit also rewrites 36 livemsgstrwhose English text is untouched by this PR, 13 of them on global-only options the diff never goes near. The other 30 languages are clean mechanical merges with 0 changedmsgstr;plis the only exception and the message doesn't mention it. Details onpo/pl/usteer.po:353.
Generated by Claude Code
e9579a7 to
5e75730
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now f751d37 + 5e75730, replacing d1b9b95/23870d4/e9579a7). The series is back to two commits, and the code delta since e9579a7 is 20 lines of usteer.js; everything else is the i18n regeneration.
Both findings from the previous round are addressed, and the fixes check out:
load_kick_enabledis now the same three-wayListValueasassoc_steering/probe_steering(''/'1'/'0',default = '',optionalviaopt()), so "unchecked" and "inherit" are no longer the same state and an SSID can override a globally-enabled setting. The four dependent fields each gained a seconddepends(sid + '_load_kick_enabled', ''), and that really does keep them active in the blank state —isDependencySatisfied()compares the widget value withisEqual(), which holds for('', ''), so only an explicit'0'makes them inactive and triggers theparse()→remove()path.- The bare
_('Signal')now carries the Status/Hearing-mapmsgctxt, so the template no longer ships twomsgid "Signal"entries, and the plain one lands aspo/pl's fifth obsolete block exactly as the message describes.
Re-verified against the tree:
- All 221
usteer.js:NNNreferences in the regenerated.potresolve to a line whose_()call carries that msgid — 221 correct, 0 off. - All 31 languages plus the template carry the same msgid set (206
msgidlines each) in the same order, and the per-language obsolete split is exactly as listed: 15 at 0 (az, be, bn_BD, da, fi, fr, hu, ja, nb_NO, nl, pt, pt_BR, ro, sk, vi), 13 at 4,it1,zh_Hant2,pl5. - Relative to master the template drops exactly the four named strings (
List of SSIDs to enable steering on,empty means all,Refresh page to get new mac addresses to show up,default true). - "30 of the 31 languages are clean mechanical merges" holds — I diffed every language entry by entry against
e9579a7: zeromsgstrchanged anywhere exceptpo/pl, which changes exactly 34. 33 of those 34 land on master's wording byte-for-byte; the 34th, plus two that the revert missed, are inline. po/plis 0 fuzzy, 1 untranslated — and that one untranslated entry is the regression below, not a pre-existing gap.- The restored
if (!hasSsidConfig)block still registers exactly 35settingsoptions, andhasSsidConfigstill gates all three sites (usteer.js:967, 1107, 1343).f751d37touches onlyusteer.js+acl.d/luci-app-usteer.json,5e75730only the po set, so the split is clean. - All three FormalityCheck runs are green on
5e75730.
The aggressiveness half of the previous round's load_kick_enabled thread (default = '3' with rmempty, so 3 can never be written as an explicit override of a global 4) is unchanged and that thread is still open — not repeated here.
Commit checks
5e75730"luci-app-usteer: update translation template and Polish translation" — three bookkeeping claims don't match the tree:- "206 live msgids, one fewer than before" — the template has 206
msgidentries, one of which is the PO header, so the live count is 205. The delta is right (the previous revision was 206 live); the absolute number wasn't decremented with it. Same off-by-one in the last paragraph's "0 fuzzy across its 206 live msgids". - "and gains 59" — master's template is 151 live; this one drops the four named strings and gains 58, landing at 205. 59 was the correct figure for the previous revision, before the
Signalmerge removed one. - "po/pl carries 1 untranslated entry (matching master exactly -
Number of remote update intervals after which a remote-node is deletedhas no Polish translation upstream either)" — master does translate it, atpo/pl/usteer.po:491-493. This commit empties it rather than reverting it, so the file ships one fewer Polish translation than master for a string the PR doesn't touch. Details inline onpo/pl/usteer.po:796.
- "206 live msgids, one fewer than before" — the template has 206
Generated by Claude Code
5e75730 to
87c1a27
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now 3a11173 + 87c1a27, replacing 46a98d9/9f1345e; the branch was also rebased onto current master, so the raw range diff carries a lot of unrelated tree churn — I diffed 9f1345e..87c1a27 restricted to applications/luci-app-usteer/). The code delta is ~400 lines of usteer.js: the new setPlaceholder() helper, the band_steering_enabled toggle dropped again, load_kick_enabled converted to the same tri-state as assoc_steering/probe_steering, On/Off relabelled Enable/Disable, band_steering_min_snr relabelled, the Known-stations Signal header given the shared msgctxt, and the new hasSsidConfig guard plus the 35 restored global fields behind it.
Everything flagged in the previous rounds is resolved, and the claims check out against the tree:
- The 35 global options are back under
Initscript.includes('usteer_ssid')and the set is exactly the per-SSID set — I diffed the option names both ways, 35/35 with nothing extra on either side, and each restored field's label, description, placeholder and datatype is byte-identical to master's copy (the one intended exception,load_kick_reason_code, is as described). band_steering_threshold's lost dependency is moot now that the toggle is gone, and the relocation guard at usteer.js:1347 got thehasSsidConfigtreatment, so the two paths really are mutually exclusive.depends(sid + '_load_kick_enabled', '')is a supported shape —isDependencySatisfied()comparesformvalue()withisEqual()andListValueinheritsAbstractValue.formvalue(), which returns the raw''(theformvalue()override that maps default→nullisRangeSliderValue's, notListValue's) — and it matches the nine existingdepends(x, '')sites in the tree. The tri-state itself matches tools/network.js:1145-1150`` as the message says.setPlaceholder()'suci.get('usteer', '@usteer[0]', field)resolves —resolveSID()expands@type[n]— and== nullcatches theundefinedan absent option returns. All five dual SNR/dBm fields passsnrDbm, and the unit regex reproduces the old annotations for the rest.- i18n: every claim in
87c1a27's message verifies mechanically. 205 live msgids in the template, all 31 po files carry exactly that msgid set, the four dropped and 58 gained msgids are as listed, and the obsolete counts land exactly where the message says (0 for the 15 named languages, 4 for 13 more,it1,zh_Hant2,pl5 — the fifth being the now-obsolete plain"Signal"). All 280usteer.js#:references in the template resolve to the right line of the final file.po/plhas 0 fuzzy and 0 untranslated, and — the point of this round — zero msgstr now differ from master across all 31 languages, so the long-running Polish-drift finding is fully closed. - All three FormalityCheck runs are green on
87c1a27.
One question about what happens to the shared-section values on a usteer_ssid-capable daemon, plus one i18n nit, inline.
Commit checks
- 3a11173 "luci-app-usteer: add per-SSID settings tabs and known-station tracking UI" — the restored-fields paragraph presents its exception list as exhaustive ("with the same labels, descriptions and defaults master's copy of this file used - apart from load_kick_reason_code's description…"), but there is a second deviation: master registers the option as
'band_steering_signal_threshold 'with a trailing space at usteer.js:757,and the restored copy at [usteer.js:1267](https://github.com/openwrt/luci/blob/87c1a27bdee09dadb761e6e62e38a881a76a9289/applications/luci-app-usteer/htdocs/luci-static/resources/view/usteer/usteer.js#L1267)`` silently drops it. The fix is clearly right — the trailing space is not a valid UCI option name, so master's global widget can never have written anything the daemon reads — but it changes which key a legacy-daemon user's value lands under, and it's the kind of thing that deserves a clause of its own rather than arriving inside a block advertised as a faithful restore. - 87c1a27 "luci-app-usteer: update translation template and Polish translation" — the
po/plparagraph says "36 msgstr this PR had previously carried with reworded (or, for one, emptied) Polish text … are reverted to master's wording". Comparing9f1345e:po/pl/usteer.powith this commit's copy, the count is 35, not 36, and none of them was empty in9f1345e— that file had 0 untranslated entries, as the previous round's review confirmed. The "emptied" one belongs to an earlier revision of the series that9f1345ehad already fixed. The 13 named global-only msgids are all in the 35, and every one of them lands back on master's exact wording, so only the count and the parenthetical need adjusting.
Generated by Claude Code
924222d to
2c1b4f8
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now 1912921 + 2c1b4f8, replacing 3a11173/87c1a27). The branch is still on the same base (6e1eb21), so the range diff is clean: 412 lines of usteer.js plus the i18n regeneration.
The headline change is the one the previous round asked about: the 35 shared-section options are no longer gated behind !hasSsidConfig on the Settings tab — they now live in an always-registered Defaults tab bound to @usteer[0], nested first in the same sub-tab bar as the per-SSID tabs when the daemon reads usteer_ssid. That closes the "visible-but-unreachable fallback" finding, and the previous round's A value of 0 disables threshold. nit landed as well.
Verified mechanically against the tree:
- The Defaults set is exactly the per-SSID set — 35/35 option names, in the same order
addSsidTab()registers them. I diffed both lists; nothing extra on either side, and the order matches element for element, as the message claims. - Each Defaults widget is a faithful copy of master's global original. I diffed all 35 blocks against
6e1eb21'susteer.js(label, description, placeholder, datatype). The only textual deviation isload_kick_reason_code, exactly the one the message calls out, and master really does register'band_steering_signal_threshold 'with a trailing space at usteer.js:757,`` so the second correction is real too. No option name is registered on both thesettingsand `defaults` tabs. - i18n. The
.potwas regenerated against the final file: all 284usteer.js:NNNreferences resolve to a line whose_()call carries that msgid — 284 correct, 0 off. The template drops precisely the four named msgids and gains 59, landing at 206 live. Obsolete counts are exactly as listed: 0 for the 15 named languages (az, be, bn_BD, da, fi, fr, hu, ja, nb_NO, nl, pt, pt_BR, ro, sk, vi), 4 for 13 more,it1,zh_Hant2,pl6.po/plis 0 fuzzy and 0 untranslated. - No translation drift. Comparing all 31 po files against master entry by entry, zero msgstr differ for any shared msgid, and
plis the only language that translates the 59 new ones — so the long-running Polish-drift thread stays closed. (A handful of entries in es/ga/ko/lo/lt/sv differ only inmsgmergeline wrapping, so "byte-identical" is a touch strong, but no text changed.) - All three FormalityCheck runs are green on
2c1b4f8.
One issue with the Defaults action bar, one question about the Defaults tab on a pre-usteer_ssid daemon, and three nits inline.
Commit checks
2c1b4f8"luci-app-usteer: update translation template and Polish translation" — "of the 206 live msgids, 204 already existed in master" contradicts the same message's own "Relative to master, the template … gains 59". Both can't hold: 206 − 59 = 147 of these msgids exist in master'susteer.pot, not 204. 204 is the figure relative to the previous revision of this PR —87c1a27's template carried 205 live msgids, this one addsDefaultsand its description and drops the unpunctuatedA value of 0 disables threshold, landing at 206 — which is also what makes the next sentence about "the two genuinely new msgids … translated fresh for Polish" correct. Naming the previous revision instead of master in that one clause makes the paragraph consistent; the msgstr claim it introduces holds either way.
Generated by Claude Code
2c1b4f8 to
3a06a98
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now 8822860 + 3a06a98, replacing 1912921/2c1b4f8). Same base (6e1eb21), so the range diff is clean: 41 lines of usteer.js plus the i18n regeneration.
All five findings from the previous round are resolved:
- Duplicate Defaults action bar —
Defaultsfooter's registration is now behindif (!hasSsidConfig)at usteer.js:1347-1351,`` exactly the suggested shape. On austeer_ssid-capable daemon the nested Defaults pane relies on the Settings bar like every SSID sub-tab does; on a legacy build, where Defaults is a top-level tab with no Settings footer beneath it, it keeps its own. - Defaults heading on a pre-
usteer_ssiddaemon —hasSsidConfigis hoisted to module scope andDefaultstitlerenders "Settings for this instance of usteer." there instead of advertising a per-SSID fallback the build has no per-SSID tabs for. defaults/ SSID key collision — the sub-tab click handler compares by identity now (usteer.js:1499),`` so a wifi network literally nameddefaultscan't activate two panes at once. `tabs` is rebuilt per `rebuildSsidSubTabs()` call and each handler closes over its own `t`, so identity is stable across rebuilds.- Stale
hasSsidConfigcomment — rewritten and moved next to the assignment. - PR body — the new "Update 2" section documents the Defaults tab and the placeholder change.
i18n, verified mechanically against the tree:
- The template really was regenerated against the final file: all 285
usteer.js:NNNreferences inusteer.potresolve to a line carrying that msgid — 285 correct, 0 off. 207 live msgids, dropping precisely the four named (List of SSIDs to enable steering on,empty means all,Refresh page to get new mac addresses to show up,default true) and gaining 60 relative to master's 151. - The "206 already existed in the previous revision … msgstr unchanged" claim holds exactly. Comparing all 31 po files against
2c1b4f8entry by entry, zero msgstr differ for any shared msgid, and the single new msgidSettings for this instance of usteer.is translated only inpl(Ustawienia tej instancji usteer.). - Obsolete counts land where the message says: 0 for az, be, bn_BD, da, fi, fr, hu, ja, nb_NO, nl, pt, pt_BR, ro, sk, vi (15), 4 for cs, de, es, ga, ko, lo, lt, ru, sv, ta, tr, uk, zh_Hans (13),
it1,zh_Hant2,pl6. All 31 files carry the template's exact msgid set, andpo/plis 0 fuzzy / 0 untranslated across all 207. - Against master, zero msgstr differ for any shared msgid in any of the 31 languages — the long-running Polish-drift thread stays closed.
All three FormalityCheck runs are green on 3a06a98. Both commit messages match their diffs — 8822860 touches only usteer.js and acl.d/luci-app-usteer.json, 3a06a98 only the po files — so no Commit checks section.
Two nits inline; nothing blocking.
Generated by Claude Code
3a06a98 to
2e4cd28
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed the force-pushed series (now c416f9c + 2e4cd28, replacing 46a98d9/9f1345e). The branch was also rebased from d7a654e onto 6e1eb21, so part of the raw po diff is master's own Weblate churn rather than this PR's. This round adds the Defaults tab: the 35 options the earlier revisions moved off the global Settings tab now land in their own section-bound tab instead of being unreachable from LuCI.
The core of it checks out against the tree:
- Nothing was lost from Settings. Master's
settingstab declares 47 options; the new tree has 12 of them still onsettings(plusknown_stations/known_stations_timeoutfrom an earlier revision of this PR) and the other 35 ondefaults— 12 + 35 = 47, no gaps, no duplicate option names between the two tabs (the per-SSID keys are allssid_<sid>_<field>, so they can't collide with the plain names either). - "Faithful copies" is literally true. I diffed every
defaultswidget against master'ssettingsoriginal — class, label, description, placeholder, datatype — and the only textual difference in the whole set isload_kick_reason_code's description, exactly as the commit message says. The other documented correction, dropping the trailing space from master's'band_steering_signal_threshold 'option name, is there too; that key really was unwritable as-is. - The field order matches
addSsidTab()position for position, all 35, as claimed. uci.get('usteer', '@usteer[0]', field)resolves —resolveSID()handles the@type[n]extended notation — and returningundefined(notnull) for an absent option in a loaded section is whatget()actually does, so== nullis the right test.- The two
addFooter()calls are safe: the base implementation builds a freshE([])on every call, so Settings and Defaults get independent trees, anddefaultsfooterdatais only ever produced under the same!hasSsidConfigguard that registersDefaultsfooter. - The new
depends(sid + '_load_kick_enabled', '')sites work as intended:isEqual('', '')is true and a blankui.Selectchoice'sformvalue()is'', so the four load-kick parameter fields stay active in the inherit state andparse()won't strip them. - The
Enable/Disable/blank tri-state does matchtools/network.js— same shape asautoneg/rxpause/txpausethere.`` - i18n, master-relative: the important claim holds. I compared all 31 languages entry by entry against master (6e1eb21): zero msgstr differ for any shared msgid, in any language. The template is 207 live msgids (151 − 4 + 60 vs master), every language's msgid set matches it exactly,
po/plhas 0 fuzzy and 0 untranslated, and the obsolete counts are exactly as the commit message enumerates (15 languages at 0, 13 at 4, it 1, zh_Hant 2, pl 6)..potreferences resolve against the finalusteer.js(Defaults→ usteer.js:439/991/1468,Settings for this instance of usteer.→ usteer.js:442,Band steering min SNR→ usteer.js:795/1290). FormalityCheck is green on2e4cd28.
c416f9c's message matches its diff throughout — including the "object identity, not string keys" detail, which does hold: an SSID literally named defaults gets its own {key, pane} entry and the click handler compares t2 === t.
Two nits inline; nothing blocking.
Commit checks
- 2e4cd28 "luci-app-usteer: update translation template and Polish translation" — the second paragraph's arithmetic is against the wrong baseline. It says "of the 207 live msgids, 206 already existed in the previous revision of this PR, and every language's msgstr for them is unchanged from that revision" and that "The one genuinely new msgid ("Settings for this instance of usteer.")" is the only addition. Measured against the previously reviewed 9f1345e, the template gains 50 msgids and drops 8; six of those are new against master and 9f1345e (
Defaults,Enable,Disable,Settings for this instance of usteer.,The fallback value for every SSID that leaves the corresponding per-SSID field blank.,Attempting to steer clients on this SSID to a higher frequency-band every n ms. A value of 0 disables band-steering.) — the other 44 are master strings coming back with the Defaults tab. Likewise, msgstr did change relative to 9f1345e: pl in 35 places, sv in 71, es/ja/lt in one each. All of that is benign — it's the rebase pulling in master's own Weblate syncs, and it's why the master-relative comparison in the next sentence comes out clean — but as written the paragraph tells a reader that only one string is new and that no translated text moved, which would send them past 50 real msgid additions. The master-relative sentence right after it is both accurate and the one that matters; scoping the whole paragraph that way (and noting the rebase) would fix it.
Generated by Claude Code
2e4cd28 to
4bff264
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Commit checks
4bff264e"luci-app-usteer: update translation template and Polish translation" — the new parenthetical claiming the branch "was also rebased onto master's own latest Weblate sync this round" doesn't hold: this revision and the previously pushed2e4cd28share the same parent (6e1eb21f), and the entire po delta between them is#:reference renumbering — not one msgid or msgstr line differs in any of the 32 files. That rebase was the previous push; drop the parenthetical and keep the previous-revision-relative claim it displaced, which is what tells a reader what this push actually changed.
Generated by Claude Code
4bff264 to
4d51fc4
Compare
…g UI
Adds a per-SSID configuration tab, letting each SSID override the
fields that were previously shared across the whole usteer instance:
roaming-policy (station tracking/policy timeouts, SNR/signal
thresholds, roaming, band steering, load kick, local_sta_update's
per-node update interval) and the per-node up script. A field left
blank on a per-SSID tab falls back to whatever the shared 'usteer'
section has stored for it. assoc_steering, probe_steering and
load_kick_enabled use a three-way Enable/Disable/Use global setting
choice (matching tools/network.js's convention for this kind of
tri-state), since a plain checkbox can't express turning a
globally-enabled setting off for just one SSID - a Flag with
optional/rmempty writes nothing when unchecked, so "unchecked" and
"inherit" collapse into the same state. load_kick_enabled's four
dependent fields (threshold, delay, min_clients, reason_code) depend
on it twice, for '1' and for '' (inherit), so they stay visible in
both states a save could otherwise silently strip them in - not
because inheriting is known to mean load kicking is active (it
defaults to off), but because this widget has no way to tell what
the inherited value actually is, and hiding on blank would delete
whatever this SSID already has stored for them on the next save.
Only an explicit '0' hides them. Band steering is disabled by
setting its interval to 0, matching link_measurement_interval's
convention - there is no separate enable/disable toggle for it.
Per-SSID Value fields' placeholders show what a blank field actually
resolves to via the new setPlaceholder() helper: the value stored in
the shared 'usteer' section (uci.get('usteer', '@usteer[0]', field)),
annotated with the same unit its compiled-in fallback carries, or
that fallback itself once the global option is unset too - checked
with == rather than === against null, since uci.get() returns
undefined (not null) for an option that's simply absent from an
otherwise-loaded section, which is the normal state of every one of
these on a stock config. Defined as a getter rather than a plain
assignment, so editing a value on the new Defaults tab (below) and
hitting Save updates every per-SSID tab's placeholder immediately -
Map.prototype.save() re-renders the form over the same option
objects, and a getter re-reads uci.get() on each of those renders
where a plain assignment would only ever have shown whatever was
loaded at page-open. The five dual SNR/dBm-convention fields
(min_snr, min_connect_snr, roam_scan_snr, roam_trigger_snr,
band_steering_min_snr) pick whichever unit the global value's own
sign means, since a bare number carries no unit of its own -
band_steering_min_snr's own fallback text is corrected from a dual
"0 (SNR) or -60 (dBm)" to plain "-60 (dBm)" in the process, since
usteer's compiled-in default for it (main.c's
config.band_steering_min_snr = -60) is unconditionally negative, so
usteer_snr_to_signal() in policy.c always takes the dBm branch for
it - there is no 0-SNR case this field's fallback ever actually
takes. band_steering_interval's fallback follows the same
init-script-conditional default (30000ms once 'aggressiveness'
support is present, 120000ms otherwise) the global field already
used.
The 35 fields these per-SSID tabs move off the global Settings tab
land in a new Defaults tab instead of disappearing outright: bound
to the shared 'usteer' section rather than any per-SSID one, in the
exact field order addSsidTab() below uses (declaration order of
struct usteer_config, not master's older grouping) since it's the
same set of settings shown the same way, just against a different
section - and there has to be a place in LuCI that can still edit or
clear the values setPlaceholder() reads as every SSID's fallback.
Its widgets are otherwise faithful copies of master's global
originals - same labels, descriptions, placeholders and datatypes -
apart from two corrections: load_kick_reason_code's description
drops master's unbalanced trailing paren and makes "Default:"
translatable (matching the per-SSID copy), and
band_steering_signal_threshold loses the trailing space in master's
option name, which is not a valid UCI key and meant that field could
never actually read or write anything the daemon looks at.
Per-SSID tabs (addSsidTab()) and Defaults are both nested under
Settings, in the same sub-tab bar the per-SSID tabs already used,
with Defaults sorting first and - unlike the SSIDs, which follow the
"SSID list" filter - always present regardless of it, since it isn't
an SSID (compared by object identity in the tab-switch handler, not
by name, so a wifi network actually named "defaults" can't collide
with it the way string keys would). Both this relocation and
addSsidTab() itself are gated on one hasSsidConfig flag
(Initscript.includes('usteer_ssid')), module-scoped like Initscript
itself since Defaultstitle's description below reads it too, and
checked at both sites so a daemon that doesn't read 'usteer_ssid'
sections never gets tabs that write to them; Defaults then stays a
plain top-level tab, since there is no per-SSID list for it to be
nested alongside, that description reads as "usteer's settings"
rather than a per-SSID fallback's, and Defaultsfooter (Save/Reset) -
registered, and refreshed on every handleSave()/handleReset(), only
under the same !hasSsidConfig condition - renders on the tab itself
instead of relying on Settings' below it, which exists only once
nested and would otherwise double up if both copies rendered
together. Settings and Defaults each get their own addFooter() call
rather than sharing one DOM node, since a single node can only be
attached in one place and reusing it would silently move it out of
whichever pane rendered first.
The Known-stations table's Signal column now shares its msgctxt with
the Status/Hearing-map tables' identical header instead of standing
alone as a second, context-free "Signal" msgid, and
band_steering_signal_threshold's "A value of 0 disables threshold"
gains the trailing period its two sibling descriptions already have
and master's own copy of the string carries.
Also adds known-station tracking: a per-node table of stations usteer
has ever seen, with a Delete button shown only for locally-owned
entries (deleting a remote node's synced copy doesn't propagate to
the node that actually owns it) that calls the daemon's delete_known
method over ubus - granted in acl.d/luci-app-usteer.json's write
block, and surfaced through ui.addNotification() on failure.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Grzegorz Kaczor <grzegorz914@icloud.com>
4d51fc4 to
5f2e9b5
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Commit checks
5f2e9b5"luci-app-usteer: update translation template and Polish translation" — the conflict note says taking master'spo/troutright is "the same rule every other language's merge already follows", but no other language does that: the other 30 all carry the regenerated msgid set andtris the only one left at master's. Either mergetrtoo (see inline) or drop the claim that this matches the other languages.5f2e9b5— the obsolete-entry counts are stale for the same reason:trnow has 0 obsolete entries, not 4, so the actual split is 16 languages on 0 and 12 on 4, not the 15 and 13 the message states.
Generated by Claude Code
Regenerates usteer.pot from the final usteer.js (207 live msgids) and merges it into every language's po file. Relative to master, the template drops four strings no longer used - "List of SSIDs to enable steering on" and "empty means all" (ssid_list's description is now one combined string with a different wrapping), "Refresh page to get new mac addresses to show up" (the Hearing map auto-refreshes live instead) and "default true" (syslog's Flag description was reworded) - and gains 60, among them the per-SSID field descriptions, the Known-stations UI text, "Enable"/"Disable" on the per-SSID tri-state fields (matching tools/network.js's convention), and the Defaults tab's title and its two descriptions (per-SSID-fallback wording when the daemon supports usteer_ssid, plain "usteer's settings" wording otherwise). The branch was rebased onto master's latest Weblate sync this round, which conflicted on po/tr (master's own Turkish update against this PR's reference-only change to the same lines) - resolved by taking master's copy of that file, then re-running the same msgmerge every language goes through against this commit's regenerated template, so tr ends up with the same 207-msgid set as everyone else instead of master's un-merged 151. Comparing every language's po file entry by entry against master's own copy: zero msgstr differ for any shared msgid, in any of the 31 languages - the long-running Polish-drift thread stays closed - and "Settings for this instance of usteer." (the Defaults tab's legacy-daemon description) remains translated only for Polish, same as any other string pending Weblate for the other 30 languages. Obsolete-entry counts differ per language, since msgmerge only keeps an obsolete entry where the removed msgid had a translation: 15 languages (az, be, bn_BD, da, fi, fr, hu, ja, nb_NO, nl, pt, pt_BR, ro, sk, vi) land on 0, 13 more on 4, it on 1, zh_Hant on 2, and pl on 6 - two more than its usual 4, for the now-obsolete plain "Signal" msgid the Known-stations fix merges into the msgctxt'd entry, and for "A value of 0 disables threshold" gaining the trailing period its two siblings and master's own copy already carry. po/pl carries 0 untranslated and 0 fuzzy entries across all 207 live msgids. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Grzegorz Kaczor <grzegorz914@icloud.com>
5f2e9b5 to
ee044e0
Compare
Summary
Companion LuCI frontend for openwrt/usteer#22 (per-SSID configuration overrides and known-station tracking with cold-start exploratory candidates).
usteer_ssidUCI section, mirroring the daemon's new per-SSID configuration overrides. The SSID list determines which tabs are shown live, without a page reload.delete_knownubus call, granted in the app's rpcd ACL) and a description of the cold-start "exploratory" placeholder semantics. Remote nodes' entries have no Delete button, since removing one only clears the local synced copy, not the owning peer's own record.config.band_steering_interval).Test plan
usteer_ssidUCI section, and fields fall back to the global setting when left blankUpdate
Extended the per-SSID tab with the remaining station/node-scoped policy fields that were still global-only:
sta_block_timeout,local_sta_timeout,max_retry_band,seen_policy_timeout,assoc_steering,probe_steering,max_neighbor_reports,load_balancing_threshold,steer_reject_timeout,roam_process_timeout,roam_kick_delay,initial_connect_delayandnode_up_script(moved from the global Settings tab, matching the daemon's extendedusteer_ssidoverrides).Also fixed a real bug found after the first round landed: the SSID tab nesting was only wired to the very first render -
Map.prototype.save()re-renders the map's content in place on every Save via the samerenderContents()used for the initial render, which silently undid the relocation (SSID tabs would jump back into the top-level tab bar after any Save). Fixed by wrappingrenderContents()itself instead of reacting only to the firstm.render()call, so relocation reruns on every render/Save/Reset.usteer_ssidUCI section, and fall back to the global setting when left blankUpdate 2
The bullet above about "improving" the existing global settings fields undersold what actually happened to them: all 35 moved to the per-SSID tab, and the global Settings tab no longer has them at all - it now only carries the whole-instance options (network, syslog, debug level, remote-sync tuning, SSID list, etc.).
That created a real gap: on a daemon that reads the new
usteer_ssidsections, the sharedusteersection's values (which the daemon still falls back to whenever a per-SSID field is left blank) had nowhere left to be edited or cleared from LuCI - only visible as a placeholder hint on each per-SSID field. Added a new Defaults tab, bound to the sharedusteersection, holding faithful copies of the same 35 fields in the exact order the per-SSID tab uses - so there's still a place to actually manage the fallback every SSID inherits from.Defaults nests first in the same sub-tab bar as the per-SSID tabs (under Settings) on a daemon with
usteer_ssidsupport, and per-SSIDValuefield placeholders now read that same shared value live (with its unit) instead of always showing usteer's compiled-in default regardless of what's actually configured. On a daemon withoutusteer_ssidsupport, Defaults stays a plain top-level tab instead - the per-SSID tabs never get created there, so its description says "usteer's settings" rather than talking about per-SSID fallbacks that don't exist on that build.usteersection, and per-SSID placeholders reflect a value set thereusteer_ssidisn't detected in the init script