Steven
Steven6 min. skaitymo

Susitikimai, kuriuos tikrai galima vėl rasti: laiko juostos leidimas

GeekBye v1.7.3 pakeitė susitikimų išskleidžiamąjį sąrašą tikra laiko juosta — žmogiškos datos, paieška, naršymo kelias, sakantis, kuriame susitikime esi. O po paviršiumi: automatinio pasirinkimo lenktynės, ekrano nuotrauka, senesnė už savo pačios susitikimą, ir penkios Windows pataisos per dvidešimt aštuonias minutes.

Inžinerija
UX
Desktop
GeekBye leidimai
Susitikimai, kuriuos tikrai galima vėl rasti: laiko juostos leidimas

Iki 2026 metų sausio GeekBye naudotojai turėjo istorijos problemą. Programa jų susitikimus įrašinėjo ir analizavo puikiai — o paskui dėjo juos į išskleidžiamąjį sąrašą. Toks sąrašas tinka trims elementams. Ties penkioliktu susitikimu „tas pokalbis dėl darbo praėjusį antradienį" virsdavo archeologine ekspedicija per identiškai atrodančias eilutes. v1.7.3 — 64 commitai tarp gruodžio vidurio ir sausio 16 d. — yra leidimas, kuriame susitikimai tapo kažkuo, ką tikrai galima vėl rasti.

(Viena buhalterinė pastaba, nes git istorija sąžininga net tada, kai versijų numeriai — ne: leidimo žymos v1.7.2 nėra. Versija buvo pakelta, bet kita išsiųsta žyma buvo v1.7.3, todėl v1.7.2 eros Windows pataisos iškeliavo šiame leidime.)

Nuo išskleidžiamojo sąrašo iki laiko juostos

Pagrindinis pakeitimas — vienas pull request: 12 failų, +640 eilučių, dauguma jų — naujas 381 eilutės komponentas MeetingsTimeline. Išskleidžiamasis sąrašas tapo slenkama susitikimų kortelių laiko juosta, sugrupuota į keturias grupes — Today, Yesterday, This Week, Older (Šiandien, Vakar, Šią savaitę, Senesni) — su datomis, atvaizduotomis taip, kaip jas pasakytų žmogus: Today, 2:30 PM, Yesterday, 2:30 PM, Mon, 2:30 PM šiai savaitei ir Jan 5, 2:30 PM toliau. Cmd/Ctrl+K sufokusuoja paieškos lauką, filtruojantį pagal pavadinimą. Susitikimo detalių rodinys tapo tikru navigacijos puslapiu, todėl naršymo juostos mygtukai „atgal" ir „pirmyn" pagaliau kažką reiškia, o naršymo kelias nustojo rodyti „Meetings / Meeting" ir pradėjo rodyti „Meetings / Interview with John" (sutrumpintą daugtaškiu, nes kas nors visada pavadins susitikimą kaip romaną).

Kartu atkeliavo du smulkūs patogumo dalykai: trynimo mygtukas susitikimo rodinio viduje (kuris po trynimo grąžina tave į laiko juostą, užuot palikęs mirusiame puslapyje), ir automatinė navigacija — kai klausymo sesija baigiasi su tikru transkripto turiniu, valdymo skydelis atsidaro tiesiai tos susitikimo detalių puslapyje. Baigi skambutį — matai susitikimą. Tuščiai pasibaigusios sesijos tyliai ištrinamos, užuot šiukšlinusios laiko juostą.

Lenktynės, kurias susikuri gerindamas navigaciją

Štai dalis, kurios changelog tau nepapasakos. Senasis susitikimų sąrašas turėjo įprotį: kiekvieno įkėlimo metu jis automatiškai pasirinkdavo naujausią sesiją. Nekenksminga, kol sąrašas buvo išskleidžiamasis meniu, kurį retai liesdavai. Mirtina tą akimirką, kai susitikimai tapo puslapiu, kuriuo naviguoji: paspaudi susitikimą #5, fone užsibaigia refetch, ir sąrašas paslaugiai pasirenka naujausią susitikimą — perrašydamas pasirinkimą, kurį padarei prieš dvi sekundes. Pataisa buvo ne gudresnė apsauga; pataisa buvo visiškas automatinio pasirinkimo ištrynimas. Bet kuris sąrašas, kuris renkasi už naudotoją, galiausiai pradės su juo kovoti.

Jo pašalinimas atidengė antrąsias lenktynes. Automatinė navigacija šoka į susitikimą tą pačią akimirką, kai jo sesija baigiasi — o tai gali būti anksčiau, nei ta sesija baigė rašyti į lokalią SQLite duomenų bazę. Naviguok per greitai — ir atvyksi į susitikimą, kurio dar nėra. Išsiųsta pataisa — 500 milisekundžių delsa prieš įkeliant sesijas atvykus į detalių rodinį, o navigacijos tvarkyklė nešiojasi savas apsidraudimo priemones — laukti lango did-finish-load plius 100ms, jei valdymo skydelis buvo ką tik sukurtas, 50ms, jei jis jau buvo atidarytas. Mūsų perskaitymas: navigacija sesijai pasibaigus kerta tris laiko domenus — duomenų bazės įrašą, lango įkėlimą ir React montavimą — ir kiekvienas gavo po savo mažą delsą. Tai veikia, ir pasakysime tiesiai: magiškų skaičių krūva yra sąžininga skola, o ne pergalė.

Ekrano nuotrauka, senesnė už savo pačios susitikimą

Šiame leidime mirė dar viena prielaida: „ekrano nuotraukos priklauso sesijai tada ir tik tada, kai buvo padarytos jos metu". Tobulai logiška. Klaidinga. Tikri naudotojai spaudžia Cmd+H ant darbo skelbimo, darbotvarkės, kodo, kurį tuoj aptarinės — prieš paspausdami Start. Report skirtukas ekrano nuotraukas su sesijos laiko intervalu lygino griežtai, todėl tos pasiruošimo nuotraukos dingdavo iš ataskaitos, kuriai buvo padarytos. Pataisa praplėtė atitikimo langą 60 sekundžių prieš sesijos pradžią. (Pati laiko intervalų mašinerija senesnė — ji tyliai atkeliavo v1.6.15; v1.7.3 indėlis — išmokyti ją, kad susitikimai prasideda šiek tiek anksčiau, nei prasideda.)

Penkios pataisos per dvidešimt aštuonias minutes

Šio leidimo karo istorija apskritai ne laiko juostoje — ji Windows įvadinio proceso perdangoje, ir tai vadovėlinė grandinė „taisyk pataisą": penki commitai tarp 10:50 ir 11:18 tą patį rytą.

Pagrindinis GeekBye langas naudoja pelės praleidimą — hook, kuris kiekvieno pelės judesio metu perjungia Electron setIgnoreMouseEvents, kad paspaudimai prasmegtų pro permatomas sritis. Įvadinio proceso metu Windows sistemoje tas hook kovojo su mokomąja perdanga, ir žingsnyje, kuriame pasirodo valdymo skydelio langas, programa užstrigo. Pataisa numeris vienas: tegul hook nieko nedaro, kol įvadinis procesas aktyvus. Taika per nusiginklavimą.

Tik dabar įvadinio proceso mygtukai nebereagavo, nes įvykių persiuntimas siuntė paspaudimus valdymo skydelio langui po perdanga. Pataisos dvi ir trys krapštėsi su forward: false kiekvienam vedliui atskirai. Tada atėjo commit, kuris rado tikrąją pirminę priežastį: kai atsidaro valdymo skydelio langas, jo tempimo tvarkyklė atstato pagrindinį langą į prasmengančių paspaudimų režimą — o pirmoji pataisa pelės praleidimo hook buvo padariusi pasyvų, o tai reiškė, kad nebeliko nieko, kas galėtų ištaisyti kišimąsi. Tikroji pataisa apvertė strategiją: hook dabar įvadinio proceso metu aktyviai iš naujo įtvirtina setIgnoreMouseEvents(false) kiekvieno pelės judesio metu — būtent todėl, kad išorinis kodas gali jį atstatyti bet kada. Ji taip pat ištrynė 75 eilutes ankstesnių apėjimų, darytų kiekvienam vedliui atskirai.

Ir net tada buvo penktas commit, nes laimėti įvesties karą — dar ne laimėti z-order karą: perdanga ir valdymo skydelis sėdėjo tame pačiame always-on-top lygyje, o Windows iškelia tą langą, kuris gauna fokusą. Perdanga persikėlė į aukštesnį lango lygį ir po valdymo skydelio pasirodymo su delsa iš naujo iškelia save. Šią trajektoriją verta įsiminti: pasyvi pataisa, nuginkluojanti tavo vienintelį gynėją, yra blogesnė už pirminę kovą.

Trys dalykai, kurių mus išmokė šis leidimas

  1. Navigacijos patobulinimai iškelia būsenos klaidas. Automatinio pasirinkimo lenktynės egzistavo iki v1.7.3; išskleidžiamasis sąrašas tiesiog niekada neleido jų pajusti. Tą akimirką, kai susitikimai tapo puslapiu, kuriuo sąmoningai naviguoji, kiekvienas kodo gabalas, rinkęsis tave, tapo klaida.
  2. Laiko riboms aplink naudotojo ketinimą reikia laisvumo. Sesijos, įrašai, ataskaitos — naudotojai veikia šiek tiek anksčiau ir šiek tiek vėliau už oficialų mašinos langą. 60 sekundžių ekrano nuotraukų buferis yra viena eilutė, atspindinti, kaip žmonės elgiasi iš tikrųjų.
  3. Niekada nedaryk savo taisančiojo kodo pasyvaus. Windows užstrigimas pareikalavo penkių pataisų, nes pataisa numeris vienas išjungė vienintelį mechanizmą, galėjusį priešintis išoriniam kišimuisi. Jei koks nors kitas kodas gali bet kada sulaužyti tavo invariantą, tavo darbas — įtvirtinti jį nuolatos, o ne pasitraukti.

Ankstesniam v1 istorijos skyriui — dviejų prekės ženklu paženklintų programų kūrimui iš šios vienos kodo bazės — žr. viena kodo bazė, dvi programos: kaip kurti baltos etiketės produktą be šakojimo (v1.7.1); o visai istorijos linijai — programinės įrangos tobulybės pristatymo anatomiją.