Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions src/app/controller/preview-session.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package controller

import (
"sync/atomic"
"time"

"github.com/snivilised/jaywalk/src/agenor/core"
)

// PreviewSession is a lightweight session implementation for the tweak
// preview traversal. It implements core.Session but strips out all
// persistence, resume, and fault handling. Timing methods return zero
// values — they are not meaningful for a disposable preview session.
// Ctrl-C exits cleanly via context cancellation in the caller — no
// navigation state is saved.
type PreviewSession struct {
done atomic.Bool
}

// NewPreviewSession creates a PreviewSession with IsComplete() == false.
func NewPreviewSession() *PreviewSession {
return &PreviewSession{}
}

// IsComplete returns true when MarkComplete has been called.
func (s *PreviewSession) IsComplete() bool {
return s.done.Load()
}

// StartedAt returns the zero time. Not meaningful for preview sessions.
func (s *PreviewSession) StartedAt() time.Time {
return time.Time{}
}

// Elapsed returns 0. Not meaningful for preview sessions.
func (s *PreviewSession) Elapsed() time.Duration {
return 0
}

// MarkComplete sets the session as completed. Called by the tweak
// coordinator when a preview traversal finishes normally. On Ctrl-C
// the context cancels the traversal and MarkComplete is never called,
// so IsComplete remains false.
func (s *PreviewSession) MarkComplete() {
s.done.Store(true)
}

// compile-time check: *PreviewSession satisfies core.Session.
var _ core.Session = (*PreviewSession)(nil)
63 changes: 63 additions & 0 deletions src/app/controller/preview-session_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package controller_test

import (
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/snivilised/jaywalk/src/agenor/core"
jac "github.com/snivilised/jaywalk/src/app/controller"
)

var _ = Describe("PreviewSession", func() {
var session *jac.PreviewSession

BeforeEach(func() {
session = jac.NewPreviewSession()
})

Describe("NewPreviewSession", func() {
It("starts with IsComplete == false", func() {
Expect(session.IsComplete()).To(BeFalse())
})
})

Describe("MarkComplete", func() {
It("sets IsComplete to true", func() {
session.MarkComplete()
Expect(session.IsComplete()).To(BeTrue())
})

It("can be called multiple times (idempotent)", func() {
session.MarkComplete()
session.MarkComplete()
Expect(session.IsComplete()).To(BeTrue())
})
})

Describe("StartedAt", func() {
It("returns the zero time", func() {
Expect(session.StartedAt()).To(Equal(time.Time{}))
})
})

Describe("Elapsed", func() {
It("returns 0", func() {
Expect(session.Elapsed()).To(Equal(time.Duration(0)))
})
})

Describe("core.Session implementation", func() {
It("satisfies the core.Session interface", func() {
var s core.Session = session
Expect(s).NotTo(BeNil())
})

It("can be assigned to a core.Session variable", func() {
var s core.Session = session
Expect(s.IsComplete()).To(BeFalse())
session.MarkComplete()
Expect(s.IsComplete()).To(BeTrue())
})
})
})
9 changes: 9 additions & 0 deletions src/prism/contract/messages.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package contract

// ThemeUpdateMsg carries a freshly built Theme to the active view
// model. Sent by tweak whenever a working-state palette change occurs.
// Each view model's Update method gains a ThemeUpdateMsg case that
// stores the new theme. The next render uses it automatically.
type ThemeUpdateMsg struct {
Theme Theme
}
Loading