Skip to content

Improve calendar view#70

Merged
monorkin merged 2 commits into
mainfrom
improve-calendar-view
Apr 7, 2026
Merged

Improve calendar view#70
monorkin merged 2 commits into
mainfrom
improve-calendar-view

Conversation

@monorkin
Copy link
Copy Markdown
Collaborator

@monorkin monorkin commented Apr 7, 2026

No description provided.

Copilot AI review requested due to automatic review settings April 7, 2026 10:18
@github-actions github-actions Bot added the enhancement New feature or request label Apr 7, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR upgrades the TUI calendar section from a simple recordings list to a richer, scrollable calendar UI with multiple display modes (Day/Week/Year) and user-aware week-start behavior.

Changes:

  • Add new calendar renderers (day/week/year) and a viewport-backed calendar display with a v key toggle.
  • Fetch identity to honor firstWeekDay, and expand Recording model support for named-day labels (Label) and completion markers.
  • Tweak the loading hourglass animation timing/frames.

Tip

If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
internal/tui/loading.go Adjusts hourglass flip timing and adds intermediate rotation frames.
internal/tui/content.go Removes the old calendar recordings list UI implementation.
internal/tui/calendar.go Switches calendar to viewport rendering, adds view mode toggling and identity-based first weekday.
internal/tui/calendar_views.go Introduces the Day/Week/Year rendering pipeline and supporting helpers.
internal/tui/calendar_test.go Updates tests for the new calendar state shape and view mode cycling.
internal/models/calendar.go Adds Recording.Label to support named-day labels in the calendar UI.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/tui/calendar_views.go Outdated
Comment on lines +807 to +819
if len(s) <= maxLen {
return s
}
if maxLen <= 1 {
return "…"
}
return s[:maxLen-1] + "…"
}

func centerPad(s string, width int) string {
pad := width - len(s)
if pad <= 0 {
return s[:width]
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

truncateStr truncates by byte length (len / s[:...]), which can split UTF-8 sequences and mis-measure terminal cell width (e.g., emoji/CJK), causing broken characters and misaligned layout. Consider truncating by runes or, better, by displayed width (e.g., using lipgloss.Width/runewidth) and ensuring you only cut at rune boundaries.

Suggested change
if len(s) <= maxLen {
return s
}
if maxLen <= 1 {
return "…"
}
return s[:maxLen-1] + "…"
}
func centerPad(s string, width int) string {
pad := width - len(s)
if pad <= 0 {
return s[:width]
if lipgloss.Width(s) <= maxLen {
return s
}
if maxLen <= 1 {
return "…"
}
runes := []rune(s)
for len(runes) > 0 && lipgloss.Width(string(runes))+lipgloss.Width("…") > maxLen {
runes = runes[:len(runes)-1]
}
return string(runes) + "…"
}
func centerPad(s string, width int) string {
pad := width - lipgloss.Width(s)
if pad <= 0 {
runes := []rune(s)
for len(runes) > 0 && lipgloss.Width(string(runes)) > width {
runes = runes[:len(runes)-1]
}
return string(runes)

Copilot uses AI. Check for mistakes.
Comment on lines +816 to +824
func centerPad(s string, width int) string {
pad := width - len(s)
if pad <= 0 {
return s[:width]
}
left := pad / 2
right := pad - left
return strings.Repeat(" ", left) + s + strings.Repeat(" ", right)
}
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

centerPad uses len(s) and slices s[:width], which is byte-based and can split multibyte UTF-8 characters; it also doesn't account for visual width (some runes take 2 cells). This can cause panics/garbled output and header misalignment; consider using rune-safe truncation and lipgloss.Width (or similar) when computing padding.

Copilot uses AI. Check for mistakes.
Comment thread internal/tui/loading.go Outdated
Comment on lines 94 to 103
{ // 8: 90° horizontal — sand on right
"╭─ ",
"│ ──╮ ",
"╰─ ⣠╭── ",
" ──╯ ⣾⣿⣿─╮",
" ╰──⣿│",
" ─╯",
},
{ // 8: 90° horizontal — sand on right
" ",
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Frame index comments in hourglassFrames are now inconsistent (multiple frames are labeled "8" after adding intermediate rotation frames). This makes it hard to reason about the animation and can lead to off-by-one mistakes when tweaking phases/indices; please renumber the frame comments to match the actual array indices (now 0–12).

Copilot uses AI. Check for mistakes.
Comment thread internal/tui/calendar.go
Comment on lines +259 to +264
identity, err := v.vc.sdk.Identity().GetIdentity(v.vc.ctx)
if err != nil || identity == nil {
return identityLoadedMsg{firstWeekDay: time.Monday}
}
return identityLoadedMsg{firstWeekDay: time.Weekday(identity.FirstWeekDay)}
}
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

identity.FirstWeekDay is cast directly to time.Weekday without validation. If the API ever returns an out-of-range value, downstream code (week calculations, labels) can behave unpredictably. Consider clamping/normalizing to 0–6 (or defaulting to Monday) before storing it in v.firstWeekDay.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 issues found across 6 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="internal/tui/calendar.go">

<violation number="1" location="internal/tui/calendar.go:69">
P2: Initial recordings can be fetched with the wrong week-start because identity loading races with data fetch, and identity updates do not trigger a corrective refetch.</violation>
</file>

<file name="internal/tui/loading.go">

<violation number="1" location="internal/tui/loading.go:94">
P2: Frame index comments are stale/inconsistent after expanding to 13 frames; multiple rotation frames are mislabeled as `// 8`, making frame-to-index mapping misleading.</violation>
</file>

<file name="internal/tui/calendar_views.go">

<violation number="1" location="internal/tui/calendar_views.go:807">
P2: truncateStr slices by byte length, which can cut multibyte UTF‑8 runes and render garbled characters. Use rune-aware truncation so event titles with non‑ASCII characters stay valid.</violation>

<violation number="2" location="internal/tui/calendar_views.go:816">
P2: `centerPad` uses byte-based `len(s)` for width measurement and `s[:width]` for truncation, which can slice through multi-byte UTF-8 sequences, causing a panic or garbled output. Use `lipgloss.Width(s)` for visual width and rune-safe truncation.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread internal/tui/calendar.go
}

func (v *calendarView) Init() tea.Cmd {
cmds := []tea.Cmd{v.fetchIdentity()}
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Initial recordings can be fetched with the wrong week-start because identity loading races with data fetch, and identity updates do not trigger a corrective refetch.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At internal/tui/calendar.go, line 69:

<comment>Initial recordings can be fetched with the wrong week-start because identity loading races with data fetch, and identity updates do not trigger a corrective refetch.</comment>

<file context>
@@ -44,24 +58,32 @@ type calendarView struct {
 }
 
 func (v *calendarView) Init() tea.Cmd {
+	cmds := []tea.Cmd{v.fetchIdentity()}
 	if len(v.calendars) == 0 {
 		v.loading = true
</file context>
Fix with Cubic

Comment thread internal/tui/loading.go Outdated
Comment thread internal/tui/calendar_views.go Outdated
Comment thread internal/tui/calendar_views.go
@monorkin monorkin merged commit 22aeea7 into main Apr 7, 2026
28 checks passed
@monorkin monorkin deleted the improve-calendar-view branch April 7, 2026 10:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants