list: ensure manager modify after shutdown does not crash

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
list: test manager modify after shutdown

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
async: never close updated channel

The update loop sometimes schedules an update over this output channel onto the worker
pool. This update races against the loader shutting down and closing its output channel
before the scheduled update does a send. This results in a panic from the scheduled goroutine
that is impossible for applications to gracefully handle. It's better for the updated channel
to stay open than for it to crash.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
example/kitchen{,/ui}: allow chats to start at oldest via a flag

This commit exposes a CLI flag to make chats start at the beginning
of the conversation instead of at the end. Having this flag may serve
as a useful reference for folks looking for this behavior.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
cddbe8d3 — vkoshelev 6 months ago
fix ScrollToEnd behavior
list: [hotfix] drop runtime.SetFinalizer

This commit removes the use of runtime.SetFinalizer from list.Manager.
I added it in order to try to ensure that the goroutine it spawns was
always cleaned up, but I didn't realize that doing so would break the
garbage collector's ability to GC the manager if any of the manager's
hook functions managed to create an import cycle (this is very easy to
do, as it's natural to provide methods on a type containing the manager
as hooks).

https://pkg.go.dev/runtime#SetFinalizer says:

If a cyclic structure includes a block with a finalizer, that cycle is
not guaranteed to be garbage collected and the finalizer is not guaranteed
to run, because there is no ordering that respects the dependencies.

This means we can't safely automate the destruction of that goroutine,
and must rely upon users to properly invoke Shutdown().

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
list: [API] drop Reset and enable clean shutdown

This commit provides a mechanism to explicitly and cleanly deallocate
the async resources servicing a Manager. This wasn't really compatible
with the Reset() concept, and I'm fairly certain that Reset() is a bad
idea anyway, so I removed that method at the same time.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
async: ensure update channel closes when loader shuts down

This commit updates the Loader so that goroutines selecting off of the Update()
channel cna shut down correctly.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
async: add shutdown option to end loader goroutine

This commit adds a simple Shutdown() mechanism to the Loader, enabling several
goroutines that power it to actually shut down after it is no longer needed.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
deps: update to latest gio and gio-x

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
ninepatch: fix test unit API usage

This commit updates the test cases for ninepatch support to use
the latest Gio unit API.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
list: fix manager tests from Gio list change

This commit updates the expectations of the list manager tests to match
changes in upstream Gio's implementation of layout.List. In particular,
layout.List now lays out elements before and after the visible elements.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
ci: add vulkan dependency

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
async: drop stale comment

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
async(loader): protect against init race

Originally the async.Loader was designed assuming that Update
and Schedule would be synchronized in a select.

This commit drops that assumption, allowing Updated to be called
in a concurrent goroutine by also performing lazy init in Updated.
The sync.Once provides all the synchronization we need.

Signed-off-by: Jack Mordaunt <jackmordaunt.dev@gmail.com>
list: provide a method to reuse list managers

This commit adds a method that resets a list manager's state for reuse.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
ninepatch,widget/plato: fix build error from px inset

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
all,deps: update to latest Gio unit API

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
debug: add helpers for constraint and size debugging

This commit adds some utilities for drawing thin rectangles at the
min/max of gtx constraints and at the returned size of a widget.
This helps enable visual layout debugging.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
list: fix stickiness on frequent state updates

This commit fixes a long-standing and subtle bug in the stickiness
implementation for the list. The way that stickiness works, when the
list.Manager receives a state update, it checks whether the element
at either end of the element list is visible. If it is, it concludes
that it should stick to that end. It calculates whether an element
is visible using the list.Position field of the list passed to
list.Manager.UpdatedLen, and it modifies this position to ensure
that an end is stuck to (if necessary).

The problem with this approach is that the manager can receive
more than one state update during a single frame (it recieves
a slice of them). The first state update could conclude that it
should stick to the end of the list, but the next iteration of the
processing loop would then be looking at the list.Position that
was partially modified by the previous iteration. Its own logic
to check whether an element was visible assumed that the
list.Position was totally valid and consistent, which was no
longer the case since it was altered by the previous loop
iteration. It could conclude that the list should not stick,
and thus the list would come unstuck from the end.

This commit addresses the problem by ensuring that if any of the
update iterations conclude that they should stick, they will
all make that stickiness decision for the frame from that
point forward, regardless of the state of the list.Position.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>