okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
f7fcae1
main
1// Package contracts is a dependency-free teaching fixture, not a UI framework. 2// Its state is owned by one event loop; it is deliberately not thread-safe. 3package contracts 4 5type phase uint8 6 7const ( 8idle phase = iota 9debouncing 10loading 11ready 12failed 13stopped 14) 15 16type searchState struct { 17generation uint64 18query string 19phase phase 20rows []string 21err error 22} 23 24// change records new intent now, before the debounce timer fires. This fixture 25// clears rows; an application may instead retain them with an explicit stale tag. 26// The real application must also cancel its superseded backend context. 27func (s * searchState )change (query string )uint64 { 28s .generation ++ 29s .query = query 30s .phase = debouncing 31s .rows = nil 32s .err = nil 33return s .generation 34} 35 36// begin admits one request for the current intent, rejecting stale or duplicate 37// debounce messages. A same-query retry must first create new intent with change. 38func (s * searchState )begin (generation uint64 )bool { 39if generation != s .generation || s .phase != debouncing { 40return false 41 } 42s .phase = loading 43return true 44} 45 46// finish transfers an immutable result to this state only while its request is 47// active. The producer must not mutate rows concurrently, even during this copy. 48func (s * searchState )finish (generation uint64 ,rows []string ,err error )bool { 49if generation != s .generation || s .phase != loading { 50return false 51 } 52if err != nil { 53s .phase = failed 54s .rows = nil 55s .err = err 56return true 57 } 58s .phase = ready 59s .rows = append ([]string (nil ),rows ... ) 60s .err = nil 61return true 62} 63 64// stop invalidates pending completions. It does not stop real I/O; the caller 65// must cancel and clean up the application's owned resources as well. 66func (s * searchState )stop () { 67s .generation ++ 68s .phase = stopped 69} 70 71// bodyRows handles nonnegative row allocation. compact is true when the caller 72// must use a different layout because the chrome does not fit. It does not 73// measure text or model Lip Gloss's box behavior. 74func bodyRows (total ,header ,footer int ) (rows int ,compact bool ) { 75total = max (0 ,total ) 76header = max (0 ,header ) 77footer = max (0 ,footer ) 78if header > total || footer > total - header { 79return 0 ,true 80 } 81return total - header - footer ,false 82}