detached ece7682

supervisor_navigation.go RawHistoryFolder

1package client
2
3import (
4	"github.com/bnema/vev/internal/ports"
5	"github.com/bnema/vev/internal/protocol"
6)
7
8// navigationState is the supervisor's run-goroutine navigation bookkeeping:
9// the adopted connection's publication wake, the swap and in-place choices
10// still waiting on a live attachment, and the client route ledger. It is only
11// touched from the run goroutine, so it has no mutex. The zero value is ready.
12type navigationState struct {
13	// readySub is the adopted connection's subscription while the ready phase
14	// runs, so the picker overlay over a live attachment keeps folding broker
15	// publications.
16	readySub ports.BrokerSubscription
17	// pendingSwap is the request the picker overlay or a daemon navigation
18	// committed to another target while an attachment was live. Consumed by
19	// settleAttachment.
20	pendingSwap *pickerAttachmentTarget
21	// pendingInPlace is the choice the live attachment is switching to in
22	// place on its own daemon. A refusal turns it into pendingSwap. Cleared
23	// when the attachment settles.
24	pendingInPlace *pendingInPlace
25	// inPlaceSeq numbers in-place choices so a late outcome for an older one
26	// is never applied to a newer one.
27	inPlaceSeq uint64
28	// routes is the client route ledger published to the serving daemon;
29	// routesSent is the attachment that received its latest snapshot.
30	routes     *routeLedger
31	routesSent AttachmentToken
32}
33
34// brokerChanged is the adopted connection's publication wake, or nil.
35func (n *navigationState) brokerChanged() <-chan struct{} {
36	if supervisorNil(n.readySub) {
37		return nil
38	}
39	return n.readySub.Changed()
40}
41
42// takeSwap returns and clears the committed swap target.
43func (n *navigationState) takeSwap() *pickerAttachmentTarget {
44	swap := n.pendingSwap
45	n.pendingSwap = nil
46	return swap
47}
48
49// switchingInPlaceTo reports whether an in-place switch to target is in flight.
50func (n *navigationState) switchingInPlaceTo(target protocol.ExactSessionTarget) bool {
51	return n.pendingInPlace != nil && n.pendingInPlace.target.request.Target == target
52}
53
54// inPlaceIdle reports whether no in-place switch is in flight.
55func (n *navigationState) inPlaceIdle() bool { return n.pendingInPlace == nil }
56
57// nextInPlaceSeq numbers one new in-place choice.
58func (n *navigationState) nextInPlaceSeq() uint64 {
59	n.inPlaceSeq++
60	return n.inPlaceSeq
61}
62
63// startInPlace records the in-place switch numbered seq as in flight.
64func (n *navigationState) startInPlace(seq uint64, target pickerAttachmentTarget) {
65	n.pendingInPlace = &pendingInPlace{seq: seq, target: target}
66}
67
68// clearInPlace forgets any in-place switch in flight.
69func (n *navigationState) clearInPlace() { n.pendingInPlace = nil }
70
71// takeInPlace returns and clears the in-flight in-place switch when it is the
72// one numbered seq; an outcome for an older choice returns nil and changes
73// nothing.
74func (n *navigationState) takeInPlace(seq uint64) *pendingInPlace {
75	pending := n.pendingInPlace
76	if pending == nil || pending.seq != seq {
77		return nil
78	}
79	n.pendingInPlace = nil
80	return pending
81}
82
83// buildRoutes rebuilds the route ledger over the broker snapshot, creating it
84// on first use.
85func (n *navigationState) buildRoutes(snapshot ports.BrokerSnapshot, active routeActive) (protocol.RecentRouteSnapshot, bool) {
86	if n.routes == nil {
87		n.routes = newRouteLedger()
88	}
89	return n.routes.build(snapshot, active)
90}
91
92// resolveRoute resolves one route reference against the ledger.
93func (n *navigationState) resolveRoute(ref protocol.RouteRef) (routeLedgerTarget, bool) {
94	if n.routes == nil || ref.IsZero() {
95		return routeLedgerTarget{}, false
96	}
97	return n.routes.resolve(ref)
98}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close