Steven
Steven6 хв читання

Одна CSS-змінна, п'ять раундів рев'ю та ланцюжок інструментів Swift, що збрехав

GeekBye v2.0.7 зробив увесь оверлей регульовано напівпрозорим — що звучить як однорядкова зміна CSS і абсолютно нею не було. Справжня історія — про те, що виловило код-рев'ю: дві поверхні, які відмовлялися згасати, панель запису, що виглядала неправильно за тієї самої прозорості, і скомпільований бінарник, який стрибнув на 672 байти, бо наша власна документація підказала рецензенту неправильну версію Swift.

Інженерія
Дизайн
Збірка
Релізи GeekBye
Одна CSS-змінна, п'ять раундів рев'ю та ланцюжок інструментів Swift, що збрехав

«Зробіть оверлей напівпрозорим» — це той тип задачі, що звучить як повзунок і CSS-властивість opacity. GeekBye v2.0.7 випустив рівно цей результат для користувача — єдиний регульований «світлий режим», що дозволяє бачити крізь панелі асистента те, що за ними. Але цікава частина цього релізу — не сама функція. Це п'ять раундів рев'ю, які знадобилися, щоб зробити її правильно, і фронтова історія про скомпільований бінарник, що змінив розмір, бо наша власна документація збрехала рецензентові.

Правильний спосіб зробити цілий інтерфейс напівпрозорим

Наївний варіант — розсипати значення прозорості по кожному компоненту-панелі й вважати справу зробленою. Це пастка супроводу: десяток зашитих значень, які розповзаються тієї ж миті, щойно хтось торкнеться одного.

Натомість v2.0.7 використовує одну спільну CSS-утиліту й токен для кожної поверхні. Є єдиний клас overlay-surface, який обчислює фон панелі з двох користувацьких властивостей: базової прозорості, яку кожна поверхня оголошує для себе (панель керування, чат, бульбашки транскрипту, блоки коду тощо — кожна обирає свою власну), і глобального множника альфи, що живе в корені оверлея й представляє налаштування повзунка користувача. Кожна поверхня читає той самий множник; кожна зберігає власний характер. Критично: масштабується лише фон панелі — текст, іконки й backdrop-blur лишаються повністю відмальованими, тож «напівпрозорий» ніколи не означає «нечитабельний».

Два рішення в цьому дизайні варто виокремити, бо саме вони — різниця між функцією, що допомагає, і тією, що породжує звернення до підтримки:

  • За замовчуванням оверлей повністю непрозорий. Налаштування прозорості постачається на рівні 100% — тобто нічого не робить. Ніхто не побачив, як його оверлей раптом став прозорим після оновлення; прозорість там, коли ви до неї потягнетеся, і невидима доти.
  • Налаштування валідується захисно. Є одне джерело правди для мінімуму, максимуму, значення за замовчуванням і кроку, а також нормалізатор, який захищає порожній/відсутній випадок. Це важливо через одну підступність JavaScript: Number(null) дорівнює 0, тож наївно приведене відсутнє налаштування миттєво перемкнуло б оверлей у найпрозоріший стан замість стану за замовчуванням. Нормалізатор ловить це, перш ніж воно станеться.

Потягніть повзунок — і весь оверлей перетонується наживо, посеред запису, бо кожна поверхня підписана на те саме налаштування. Без перезапуску, без перезавантаження.

Що виловило рев'ю (і чого тест на одному моніторі ніколи б не виловив)

Ось де «одна CSS-змінна» перестала бути простою. Три баги виринули на рев'ю, і два з них — той самий урок у різних масках.

Панель, яка не хотіла згасати. Оверлей клавіатурних скорочень уперто залишався щільним, поки все інше ставало напівпрозорим. Причина: він відмальовується поза піддеревом DOM, що несе змінну прозорості, тож ніколи не успадкував значення, що каскадувало вниз від кореня оверлея. Користувацькі CSS-властивості успадковуються через дерево DOM — і якщо вузол насправді не є нащадком того місця, де ви встановили змінну, він мовчки не отримує нічого. Виправлення — встановити змінну локально й на цій панелі теж.

Підсвітка при наведенні, яка зникла. Кнопки Fn/Assist втратили своє блакитне сяйво при наведенні. Утиліта прозорості встановлювала фон із !important (вона мусить перемагати типові значення поверхонь), і це переїхало фонову підсвітку hover: на тому самому елементі. Колізія специфічності. Виправлення — зробити підсвітку при наведенні так само наполегливою, щоб вона могла відвоювати перемогу при наведенні.

Обидва ці випадки — та сама глибинна істина: каскад CSS-змінної — це справжня межа коректності, а не деталь стилізації. Успадкування й специфічність вирішують, чи ваше значення взагалі досягне елемента, і жодне з них не проявиться на скріншоті, поки не стане помилковим.

Однакова прозорість, різний вигляд. Найтонший: панель запису й панель очікування були виставлені на ідентичну базову прозорість — і все одно виглядали помітно по-різному. Чому? Пігулка запису використовувала важче backdrop-blur, а сильне розмиття над темним фоном усереднюється в бік темнішого результату — тож однакова альфа дала неоднаковий вигляд. У неї також була ледь помітна межа там, де панель очікування мала яскраву кайму градієнтного кільця. Виправлення узгодило рівень розмиття й кільце. Урок закарбувався: однакова альфа — це не однаковий вигляд, щойно в гру входить розмиття. Прозорість — це система взаємодіючих ефектів, а не одне-єдине число.

Бінарник, що змінив розмір, бо документація збрехала

Тепер фронтова історія, і це мій улюблений жанр — той, де інструментарій і документація не збігаються, а сумлінний рецензент потрапляє під перехресний вогонь.

GeekBye постачає деякі попередньо скомпільовані бінарники Swift (нативні помічники для таких речей, як виявлення зустрічей). Оскільки скомпільований бінарник закомічено в репозиторій, кожен розробник мусить компілювати його з точно тією самою версією Swift — різні ланцюжки інструментів дають різні байти з ідентичного вихідного коду, а це означало б фантомний git-конфлікт щоразу, коли хтось перезбирає. Тож є скрипт, який застосовує одну конкретну версію: Swift 6.3.x, перевіряється під час збірки.

Під час рев'ю цього релізу рецензент зауважив, що бінарник слід перезібрати відповідно до «мандатованого репозиторієм ланцюжка інструментів». Розробник зробив саме це — і розмір бінарника змінився з 89,184 байтів на 88,512. Повідомлення коміту навіть казало, що це «відновлення байт-стабільного виводу» шляхом перезбирання з Swift 6.2.1, «мандатованим репозиторієм ланцюжком інструментів».

От тільки 6.2.1 була неправильною версією. Скрипт-регулятор збірки вимагав 6.3.x. Проблема була в тому, що текстова документація — README й посібник для контриб'юторів — усе ще казала 6.2.1 у кількох місцях. Тож сумлінний рецензент і сумлінний розробник, обидва прагнучи зробити правильно, пішли за документацією прямісінько до коміту саме того артефакту, який скрипт-регулятор існує, щоб відкидати. Бінарник 6.2.1 у репозиторії 6.3.x — це точно той дрейф, що зламав би чисту перезбірку кожному іншому розробнику.

Наступний коміт це виправив — і виправлення тут головне. Він не просто перезібрав бінарник назад до форми 6.3.x (розмір відновлено до 89,184, рівно туди, де все починалося). Він також виправив застарілі згадки «6.2.1» у документації, щоб пастку не можна було знову захряснути. Бінарник стрибнув на 672 байти й назад за два коміти, а справжній баг ніколи не був у бінарнику. Він був у тому, що два джерела правди — скрипт-регулятор і письмова документація — не збігалися, а людина довірилася не тому.

Три речі, яких навчив цей реліз

  1. Каскад CSS-змінної — це межа коректності. Два з трьох багів рев'ю зводилися до змінної, яка не успадкувалася, і !important, який збив стан наведення. Якщо значення мусить досягти елемента через успадкування або перемогти через специфічність, цей шлях — логіка; перевіряйте його як логіку, а не як стилізацію.
  2. Однакові параметри можуть давати неоднакові результати. Панель запису й панель очікування ділили прозорість і все одно виглядали по-різному, бо інше розмиття змінило результат. Коли ви уніфікуєте візуальну систему на одному числі, перевірте, що інші змінні навколо кожної поверхні не змінюють тихцем того, що це число означає.
  3. Коли документація й регулятор не збігаються, виправляйте розбіжність — а не лише симптом. Баг був не в поганому бінарнику; він був у документації, яка назвала неправильний ланцюжок інструментів, і скрипті-регуляторі, який казав інакше. Перезбирання бінарника лікує симптом. Узгодження кожного джерела правди — ось справжнє виправлення, бо наступний рецензент теж довіриться документації.

GeekBye v2.0.7 випустив однорідну прозорість — усі граничні випадки переглянуто, а документацію ланцюжка інструментів поставлено на місце. Це останній із релізів «тихого ремесла» перед спринтом надійності, що настав опісля. Про фундамент під ним див. чого насправді коштує друга версія (v2.0.0); про споріднений реліз шліфування — спокійне програмне забезпечення: виправлення мерехтіння й чип режиму відповідей (v2.0.3 + v2.0.5); а про те, як оверлей лишається прихованим під час дзвінка — як залишатися невидимим під час демонстрації екрана.

Схожі статті

Перепроєктування дашборда навколо одного хвильового графіка
Steven
Steven7 хв читання

Перепроєктування дашборда навколо одного хвильового графіка

GeekBye v1.8.2 перетворив дашборд із пульта керування записом на аналітичний вид тільки-для-читання — смуга статистики та 7-денний хвильовий графік. Обидва фірмові елементи були другими чернетками, випущеними протягом двадцяти хвилин після перших, того самого дня по обіді.

Інженерія
Дизайн
Дашборд
Сторінка логіна і Є демо
Steven
Steven6 хв читання

Сторінка логіна і Є демо

GeekBye v1.7.5 додав скриншот продукту на сторінку логіна й видалив його того ж дня — перезібравши натомість демо зі справжніх компонентів. Плюс: користувач, який виявився швидшим за OCR, і як насправді виглядають 25 стильових commitів за один день.

Інженерія
Дизайн
UX
Одна кодова база, два застосунки: як зробити white-label без форку
Steven
Steven5 хв читання

Одна кодова база, два застосунки: як зробити white-label без форку

GeekBye і Pavleur — це два по-різному брендовані десктопні застосунки, зібрані з одного репозиторію: без форку, без дубльованої кодової бази. Ось механіка часу збірки, яка перетворює одну кодову базу на два продукти, і однорядковий баг, через який наш другий застосунок представлявся неправильним іменем.

Інженерія
Архітектура
Збірка