fix(charge): панель и меню берут порог заряда из прошивки (XIC-17) - #15
Merged
Conversation
Если порог менял кто-то снаружи (Xiaomi PC Manager, чужая утилита), быстрая панель продолжала показывать старое значение: она рисовала из конфига и прошивку не перечитывала вовсе. При этом клик по пилюле читал живое состояние — подпись говорила одно, поведение исходило из другого. AppController.SyncCareFromFirmware() читает GET 0x10/02 и приводит конфиг к прошивке (по docs/12 источник истины — она). Зовётся из QuickPanelForm.RefreshState() (до Show(), рядом с чтением режима и тачпада) и из TrayMenuBuilder при пересборке меню — фонового опроса не добавилось, читаем только когда UI открывают. Тонкости, без которых это ломается: - прошивка молчит (null) → конфиг не трогаем, лучше своё значение, чем ноль; - процент принимаем только валидным пресетом, чужой уровень вслепую не пишем; - 100 = «защита выключена», а не «порог 100» — выбранный X храним до включения; - при активном «В дорогу» не примиряем: там 100% держится намеренно, и сброс ChargeCare сломал бы режим; - CareChanged не дёргаем — это не действие пользователя, а подхват чужого, и при скрытой панели TrayApp показал бы на него OSD: всплывашка на каждое открытие; - конфиг пишем только при фактическом отличии. Заодно та же ошибка в меню трея: галочка считалась от живого значения, а процент в подписи брался из конфига, поэтому меню могло показать «беречь 60%» с галочкой при 50% в железе. Теперь панель и меню рисуют из конфига — он приведён к железу. Тултип трея сознательно оставлен как был: он живёт на 30-секундном опросе, и правдивость потребовала бы фонового WMI-вызова. Логика в командном слое, поэтому покрыта тестами на фейках: подхват уровня, выключение защиты снаружи, молчащая прошивка, «в дорогу», неизвестный уровень, отсутствие записи без отличий — плюс проверка, что OSD при подхвате не всплывает. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…eGuard Ревью первого коммита нашло дыру: EC читается как 100 и когда защиту выключили снаружи, и — транзиентно — после сна/смены питания. Лимит на этих событиях теряется, а ChargeGuard переармирует его с дебаунсом 1.5 с. Отличить случаи нельзя. Приняв 100, SyncCareFromFirmware сбрасывал ChargeCare в конфиге — а гард читает желаемый порог из конфига и разоружался навсегда: панель, открытая сразу после resume или выдёргивания зарядника (естественный жест «посмотреть на батарею»), молча убивала защиту до ручного включения. Правило сужено: принимаем только валидный порог < 100. Другой уровень EC сам не породит — это всегда чей-то осознанный SET, его принимать безопасно. Внешнее «выключить» не отражаем вовсе: гард по своей документированной задаче перебивает его на следующем событии питания, поэтому UI показывает намерение пользователя, а не мгновенное состояние EC (то же самое гард сделал бы с самим EC). Тест SyncCare_ProtectionOffOutside_KeepsChosenPercent заменён на SyncCare_Reads100_DoesNotDisarm (пиняет гонку), добавлен SyncCare_ExternalArming_IsAdopted (включение защиты снаружи принимается). docs/12 и CHANGELOG приведены к фактическому правилу; заодно секции Unreleased выровнены по порядку файла (Добавлено → Исправлено). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Подпись команды во вкладке «HTTP API» обещала «беречь ~80%», хотя с XIC-4 порог выбирается пользователем (40–80). Процент убран совсем, а не подставляется живым значением: строка описывает эндпоинт, а не текущую настройку, и тянуть сюда фактический порог значило бы держать ещё одно место, где он может разойтись. Формулировка выровнена по соседям (POST /mode — переключение режима). README RU/EN правки не требуют — там уже «настроенный порог». Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Те же устаревшие цифры, что и в описании POST /care, но в переназначении клавиш: «Заряд 80 / 100 %» в списке действий (все три языка) и «…всегда заряд 80/100» в подсказке к клавише с шестерёнкой (только ru — en/zh уже были без процента). Действие переименовано по образцу соседних тумблеров («Тачпад вкл/выкл»): «Лимит заряда вкл/выкл» / «Charge limit on/off» / «充电限制开关». Подсказка ru выровнена по en — «всегда переключает лимит заряда». После этого хардкода 80 в локализации не осталось ни в одном языке (grep чист): порог выбирается пользователем с XIC-4, и упоминать конкретное число в статике больше негде. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Те же устаревшие «80/100», что вычистили из локализации, жили и в README обоих языков — по пять мест в каждом. Порог выбирается пользователем с XIC-4, поэтому конкретное число в описании фич врёт всем, кто выбрал не 80: бейдж качества БП иконка показывает лимит 80/100 → текущий лимит заряда двойной клик Mi заряд 80/100 → переключение лимита заряда удержание Mi режимы + заряд 80/100 → режимы + лимит заряда «В дорогу» пилюли 80/100 → пилюли «порог/100» переназначение заряд 80/100 → лимит заряда вкл/выкл Legitimate-упоминания оставлены как есть: набор пресетов (40/50/60/70/80/100%), «В дорогу» до 100%, уровни подсветки клавиатуры, пример запоминания яркости, hex-статус 0x80 и «скажем, 80%» в туториале «В дорогу» — там процент явно подан примером («скажем»), и он помогает понять сценарий. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Если порог заряда менял кто-то снаружи (Xiaomi PC Manager, чужая утилита), наша быстрая панель продолжала показывать старое значение — она рисовала из конфига и прошивку не перечитывала вовсе. При этом клик по пилюле исходил из живого состояния: подпись говорила одно, поведение — другое.
Закрывает XIC-17.
Что сделано
AppController.SyncCareFromFirmware()— примирение конфига с прошивкой в командном слое. Зовётся изQuickPanelForm.RefreshState()(доShow(), рядом с существующими железными чтениями) и изTrayMenuBuilder.Build()при пересборке меню. Фонового опроса не добавилось — читаем только когда UI открывают; частота WMI-чтений не выросла (меню и раньше читалоGetChargeLimitна каждыйOpening).Заодно исправлена та же ошибка в меню, которой в issue не было: галочка считалась от живого значения, а процент в подписи брался из конфига — меню могло показать «беречь 60 %» с галочкой при 50 % в железе.
Правило примирения (важно)
Принимается только валидный порог < 100. Показание «100» не принимается — и это защита от найденной на ревью гонки:
EC теряет лимит после сна/смены питания, а
ChargeGuardпереармирует его с дебаунсом 1.5 с. В этом окне прошивка честно читается как 100 — неотличимо от внешнего «выключить». Приняв 100, мы сбросили быChargeCareв конфиге, а гард читает желаемый порог из конфига — то есть панель, открытая сразу после resume или выдёргивания зарядника, молча разоружала бы защиту навсегда.Другой валидный уровень EC самопроизвольно не породит — это всегда чей-то осознанный SET, его принимать безопасно. Внешнее «выключить» не отражаем вовсе: гард по своей документированной задаче перебивает его на следующем событии питания, поэтому UI показывает намерение пользователя, а не мгновенное состояние EC.
Остальные грани: прошивка молчит (
null) → конфиг не трогаем; при активном «В дорогу» примирение выключено (там 100 % держится намеренно, сбросChargeCareсломал бы режим);CareChangedне дёргается (иначе OSD-всплывашка на каждое открытие панели); конфиг пишется только при фактическом отличии.Проверка
Reads100_DoesNotDisarmпиняет гонку.AppController→ покрыта на фейках;QuickPanelFormостался тупым view._charge.Reapply()вStartup()синхронный и идёт доPrime()меню.Мелочь заодно
Вычищены устаревшие «80 %» из статических текстов: с XIC-4 порог выбирается пользователем, поэтому конкретное число в подписях врёт всем, кто выбрал не 80.
settings.api.cmd.care.descPOST /care — «беречь ~80%» вкл/выкл.POST /care — лимит заряда вкл/выкл.settings.act.chargeЗаряд 80 / 100 %Лимит заряда вкл/выклsettings.key.settings.desc…всегда заряд 80/100.…всегда переключает лимит заряда.Процент убран, а не подставляется живым значением: это описания эндпоинта и действия, а не индикаторы текущей настройки — тянуть туда фактический порог значило бы завести ещё одно место, где он может разойтись с железом. Названия выровнены по соседям (
Тачпад вкл/выкл),settings.key.settings.descв ru — по уже корректному en/zh.То же самое вычищено из README обоих языков — по пять мест в каждом: бейдж качества БП («иконка показывает лимит 80/100» → «текущий лимит заряда»), двойной клик Mi, удержание Mi, пилюли в разделе «В дорогу» («80/100» → «порог/100»), список действий переназначения.
Законные упоминания процентов оставлены: набор пресетов
40/50/60/70/80/100%, «В дорогу» до 100 %, уровни подсветки клавиатуры, пример запоминания яркости, hex-статус0x80и «скажем, 80 %» в туториале «В дорогу» (там процент явно подан примером и помогает понять сценарий). Таблица эндпоинтов правок не требовала — там уже «настроенный порог» / «the configured threshold».Вне скоупа
ToggleCharge(решение по живому чтению в момент клика) — не менялся.🤖 Generated with Claude Code