
Зустрічі, які знову можна знайти: реліз із таймлайном
GeekBye v1.7.3 замінив дропдаун зустрічей справжнім таймлайном — людські дати, пошук, хлібні крихти, що кажуть, у якій зустрічі ти перебуваєш. А під капотом: гонка авто-вибору, скриншот, старший за власну зустріч, і п'ять фіксів для Windows за двадцять вісім хвилин.
До січня 2026 року в користувачів GeekBye з'явилася проблема з історією. Застосунок чудово записував і аналізував їхні зустрічі — а потім складав їх у дропдаун. Дропдаун годиться для трьох елементів. До п'ятнадцятої зустрічі «та співбесіда минулого вівторка» перетворювалася на археологічну експедицію крізь однакові на вигляд рядки. v1.7.3 — 64 commits між серединою грудня та 16 січня — це реліз, у якому зустрічі стали тим, що знову можна знайти.
(Одна бухгалтерська примітка, бо історія git чесна навіть тоді, коли номери версій — ні: тега релізу v1.7.2 не існує. Версію підняли, але наступним відвантаженим тегом став v1.7.3, тож фікси для Windows епохи v1.7.2 поїхали в цьому релізі.)
Від дропдауна до таймлайна
Головна зміна — один pull request: 12 файлів, +640 рядків, більшість із яких — новий 381-рядковий компонент MeetingsTimeline. Дропдаун став прокручуваним таймлайном карток зустрічей, згрупованих у чотири кошики — Today, Yesterday, This Week, Older (Сьогодні, Вчора, Цього тижня, Старіші) — з датами, відрендереними так, як їх вимовила б людина: Today, 2:30 PM, Yesterday, 2:30 PM, Mon, 2:30 PM для цього тижня та Jan 5, 2:30 PM далі. Cmd/Ctrl+K фокусує поле пошуку, що фільтрує за назвою. Детальний вигляд зустрічі став справжньою сторінкою навігації, тож кнопки «назад» і «вперед» у навбарі нарешті щось означають, а хлібні крихти перестали показувати «Meetings / Meeting» і почали показувати «Meetings / Interview with John» (обрізане трикрапкою, бо хтось завжди назве зустріч як роман).
Разом із цим приїхали дві маленькі приємності: кнопка видалення всередині вигляду зустрічі (яка після видалення повертає тебе на таймлайн, замість покинути на мертвій сторінці), і авто-навігація — коли сесія прослуховування завершується зі справжнім вмістом транскрипту, дашборд відкривається одразу на детальній сторінці цієї зустрічі. Завершуєш дзвінок — бачиш зустріч. Сесії, що завершилися порожніми, тихо видаляються, замість захаращувати таймлайн.
Гонка, яку створюєш, покращуючи навігацію
А ось частина, якої changelog тобі не розповість. Старий список зустрічей мав звичку: при кожному завантаженні він авто-вибирав найновішу сесію. Нешкідливо, доки список був дропдауном, якого ти рідко торкався. Смертельно тієї миті, коли зустрічі стали сторінкою, якою ти навігуєш: клікаєш зустріч #5, фоновий refetch завершується — і список послужливо вибирає найновішу зустріч, перезаписуючи вибір, який ти зробив дві секунди тому. Фіксом став не хитріший гард; фіксом стало повне видалення авто-вибору. Будь-який список, що вибирає щось від імені користувача, зрештою почне з ним битися.
Його видалення оголило другу гонку. Авто-навігація стрибає в зустріч у мить завершення її сесії — що може статися до того, як ця сесія закінчить запис у локальну базу SQLite. Навігуєш надто швидко — і прибуваєш у зустріч, якої ще не існує. Відвантажений фікс — 500-мілісекундна затримка перед завантаженням сесій при вході в детальний вигляд, а обробник навігації несе власні підстраховки — чекати did-finish-load вікна плюс 100ms, якщо дашборд щойно створили, 50ms, якщо він уже був відкритий. Наше прочитання: навігація по завершенні сесії перетинає три часові домени — запис у базу, завантаження вікна та монтування React — і кожен отримав свою маленьку затримку. Це працює, і ми скажемо прямо: стос магічних чисел — це чесний борг, а не перемога.
Скриншот, старший за власну зустріч
У цьому релізі померло ще одне припущення: «скриншоти належать сесії тоді й лише тоді, коли були зроблені під час неї». Бездоганно логічно. Хибно. Реальні користувачі тиснуть Cmd+H на вакансії, порядку денному, коді, який вони збираються обговорювати — до натискання Start. Вкладка Report зіставляла скриншоти з часовим діапазоном сесії строго, тож ці підготовчі скриншоти зникали зі звіту, заради якого їх зробили. Фікс розширив вікно зіставлення на 60 секунд до старту сесії. (Сама машинерія часових діапазонів старша — вона тихо приїхала у v1.6.15; внесок v1.7.3 — навчити її того, що зустрічі починаються трохи раніше, ніж починаються.)
П'ять фіксів за двадцять вісім хвилин
Бойова історія цього релізу взагалі не в таймлайні — вона в оверлеї онбордингу на Windows, і це хрестоматійний ланцюжок «лагодь фікс»: п'ять commitів між 10:50 та 11:18 одного й того самого ранку.
Головне вікно GeekBye використовує пропуск миші — хук, що перемикає Electron-івський setIgnoreMouseEvents при кожному русі миші, аби кліки провалювалися крізь прозорі області. Під час онбордингу на Windows цей хук воював з оверлеєм туторіалу, і на кроці, де з'являється вікно дашборда, застосунок замерзав. Фікс номер один: нехай хук нічого не робить, доки онбординг активний. Мир через роззброєння.
От тільки тепер кнопки онбордингу не відповідали, бо форвардинг подій відправляв кліки вікну дашборда під оверлеєм. Фікси два і три колупалися з forward: false для кожного майстра. Потім прийшов commit, який знайшов справжню першопричину: коли відкривається вікно дашборда, його обробник перетягування скидає головне вікно в режим наскрізних кліків — а перший фікс зробив хук пропуску пасивним, що означало: не лишилося нічого, що могло б виправити це втручання. Справжній фікс перевернув стратегію: хук тепер активно перестверджує setIgnoreMouseEvents(false) при кожному русі миші під час онбордингу — саме тому, що зовнішній код може скинути його будь-якої миті. Він також видалив 75 рядків раніших обхідних шляхів для кожного майстра.
І навіть тоді був п'ятий commit, бо виграти війну за ввід — не означає виграти війну за z-order: оверлей і дашборд сиділи на одному й тому самому рівні always-on-top, а Windows піднімає те вікно, яке отримує фокус. Оверлей переїхав на вищий рівень вікна й заново піднімає себе із затримкою після появи дашборда. Цю дугу варто запам'ятати: пасивний фікс, що роззброює твого єдиного захисника, гірший за початкову бійку.
Три речі, яких нас навчив цей реліз
- Апгрейди навігації виводять на світло баги стану. Гонка авто-вибору існувала до v1.7.3; дропдаун просто ніколи не давав її відчути. Тієї миті, коли зустрічі стали сторінкою, якою ти свідомо навігуєш, кожен шматок коду, що вибирав щось за тебе, став багом.
- Часовим межам навколо наміру користувача потрібен люфт. Сесії, записи, звіти — користувачі діють трохи раніше й трохи пізніше за офіційне вікно машини. 60-секундний буфер для скриншотів — один рядок, що відображає те, як люди поводяться насправді.
- Ніколи не роби свій корегувальний код пасивним. Зависання на Windows забрало п'ять фіксів, бо фікс номер один вимкнув єдиний механізм, здатний протидіяти зовнішньому втручанню. Якщо якийсь інший код може зламати твій інваріант будь-якої миті, твоя робота — перестверджувати його безперервно, а не відійти вбік.
Про попередній розділ історії v1 — як із цієї однієї кодової бази будуються два брендовані застосунки — дивись одна кодова база, два застосунки: як зробити white-label без форку (v1.7.1); а про всю дугу — анатомію доставки програмного забезпечення до досконалості.