Steven
Steven8 мин четене

Предизайн на dashboard-а около една-единствена вълнова диаграма

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

Инженерство
Дизайн
Dashboard
Издания на GeekBye
Предизайн на dashboard-а около една-единствена вълнова диаграма

Някои издания добавят функция. GeekBye v1.8.2 по-скоро премахна една — и премахването е историята. В един-единствен следобед през февруари 2026 осемнайсет комита превърнаха началния екран на dashboard-а от дистанционно за запис в аналитичен изглед само за четене: четири статистики и една диаграма за активност. По пътя достави bar chart, който живя двайсет и две минути, решетка от карти със статистики, която живя двайсет, и ръчно направена SVG вълна, която замени и двете. Цялото търсене е запазено във времевите маркери на комитите, което е най-добрият вид дизайнерска документация, който съществува.

Dashboard-ът престана да бъде дистанционно

Преди това издание началният екран на dashboard-а беше контролен панел. Започваше с hero карта — голям widget за запис с LIVE значка, бутони Pause/Resume/Stop, градиентни петна и hook useSessionState, който свързваше всичко това с рекордера. Dashboard-ът се опитваше да бъде две неща наведнъж: мястото, където гледаш срещите си, и мястото, откъдето управляваш рекордера. Два продукта, един екран, тихо съперничещи си.

v1.8.2 избра едно. Изтри hero картата и свързването useSessionState — включително ефект, който автоматично те навигираше към страницата с детайли на срещата в момента, в който сесията приключеше, точно този вид „услужлив" скок, който изненадва хората насред потока. Стартирането и скриването на рекордера се преместиха във обикновен navbar превключвател (преназначен бутон, който загуби около сто реда, минавайки от контролер на сесия към превключвател вкл/изкл), подпрян от нов navbar:hide IPC handler. Остана dashboard, който прави едно нещо: показва ти какво си записал. Само за четене. Спокоен.

В този преход има малък, човешки бъг, който заслужава да се спомене, защото е от този тип, който един предизайн въвежда тихо, а добро око улавя в същия час. Двата нови бутона в sidebar-а — Start и Hide — бяха доставени със същата обща grid икона, така че бяха визуално идентични. Дванайсет минути по-късно последващ комит даде на Start икона за play, даде на Hide икона за зачеркнато око и оцвети Hide в кехлибарено, така че „накарай приложението да изчезне" да се чете като преднамерено действие, а не като неутрален близнак на „start". Иконите са текст. Два бутона, които изглеждат еднакво, казват едно и също нещо, а тези не означаваха едно и също нещо.

Bar chart-ът, който живя двайсет и две минути

Ето частта, която обичам, и тя е напълно четима от git log-а. В 16:29:34 кацна първата чернова на предизайна: диаграма за активност за 7 дни, начертана като стълбчета — анимирани колони, минимална височина, за да останат видими малките дни, и затъмнено чуканче от 2 пиксела за дните с нула. Разумно. Конвенционално. Този вид диаграма, за която посягаш без да мислиш.

В 16:51:21 — двайсет и две минути по-късно — беше изтрита. Заменящият комит казва точно какво направи: „replace bar chart with smooth wave area chart for 7-day activity" (замени bar chart с гладка вълнова area диаграма за 7-дневната активност). А в 16:52:21, минута след това, друг комит махна заоблената карта и рамката около вълната, „for cleaner look" (за по-чист вид).

Защо? Комитите казват само какво се е променило, така че защо-то е тълкуване — но формата на данните го прави очевидно. Това е инструмент, в който типичен потребител има нула, една или две срещи в който и да е ден. Седем стълбчета, повечето високи 2 пиксела, изглеждат като почти пуст терен. Същите седем числа, начертани като непрекъсната запълнена area, изглеждат като тренд — нежна вълна, която се надига там, където седмицата е била натоварена. Нищо не беше фалшифицирано; стойностите по оста y са идентични. Предизайнът просто избра кодирането, което позволява на разредените, но честни данни да се четат като форма, вместо като отсъствие.

Статистиките получиха същото отношение по същия часовник. Първата чернова (16:29) сложи четири числа в 2×4 решетка от карти. В 16:49 решетката се сви в една inline лента със статистики — един ред с рамка, с тънки разделители, по-малък шрифт, един контейнер вместо четири. Пет кутии на екрана (четири карти плюс карта с диаграма) станаха две (лента и вълна). Следващият PR добави още един честен щрих: етикетът „Total Time" стана „Time in Meetings" (Време в срещи), защото общо-от-какво беше основателен въпрос, който никой не бива да е принуден да задава.

Двайсет минути, от първа чернова до финална, всичко в един pull request. Ако тези бяха squash-нати в един-единствен комит „redesign dashboard", търсенето щеше да е невидимо. Тъй като не бяха, можеш да наблюдаваш как един дизайнер конвергира в реално време.

Вълната, механично

Тук няма библиотека за диаграми. Вълната е inline SVG, построен в JSX, и заслужава поглед, защото е малка, честна рецепта, която можеш да откраднеш за всеки sparkline.

Изглаждането е трикът. За всяка двойка съседни точки пътят използва cubic-bezier сегмент, чиито две контролни точки седят в хоризонталната среда между тях — cpx = (prev.x + curr.x) / 2 — с контролните точки, задържани на собствената височина на всеки край. Това е класическото изглаждане с плоска допирателна: кривата минава плавно през всяка точка от данните, без някога да надскача над най-високата или под най-ниската стойност, което наивен Catmull-Rom spline би направил. За диаграма за броя на срещите, „никога не чертай изпъкналост, която подсказва стойност, която не се е случила" не е любезност; то е коректност. Запълнената area е същата крива, затворена по дъното и боядисана с вертикален градиент (cyan, избледняващ от 30% до почти нищо), а линията се изчертава сама с framer-motion pathLength анимация, отляво надясно.

Под SVG-то е водопроводът на данните, и той е тихият герой. Нов метод getAggregateStats() върху transcript repository-то изпълнява три prepared statements срещу локалната SQLite таблица transcript_sessions: всевремеви суми (брой, сумирана продължителност, средна продължителност), плъзгащ седемдневен брой и кофа по дни с GROUP BY date(created_at). После — и това е детайлът, който прави диаграмата издръжлива — малък JavaScript цикъл обхожда последните седем календарни дни и запълва (back-fill) всеки ден, който заявката не е върнала, добавяйки нула. Затова диаграмата е гарантирано с точно седем точки, винаги.

Тази гаранция е това, което кара граничните случаи да изчезнат, вместо да имат нужда от предпазители, разпръснати из изгледа. Празна седмица? Седем нули, а Math.max(count, 1) върху знаменателя държи линията плоска в дъното, вместо да дели на нула. Единствена точка от данните, която би накарала формулата за x-разстояние i / (n − 1) да произведе NaN? Не може да се случи — repository-то никога не издава по-малко от седем. Етикетите на дните дори парсват всяка кофа при T12:00:00, а не при гола полунощ, така че YYYY-MM-DD низ не се изплъзва в предишния ден в часова зона с отрицателен UTC. Поправи формата на данните при източника и рендиращият код може да бъде наивен нарочно.

Всичко остава на машината. Заявката за статистики чете локалната база данни, връща се през типизиран IPC канал transcript:get-stats и се анимира в четири нарастващи (count-up) числа при монтиране. Нищо от историята на срещите ти не напуска лаптопа, за да начертае тази диаграма — което, за инструмент, който записва разговорите ти, е единственият приемлив начин да се построи аналитичен изглед.

Още един бъг, защото предизайните ги измъкват на светло

Пакетиран в същото издание беше fix, който нямаше нищо общо с dashboard-а и всичко общо с вида дълг, в който се препъва един предизайн. Стилизирането на тъмния scrollbar на приложението беше отишло в две конкуриращи се CSS дефиниции на един и същи клас — по-стара лилава и по-нова бяло-на-тъмно — и коя печели зависеше от реда на каскадата. По-лошо, стилизирани изобщо бяха само елементите, които се сещаха да добавят класа; всичко останало се връщаше към светлия scrollbar по подразбиране, а хоризонталните scrollbar-и никога не бяха стилизирани, защото старите правила задаваха само ширина, никога височина. Fix-ът изтри и двете дефиниции, стилизира scrollbar-а глобално върху всеки елемент и премахна вече мъртвия клас от десетте компонента, които го носеха. Това е diff от два реда, повторен десет пъти — негламурният данък от това, че си стилизирал едно и също нещо два пъти и си оставил и двете да оцелеят.

Три неща, на които ни научи това издание

  1. Извади, за да фокусираш. Dashboard-ът стана по-добър, като правеше по-малко — губейки контролите за запис, от които никога не се нуждаеше, и ставайки едно ясно нещо. Екран, който е едновременно визуализатор и дистанционно, е два половин продукта; избери един и премести другия там, където му е мястото.
  2. Избери кодирането, което данните ти заслужават. Разредените броения се четат като отсъствие в стълбчета и като тренд в area chart, от идентични числа. Това не е разкрасяване — то е избирането на честната форма, която позволява на реалните, тънки данни да комуникират.
  3. Гарантирай формата на данните нагоре по веригата. Цикълът на запълване-до-седем е причината кодът на диаграмата да няма разпръснати null проверки: делението на нула, NaN от една точка и липсващите дни изчезват, защото заявката обещава точно седем кофи. Издръжливото рендиране започва един слой по-надолу.

За предишната глава от историята на v1 — четири издания за двайсет и шест часа (v1.7.6–v1.8.1); а за цялата дъга — анатомията на доставянето на софтуер до съвършенство.

Свързани статии

Login страницата Е демото
Steven
Steven6 мин четене

Login страницата Е демото

GeekBye v1.7.5 добави продуктов скрийншот на login страницата и го изтри същия ден — изграждайки го наново като истински компоненти. Плюс: потребителят, който беше по-бърз от OCR-а, и как всъщност изглеждат 25 стилови комита за един ден.

Инженерство
Дизайн
UX
Тишината беше носеща
Steven
Steven7 мин четене

Тишината беше носеща

Последните две издания на GeekBye v1 са за една и съща неудобна истина: транскрипцията в реално време през реална мрежа не е без загуби, а честният ход е да спреш да се преструваш, че е. v1.8.20 запази на диска копие на всеки аудио фрагмент, преди да го изхвърли по време на повторно свързване, и започна да маркира на глас пропуските в транскрипцията. v1.9.0 спря да изпраща тишина, за да пести честотна лента — и откри, че тишината беше точно сигналът, който транскрайбърът използваше, за да знае, че изречението е свършило. Две издания за цената на изхвърлянето на неща.

Инженерство
Audio
Надеждност
Три глагола, които поддържат Web Audio жив
Steven
Steven9 мин четене

Три глагола, които поддържат Web Audio жив

Две точкови издания на GeekBye, на два месеца разстояние и в два различни файла, научиха нашия аудио код на един и същ урок от противоположни краища: спри да третираш AudioContext на браузъра като за еднократна употреба. Едно издание се научи да прави resume() на контекст, който macOS тихо беше суспендирал по средата на записа; другото се научи да прави suspend() вместо close(), за да спрат последователните сесии да се блъскат в тавана на Chromium от приблизително шест контекста. Resume, suspend, close — това е целият сюжет.

Инженерство
Audio
Desktop