Ask HN: Was sind eurer Erfahrung nach solide Konventionen für die Entwicklung von E-Ink-Oberflächen?
Ask HN: In your experience, what are sound conventions for e-ink UI development?
Ich arbeite an einem Port von Excalidraw auf meinen ReMarkable Pro und habe festgestellt, wie sehr wir UI-Interaktionen für selbstverständlich halten, wenn wir von einem 30+Hz-Bildschirm ohne Ghosting ausgehen. Ich suche nach Konventionen für die Entwicklung von E-Ink-Oberflächen, insbesondere im Hinblick auf Layout-Stabilität, die Minimierung von Zwischenzuständen und den Umgang mit Ghosting und Latenz. Ich frage mich, wie man Interaktionen gestaltet, die bewusst und absichtlich wirken, und wie man mit kontinuierlichem Feedback wie Streaming-Text umgeht.
Wenn du es herausfindest, lass es mich wissen! Ich arbeite an einem Port von Excalidraw auf meinen ReMarkable Pro und es hat mir die Augen geöffnet, wie viel wir in Bezug auf UI-Interaktionen für selbstverständlich halten, wenn wir einen 30+Hz-Bildschirm mit minimalem Ghosting annehmen. Das Layout muss so monoton wie möglich werden, besonders ohne Benutzerinteraktion; mit anderen Worten, die App selbst sollte niemals etwas tun, das frühere Renderings stört, es sei denn, du leerst die gesamte Seite. Wenn der Benutzer mit der App interagiert, versuche, die Anzahl der Zwischenzustände zu minimieren, die seine Interaktionen erzeugen. Das bedeutet NICHT, diese Zwischenzustände einfach nicht zu rendern. Es bedeutet, dass die Interaktionen selbst kein Zwischenfeedback erfordern sollten. Im Wesentlichen sind Benutzer (und Entwickler) so daran gewöhnt, Dinge ohne Nebenwirkungen manipulieren zu können, dass du jede mögliche Interaktion so absichtlich wie möglich gestalten musst, damit sie weniger frustriert sind, wenn sie eine Aktualisierung sehen. Wenn eine Operation eine Aktualisierung verursacht, sollte sie in einem Moment passieren, den der Benutzer bereits als semantische Grenze versteht. Du kannst das natürlich nicht immer vermeiden, also verwende bei einer harten Anforderung für kontinuierliches Feedback eine abgespeckte/ billige transiente Darstellung und aktualisiere beim Abschluss dieser Aktion. Bei E-Ink ist jede Interaktion ein Kompromiss zwischen Ghosting und Latenz. Ein häufiges Muster, auf das ich immer wieder zurückkam, sind Zwischenzustände, die Latenz auf Kosten von Ghosting optimieren, bis die UI-Aktion 'abgeschlossen' ist. Dies erlaubt es, Aktualisierungen mit der Befriedigung der Endgültigkeit zu verbinden. Komischerweise erinnern viele an alte UI-Paradigmen aus der Zeit, als Computergrafiken nicht so leistungsfähig waren wie heute. Beim Größenändern zeichne ich einfach die Umrisse der Form mit einem schnellen Aktualisierungsmodus, der mehr Ghosting toleriert, bis der Benutzer Finger oder Stift loslässt. Zu diesem Zeitpunkt mache ich nach einer kleinen Verzögerung, um ein 'Ups, nur ein bisschen größer/kleiner' zu berücksichtigen, eine lokalisierte Aktualisierung der Vereinigung von altem und neuem Bereich. Der Umriss selbst ist bewusst blass, damit die Aktualisierung nicht so intensiv sein muss, wenn es ein kleines Delta ist.
Für deinen Fall mit Streaming-LLM würde ich empfehlen, es in Blöcken zu tun, wie du sagst, vielleicht einen harten Refresh von allem außer dem Eingabefeld zu machen und den Schwanz der letzten gesendeten Nachricht + den Anfang des Streams beim Senden nach oben zu verschieben. Natürlich bedeutet das, dass du genau weißt, wie lang die Antwort sein wird, was du nicht tust. Die Herausforderung wird sein, ein UI-Paradigma zu entwickeln, das nicht unangenehm aussieht, wenn die Antwort nur bis zur Mitte des Bildschirms geht, und gleichzeitig sauber vorbeugend zu aktualisieren, wenn klar ist, dass sie überläuft und nach oben verschoben werden muss. Für den ersten Fall finde einen Weg, bei dem es nicht völlig unangenehm aussieht, wenn es teilweise ist, und aktualisiere dann den Chatverlauf und verschiebe ihn an seine richtige Position, sobald der Benutzer auf das Eingabefeld klickt, um seine nächste Antwort zu tippen. Für den zweiten Fall könnte das Einbetten einer Art Restplatz-Anzeige am unteren Rand, die anzeigt, wann du diese Verschiebe- und Aktualisierungsaktion durchführen musst (beschrifte sie nicht direkt so), es dem Benutzer ermöglichen, es besser zu antizipieren und weniger frustriert zu sein, wenn es passiert, da er psychologisch auf den nächsten Teil der Antwort/Argumentation wartet, nicht überrascht von einem plötzlichen Blitz.
Für das eigentliche Streaming musst du sicherstellen, dass deine Textausrichtung so funktioniert, dass eine Zeile, sobald sie auf dem Bildschirm gerendert ist, in ihrer Position endgültig ist (mit anderen Worten, kein Streaming innerhalb eines Wortes, da du wissen musst, ob das Wort in den verbleibenden Platz in der Zeile passt, bevor du es renderst). Grundsätzlich vermeide nachträgliches Reflow wie bei einem PDF mit festem Layout, nicht wie dieses Textfeld, in das ich gerade tippe, mit einem Größenänderungsgriff unten rechts. Du solltest auch wahrscheinlich das Scrollen während der Generierung deaktivieren oder zumindest eine Art diskreten Paginierungsmechanismus zum Vor- und Zurückgehen einbauen.